postburner 1.0.0.pre.11 → 1.0.0.pre.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +961 -555
- data/app/concerns/postburner/commands.rb +1 -1
- data/app/concerns/postburner/execution.rb +11 -11
- data/app/concerns/postburner/insertion.rb +1 -1
- data/app/concerns/postburner/logging.rb +2 -2
- data/app/concerns/postburner/statistics.rb +1 -1
- data/app/models/postburner/job.rb +27 -4
- data/app/models/postburner/mailer.rb +1 -1
- data/app/models/postburner/schedule.rb +703 -0
- data/app/models/postburner/schedule_execution.rb +353 -0
- data/app/views/postburner/jobs/show.html.haml +3 -3
- data/lib/generators/postburner/install/install_generator.rb +1 -0
- data/lib/generators/postburner/install/templates/config/postburner.yml +15 -6
- data/lib/generators/postburner/install/templates/migrations/create_postburner_schedules.rb.erb +71 -0
- data/lib/postburner/active_job/adapter.rb +3 -3
- data/lib/postburner/active_job/payload.rb +5 -0
- data/lib/postburner/advisory_lock.rb +123 -0
- data/lib/postburner/configuration.rb +43 -7
- data/lib/postburner/connection.rb +7 -6
- data/lib/postburner/runner.rb +26 -3
- data/lib/postburner/scheduler.rb +427 -0
- data/lib/postburner/strategies/immediate_test_queue.rb +24 -7
- data/lib/postburner/strategies/nice_queue.rb +1 -1
- data/lib/postburner/strategies/null_queue.rb +2 -2
- data/lib/postburner/strategies/test_queue.rb +2 -2
- data/lib/postburner/time_helpers.rb +4 -2
- data/lib/postburner/tube.rb +9 -1
- data/lib/postburner/version.rb +1 -1
- data/lib/postburner/worker.rb +684 -0
- data/lib/postburner.rb +32 -13
- metadata +7 -3
- data/lib/postburner/workers/base.rb +0 -205
- data/lib/postburner/workers/worker.rb +0 -396
|
@@ -105,6 +105,10 @@ module Postburner
|
|
|
105
105
|
# is invoked. If the job has a future run_at, travels to that time before
|
|
106
106
|
# execution. Otherwise executes immediately.
|
|
107
107
|
#
|
|
108
|
+
# Uses recursion detection to prevent infinite loops when jobs create and
|
|
109
|
+
# enqueue other jobs (e.g., schedule callbacks). Jobs enqueued while already
|
|
110
|
+
# inside a perform! call are queued but not executed immediately.
|
|
111
|
+
#
|
|
108
112
|
# @param job [Postburner::Job] The job to execute
|
|
109
113
|
# @param options [Hash] Unused in test mode
|
|
110
114
|
#
|
|
@@ -115,17 +119,30 @@ module Postburner
|
|
|
115
119
|
# @api private
|
|
116
120
|
#
|
|
117
121
|
def insert(job, options = {})
|
|
118
|
-
#
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
# Detect recursion: if we're already performing a job, don't execute
|
|
123
|
+
# the newly enqueued job immediately. This prevents infinite loops
|
|
124
|
+
# when job callbacks (like schedule_next_execution) enqueue new jobs.
|
|
125
|
+
if Thread.current[:postburner_performing]
|
|
126
|
+
return { status: 'INLINE_DEFERRED', id: nil }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
begin
|
|
130
|
+
Thread.current[:postburner_performing] = true
|
|
131
|
+
|
|
132
|
+
# If job has a future run_at, travel to that time for execution
|
|
133
|
+
if job.run_at && job.run_at > Time.current
|
|
134
|
+
travel_to(job.run_at) do
|
|
135
|
+
job.perform!(job.args)
|
|
136
|
+
end
|
|
137
|
+
else
|
|
138
|
+
# No future run_at, execute normally
|
|
121
139
|
job.perform!(job.args)
|
|
122
140
|
end
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
job.perform!(job.args)
|
|
141
|
+
ensure
|
|
142
|
+
Thread.current[:postburner_performing] = false
|
|
126
143
|
end
|
|
127
144
|
|
|
128
|
-
# Return format matching
|
|
145
|
+
# Return format matching Beanstalkd response (symbol keys)
|
|
129
146
|
{ status: 'INLINE', id: nil }
|
|
130
147
|
end
|
|
131
148
|
end
|
|
@@ -77,7 +77,7 @@ module Postburner
|
|
|
77
77
|
# @note Logs "PREMATURE; RE-INSERTED" message to job's audit trail
|
|
78
78
|
#
|
|
79
79
|
def handle_premature_perform(job)
|
|
80
|
-
response = job.insert! delay: job.run_at - Time.
|
|
80
|
+
response = job.insert! delay: job.run_at - Time.current
|
|
81
81
|
job.log! "PREMATURE; RE-INSERTED: #{response}"
|
|
82
82
|
end
|
|
83
83
|
end
|
|
@@ -88,7 +88,7 @@ module Postburner
|
|
|
88
88
|
# @api private
|
|
89
89
|
#
|
|
90
90
|
def insert(job, options = {})
|
|
91
|
-
# Return format matching
|
|
91
|
+
# Return format matching Beanstalkd response (symbol keys)
|
|
92
92
|
{ status: 'NULL', id: nil }
|
|
93
93
|
end
|
|
94
94
|
|
|
@@ -118,7 +118,7 @@ module Postburner
|
|
|
118
118
|
# @api private
|
|
119
119
|
#
|
|
120
120
|
def handle_perform!(job)
|
|
121
|
-
if job.run_at && job.run_at > Time.
|
|
121
|
+
if job.run_at && job.run_at > Time.current
|
|
122
122
|
travel_to(job.run_at) do
|
|
123
123
|
job.perform!(job.args)
|
|
124
124
|
end
|
|
@@ -105,7 +105,7 @@ module Postburner
|
|
|
105
105
|
# Will raise PrematurePerform if run_at is in the future
|
|
106
106
|
job.perform!(job.args)
|
|
107
107
|
|
|
108
|
-
# Return format matching
|
|
108
|
+
# Return format matching Beanstalkd response (symbol keys)
|
|
109
109
|
{ status: 'INLINE', id: nil }
|
|
110
110
|
end
|
|
111
111
|
|
|
@@ -121,7 +121,7 @@ module Postburner
|
|
|
121
121
|
# @raise [Postburner::Job::PrematurePerform] Always raises with helpful message
|
|
122
122
|
#
|
|
123
123
|
def handle_premature_perform(job)
|
|
124
|
-
raise Postburner::Job::PrematurePerform, "Job scheduled for #{job.run_at} (#{((job.run_at - Time.
|
|
124
|
+
raise Postburner::Job::PrematurePerform, "Job scheduled for #{job.run_at} (#{((job.run_at - Time.current) / 60).round(1)} minutes from now). Use `travel_to(job.run_at)` in your test, or set `Postburner.inline_immediate_test_strategy!` to execute scheduled jobs immediately."
|
|
125
125
|
end
|
|
126
126
|
end
|
|
127
127
|
end
|
|
@@ -18,7 +18,8 @@ module Postburner
|
|
|
18
18
|
#
|
|
19
19
|
# travel_to(2.days.from_now) do
|
|
20
20
|
# # Code here executes as if it's 2 days in the future
|
|
21
|
-
# Time.
|
|
21
|
+
# Time.current # => 2 days from now (preferred in Rails)
|
|
22
|
+
# Time.zone.now # => 2 days from now (equivalent)
|
|
22
23
|
# end
|
|
23
24
|
#
|
|
24
25
|
# @example In a class method
|
|
@@ -54,7 +55,8 @@ module Postburner
|
|
|
54
55
|
#
|
|
55
56
|
# @example Travel to specific time
|
|
56
57
|
# travel_to(Time.zone.parse('2025-12-25 00:00:00')) do
|
|
57
|
-
# puts Time.
|
|
58
|
+
# puts Time.current # => 2025-12-25 00:00:00 (preferred)
|
|
59
|
+
# puts Time.zone.now # => 2025-12-25 00:00:00 (equivalent)
|
|
58
60
|
# end
|
|
59
61
|
#
|
|
60
62
|
# @example Travel relative to now
|
data/lib/postburner/tube.rb
CHANGED
|
@@ -31,7 +31,11 @@ module Postburner
|
|
|
31
31
|
# Just pass the last known id to after for the next batch.
|
|
32
32
|
#
|
|
33
33
|
def jobs(count=20, limit: 1000, after: nil)
|
|
34
|
+
# Access raw hash to avoid beaneater FastStruct method definition issues in Ruby 3.4
|
|
34
35
|
stats = @tube.stats
|
|
36
|
+
stats_hash = stats.instance_variable_get(:@hash) || {}
|
|
37
|
+
tube_name = stats_hash['name']
|
|
38
|
+
|
|
35
39
|
jobs = Array.new
|
|
36
40
|
|
|
37
41
|
min_known = (
|
|
@@ -42,7 +46,11 @@ module Postburner
|
|
|
42
46
|
|
|
43
47
|
for i in min..max
|
|
44
48
|
job = @tube.client.jobs.find(i)
|
|
45
|
-
|
|
49
|
+
if job
|
|
50
|
+
job_stats = job.stats
|
|
51
|
+
job_stats_hash = job_stats.instance_variable_get(:@hash) || {}
|
|
52
|
+
jobs << job if job_stats_hash['tube'] == tube_name
|
|
53
|
+
end
|
|
46
54
|
break if jobs.length >= count
|
|
47
55
|
end
|
|
48
56
|
|
data/lib/postburner/version.rb
CHANGED