1class Task < ActiveRecord::Base |
|
2 validates :name, presence: true, length: { maximum: 60 } |
|
4 class << self |
|
5 def run(name, period = 12.hours, &block) |
|
6 task_for(name).send(:run, period, &block) |
|
7 end |
|
9 private
|
|
|
11 def task_for(name) |
12 begin |
|
13 find_or_create_by!(name: name) |
|
14 rescue ActiveRecord::RecordNotUnique => e |
|
15 retry |
|
16 end |
|
17 end |
|
18 end |
|
20 private
|
|
|
22 def run(period = 12.hours, &block) |
23 retry_lock do |
|
24 if pending?(period) |
|
25 block.call
|
|
26 touch
|
|
27 end |
|
28 end |
|
29 end |
|
|
31 def pending?(period) |
32 created_at == updated_at || updated_at < period.ago
|
|
33 end |
|
|
35 def retry_lock |
36 retried = false |
|
38 begin |
|
39 with_lock { yield } |
|
40 rescue PG::InFailedSqlTransaction => e |
|
41 if retried |
|
42 raise e
|
|
43 else |
|
44 retried = true |
|
45 self.class.connection.clear_cache! |
|
46 retry |
|
47 end |
|
48 end |
|
49 end |
|
50end |