同時に実行しても重複しないコレクションを取得するメソッドを提供する
Article モデルに対して処理を行う場合、
class Article < ActiveRecord::Base
include Ans::Publishable
scope :publishable, lambda{|args|
# 処理を実行するコレクションを返す
# article_publish_id is null の条件は自動で追加される
}
end
# Article に article_publish_id カラムを追加
# ArticlePublish モデルを追加
class ArticlePublish < ActiveRecord::Base
# カラムは id 以外は必要ない
end
# job
Article.publish(scope_params) do |article|
# article に対する何らかの処理
end
時間を置かずに実行されても、同じモデルに対して、二重に処理することがないように考慮している
- メールキューの処理 : 送信時刻が過去の、未送信のメールを送信する
- ポイントの追加 : 実行時刻が過去の、未処理のキューを処理してポイントを追加、メールの送信等を行う
メールの送信や、ポイントの追加など、二重処理すると困る場合
スケジューラーで処理を行なっている場合、機械の状態によって前の実行が終わらないうちに 次の実行が始まってしまう可能性があり、二重処理されてしまう
- ArticlePublish モデルにより、一意な
article_publish_idを生成 - Article の
article_publish_idに生成したidを設定 - その
idを持つ Article を順に取得して transaction を張りつつブロックを処理 - StandardError が発生した場合はそのレコードのみ transaction でロールバックされ、
publish_idを nil に戻す
publish メソッドにブロックを渡さなかった場合、生成した article_publish_id を持つ Article のリレーションが返される
Article の publishable を取得する場合、
Article.publishable(hash)が定義されていることArticlePublishでpublish_idを振り出すことArticle.article_publish_idにpublish_idを持つことArticlePublish.idをpublish_idとして扱うこと
publishable_scopeでメソッド名を返すことで、publishable以外のスコープを使用可能publish_modelでモデルクラスを返すことで、ArticlePublish以外のモデルを使用可能publish_foreign_keyでカラム名を返すことで、article_publish_id以外のカラムを使用可能publish_primary_keyでカラム名を返すことで、ArticlePublish.id以外のカラムを使用可能