开发者

Rails Asynchonous Processing in the Model

My rails app has a simple model Links which tracks all the Urls associated with an Update.

class Link
include Mongoid::Document
include Mongoid::Timestamps

field :url, type: String
field :domain, type: String
attr_accessible :url, :domain

validates_uniqueness_of :url

has_and_belongs_to_many :updates

before_create :longenate

But before I create the object I'd like to get rid of any ur开发者_高级运维l shortening, for various reasons like longevity of link, and overall just not liking shorteners.

Currently my longenate function is very naive (still deving, so its supposed to be :) ), and creates quite a bottleneck since it blocks during the request, which can be quite a while if quite a few updates are being created at a time, and usually its a few dozen being created. As the Updates/Links and so forth need to be displayed back to the user quickly, this is a problem.

    http_client = HTTPClient.new(:agent_name => "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)")
begin
    head_res = http_client.head(url)
    unless head_res.header['Location'].empty?
        short_url = url
        self.url = head_res.header['Location'][0]    
    end
rescue Exception => e
    self.domain = "ERROR ACCESSING URI"
    self.url = "Error Accessing URI, site down/non existant?"
end

I would like to swap this out for something non blocking. I am familiar with eventmachine, and have used it to create some simple services and consumers, but am still relatively new to rails. What would be the best rails approach for something like this? A "finalize" function that includes an event machine loop to lengthen/create all the Links at one time, or maybe doing (somehow) within the model so that it spins off an async task whenever one is created?

Thanks for any advice/resources


There are a couple of background processing frameworks (delayedjob, stalker, resque, etc).... Arguably the easiest to get started with with Delayed Job.

Once you have delayedjob installed (gem install plus a migration), then you can do things like:

class Link
  ..
  before_create :longenate
  def longenate
    # do your stuff
    self.save
  end
  handle_asychronously :longenate
end

Then you have workers do their work using rake jobs:work. This will take place in the background; with this implementation, you'll be saving records that have not been longenate'd, so you may want a 'status' field that tacks if it's been longenated or not.

More info: http://www.therailsway.com/2009/7/22/do-it-later-with-delayed-job

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜