这应该转移到后台任务吗?

时间:2014-01-28 04:51:56

标签: ruby-on-rails

我有一个包含用户和工作的招聘系统。

他们之间存在着一种关系:通过潜力。

这基本上允许管理员了解用户适合工作的可能性

要做到这一点,我有一个after_create和一个after_save事件,如此 -

 class User < ActiveRecord::Base

  after_create :create_potentials
  after_save :set_potentials

  private
    def create_potentials
      Job.all.each do | job | 
        potential = Potential.new
        potential.job_id = job.id
        potential.user_id = self.id
        potential.save!
      end
    end

    def set_potentials
      self.potentials.each do |potential|
        potential.level = potential.find_potential
        potential.save!
      end
    end

这让我很担心。首先,我使用整个模型只是为了一个属性,“潜在”,这似乎有点古怪。

第二个是在创建用户之后,我正在为总工作量创建潜力。

目前,这些工作相对较少(即30岁以下),但这是很多潜在的计算任务。

after_create和after_save事件是否可以异步运行?

3 个答案:

答案 0 :(得分:1)

您可以使用像延迟作业这样的Gem来异步运行方法。

https://github.com/collectiveidea/delayed_job

正如您所说,优化问题的答案可能取决于可能存在多少工作,用户和“潜力”。正确的方法还取决于您是否需要使用SQL查询它们,或者是否可以动态计算它们。

通过关联创建潜力,可以略微缩短您当前的关联代码。如果您决定为每个Potential为每个User创建一个Job,则您需要使用find_each来避免一次将每个作业加载到内存中。

  Job.find_each { |job| job.potentials.create!(user_id: self.id) }

答案 1 :(得分:1)

考虑插入/更新逻辑的简单程度以及可能无法执行任何ruby方法,您可能需要考虑通过数据库显式执行此操作。

例如,您的create_potentials类似于:

insert into potentials select :user_id, id from jobs

其中:user_id作为查询参数传递,并以类似的方式处理set_potential(嵌套查询可能在update语句中)。

在某些时候,您可能希望将此逻辑移动到其中一个https://www.ruby-toolbox.com/categories/Background_Jobs中,或者如果逻辑变得复杂,甚至可以回退到在ruby中实现这两个简单方法,

但是现在最简单和最不适合的方法似乎只是使用SQL,跳过后台队列并让数据库处理这个。


此外,无论您采用哪种方式,如果您的项目启动,那么潜在的表看起来会像爆炸一样大小,所以请考虑您的作业架构在富文档模型中的适用程度(请参阅http://www.youtube.com/watch?v=PIWVFUtBV1Qhttp://railscasts.com/episodes/238-mongoid?view=asciicast

根据您的其他设置,您可能会发现它比传统数据库更适合您的需求

答案 2 :(得分:0)

根据您的Qsn,for every new user created. Entries are made into potential table for each job id along with the user_id.

更新用户条目potential level is being updated for all the potential table entries for that user which equals total no of jobs present.

如果您正在为用户寻找实时更新,则需要跳过cron部分并实现逻辑以减少查询次数。如果这不是限制那么 建议使用cron作业来处理它,使用redis / resque来处理after_create和after_save任务。创建或更新任何用户时,请执行任务,这些作业将由正在运行的redis服务器处理。

正如doctororange的回答中所建议的那样,如果您想定期处理任务而不管用户表的任何变化,也可以查看延迟的工作。