2017-01-11 6 views
0

EST/EDTのタイムゾーンに応じて月に1回請求書を生成する必要があります(クライアントは全国にありますが、この業界では同じタイムゾーンで請求が行われます)。毎月1回実行するための等価なジョブの作成方法(Rails 5)

  • 生成する請求書のみ:

    私がに関して任意の可能な重複/混乱がないように、請求書を生成するために、100%完璧な方法についての推論GenerateInvoicesJobが、私がいるトラブルを作成しています月

  • ごとに毎日ジョブを実行してみましょう一度
  • は私がいることをどのように確保するか、そして、仕事の冪等

私にとっては難しい1である最終地点くださいEST/DSTと1時間のスキップにバグはありません。ここで

は私clock.rbです:

every(1.day, 'GenerateInvoicesJob', tz: 'America/New_York', at: '04:00') do 
    Delayed::Job.enqueue GenerateInvoicesJob.new, queue: 'high' 
end 

そしてここでは、私の仕事のトップです:

Unit.where(enabled: true) 
    .joins(:user) 
    .where('last_invoice_generated_at <= ?', Time.now.utc.end_of_month) 
    .each do |unit| 

    ActiveRecord::Base.transaction do 
    unit.update_attributes(
     last_invoice_generated_at: Time.now.utc 
    ) 
    invoice = Invoice.create!(
     ... 
    ) 
    line_item = LineItem.create!(
     ... 
    ) 
    end 

私が直接、条件付きロジックが間違っているかもしれません実現するので、それは完全に私の質問はありません。 ..その質問への私の主な追加は全体的にこれを行うための最良の方法です。だから私は、ESTのすべての時間が100%が奇妙な1時間単位のバグなどを考慮していることを確認できます。重要なので、私はそれを完璧にする方法に躊躇しています。

私はデータベースにUTCを保存する必要があるかどうかはわかりません....通常、あなたはいつもUTCを保存するはずですが、UTCはDSTを持っていないことを知っていますので、私は労働者にこのような何かをするだろうというようにそれを保存し、ジョブは1時間と請求書を実行することができ、適切

答えて

0

を実行しないことになります。Time.nowとは異なるTime.currentがいかに

# `beginning_of_month` because we want to load units that haven't 
# been billed this month 
units_to_bill = Unit.where(enabled: true) 
    .where('last_invoice_generated_at < ?', Time.current.beginning_of_month) 

# `find_each` because it needs less memory 
units_to_bill.find_each do |unit| 

    # Beginn a transaction to ensure all or nothing is updated 
    Unit.transaction do 

    # reload the unit, because it might have been updated by another 
    # task in the meantime 
    unit.reload 

    # lock the current unit for updates 
    unit.lock! 

    # check if the condition is still true 
    if unit.last_invoice_generated_at < 1.month.ago 

     # generate invoices 
     # invoice = Invoice.create!(
     # line_item = LineItem.create!(

     # last step update unit 
     unit.update_attributes(
     last_invoice_generated_at: Time.current 
    ) 
    end 
    end 
end 
+0

うーん、 .utc(私のサーバーがUTCに設定されている場合、私はちょうど保存のために 'utc'をタックしていましたが、その必要はありません) – Tallboy

+0

また、トランザクションは自動的にレコードのロックを解除しますか?そのメソッドを使用して、偉大に見える – Tallboy

+1

'Time.current'は[優先される](http://stackoverflow.com/a/12748804/2483313)' Time.now'です。そして、はい、トランザクションの終わりはまた、ユニットのロックを解除します。 – spickermann