Ruby on Rails環境での非同期プログラミング
古いプロジェクトではruby 1.8.7が使われており、非常に古いバージョンでcoroutineなどの比較的新しい技術が使われていないため、プロジェクトで非同期のことをするのは非常に難しい.もちろん、最新バージョンのrubyであれば、これらは問題ではありません.ruby 1.8.7環境で非同期タスクを実行するには、2つの方法があります.ここでは簡単に覚えています.
1.delayed job、githubのオープンソースプロジェクトを使用して、https://github.com/tobi/delayed_jobコードコンテキストはデータベースに永続化され、再試行され、最大再試行回数を設定できます.
まずgemfileに依存を追加します:gem'delayed_job'
実装クラスを書くとperformメソッドが呼び出されます.タスクが実行されるとテーブルがロックされます.
Delayed::Job.enqueue LongJobs::GroupAlertJob.new(group_stuff, infos, [user.email])
これにより、タスクキューの挿入に相当するデータベースからレコードが挿入されます.
最後:
You can invoke rake jobs:work which will start working off jobs. You can cancel the rake task with CTRL-C.
2.第2の方法は、スクリプトを正直に書いたり、プロセスを常駐したり、crontabを実行したりすることです.例えばredis実装のキュー.
1つ目の方法はやはり便利で、書いた後、どんな非同期の場所でも使えます.1.8.7-head Rails 3.0.19このような古い環境はアップグレードされ、lib互換性の問題がたくさんあります.
1.delayed job、githubのオープンソースプロジェクトを使用して、https://github.com/tobi/delayed_jobコードコンテキストはデータベースに永続化され、再試行され、最大再試行回数を設定できます.
まずgemfileに依存を追加します:gem'delayed_job'
module LongJobs
require 'ooo/constants'
require 'xxx/handler'
#send group email alert
class GroupAlertJob < Struct.new(:content, :infos, :emails)
include Plusman
def before(job)
puts "#{job.id}============================#{Time.now}"
STDOUT.flush
end
def perform
実装クラスを書くとperformメソッドが呼び出されます.タスクが実行されるとテーブルがロックされます.
Delayed::Job.enqueue LongJobs::GroupAlertJob.new(group_stuff, infos, [user.email])
これにより、タスクキューの挿入に相当するデータベースからレコードが挿入されます.
最後:
You can invoke rake jobs:work which will start working off jobs. You can cancel the rake task with CTRL-C.
2.第2の方法は、スクリプトを正直に書いたり、プロセスを常駐したり、crontabを実行したりすることです.例えばredis実装のキュー.
require 'redis'
class GroupShare
include Plusman
REDIS_SHARE_KEY ='group:share:file'
REDIS_SHARE_FAILED_KEY ='group:share:file:failed'
def self.run
p "###### task begin ######"
p "time now:" + Time.now.to_s
if redis_is_usable? == false
p "redis server gone away."
p "time now:" + Time.now.to_s
end
loop do
value= redis.rpop(REDIS_SHARE_KEY)
if !value.blank?
data= JSON.parse(value) rescue {}
if data.blank?
p "JSON.parse error:" + value
end
group_id = data['group_id'].to_i
user_id = data['user_id'].to_i
bm_a = data['bm_a']
r= DHandler.share_items(group_id, user_id, bm_a, true)
if r.blank?
redis.lpush(REDIS_SHARE_FAILED_KEY, data)
end
p "sleep 3 seconds"
sleep(3)
end
end
end
def self.redis_is_usable?
redis.connected? rescue false
end
def self.save_data(data)
redis.lpush(REDIS_SHARE_KEY, data)
end
private
def self.redis
if !@redis
@redis = Redis.new(:host => DConfig::REDIS['active_user'][:host])
@redis.select(8)
p 'redis connected.'
end
@redis
end
end
1つ目の方法はやはり便利で、書いた後、どんな非同期の場所でも使えます.1.8.7-head Rails 3.0.19このような古い環境はアップグレードされ、lib互換性の問題がたくさんあります.