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'

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.第二种方式,老老实实地写一个脚本, 常驻进程或者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.8.7-head  Rails 3.0.19 这种老的环境要升级, 一大堆lib兼容问题。










你可能感兴趣的:(ruby,on,rails)