postburner 0.8.0 → 1.0.0.pre.1
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/CHANGELOG.md +0 -22
- data/README.md +1219 -238
- data/Rakefile +1 -1
- data/app/concerns/postburner/callbacks.rb +286 -0
- data/app/models/postburner/job.rb +735 -46
- data/app/models/postburner/tracked_job.rb +83 -0
- data/bin/postburner +91 -0
- data/bin/rails +14 -0
- data/config/environment.rb +3 -0
- data/config/postburner.yml +22 -0
- data/config/postburner.yml.example +142 -0
- data/lib/postburner/active_job/adapter.rb +163 -0
- data/lib/postburner/active_job/execution.rb +109 -0
- data/lib/postburner/active_job/payload.rb +157 -0
- data/lib/postburner/beanstalkd.rb +97 -0
- data/lib/postburner/configuration.rb +202 -0
- data/lib/postburner/connection.rb +113 -0
- data/lib/postburner/engine.rb +1 -1
- data/lib/postburner/queue_config.rb +151 -0
- data/lib/postburner/strategies/immediate_test_queue.rb +133 -0
- data/lib/postburner/strategies/nice_queue.rb +85 -0
- data/lib/postburner/strategies/null_queue.rb +132 -0
- data/lib/postburner/strategies/queue.rb +119 -0
- data/lib/postburner/strategies/test_queue.rb +128 -0
- data/lib/postburner/time_helpers.rb +75 -0
- data/lib/postburner/tracked.rb +171 -0
- data/lib/postburner/version.rb +1 -1
- data/lib/postburner/workers/base.rb +210 -0
- data/lib/postburner/workers/worker.rb +480 -0
- data/lib/postburner.rb +433 -4
- metadata +66 -17
- data/lib/postburner/tube.rb +0 -53
data/lib/postburner.rb
CHANGED
|
@@ -1,17 +1,368 @@
|
|
|
1
1
|
require "postburner/version"
|
|
2
|
+
require "postburner/configuration"
|
|
3
|
+
require "postburner/connection"
|
|
4
|
+
require "postburner/queue_config"
|
|
5
|
+
require "postburner/beanstalkd"
|
|
6
|
+
require "postburner/tracked"
|
|
7
|
+
require "postburner/active_job/payload"
|
|
8
|
+
require "postburner/active_job/execution"
|
|
9
|
+
require "postburner/active_job/adapter"
|
|
10
|
+
require "postburner/workers/base"
|
|
11
|
+
require "postburner/workers/worker"
|
|
2
12
|
require "postburner/engine"
|
|
3
|
-
require "postburner/
|
|
13
|
+
require "postburner/strategies/queue"
|
|
14
|
+
require "postburner/strategies/nice_queue"
|
|
15
|
+
require "postburner/strategies/test_queue"
|
|
16
|
+
require "postburner/strategies/immediate_test_queue"
|
|
17
|
+
require "postburner/strategies/null_queue"
|
|
4
18
|
|
|
19
|
+
# Postburner - PostgreSQL-backed job queue system built on Backburner and Beanstalkd.
|
|
20
|
+
#
|
|
21
|
+
# Postburner is a Ruby on Rails Engine that provides a database-backed job queue with
|
|
22
|
+
# full audit trails, inspection capabilities, and multiple execution strategies. Every
|
|
23
|
+
# job is stored as an ActiveRecord model, enabling database queries, foreign key
|
|
24
|
+
# relationships, and comprehensive statistics tracking.
|
|
25
|
+
#
|
|
26
|
+
# ## Core Concepts
|
|
27
|
+
#
|
|
28
|
+
# - **Jobs:** Subclass {Postburner::Job} and implement `perform` method
|
|
29
|
+
# - **Queue Strategies:** Control how jobs are executed (async, inline, test modes)
|
|
30
|
+
# - **Beanstalkd Integration:** Production queuing via Backburner
|
|
31
|
+
# - **Database Persistence:** Full audit trail with timestamps, logs, and errors
|
|
32
|
+
# - **Callbacks:** ActiveJob-style lifecycle hooks (enqueue, attempt, processing, processed)
|
|
33
|
+
#
|
|
34
|
+
# ## Queue Strategies
|
|
35
|
+
#
|
|
36
|
+
# Postburner uses a strategy pattern to control job execution:
|
|
37
|
+
#
|
|
38
|
+
# - **{NiceQueue}** (default): Async via Beanstalkd, gracefully handles premature execution
|
|
39
|
+
# - **{Queue}**: Async via Beanstalkd, strict premature execution errors
|
|
40
|
+
# - **{TestQueue}**: Inline/synchronous, requires explicit time travel for scheduled jobs
|
|
41
|
+
# - **{ImmediateTestQueue}**: Inline/synchronous with automatic time travel
|
|
42
|
+
# - **{NullQueue}**: Creates jobs without queueing, manual execution with time travel
|
|
43
|
+
#
|
|
44
|
+
# ## Auto-Detection
|
|
45
|
+
#
|
|
46
|
+
# Postburner automatically detects Rails test mode and switches to {TestQueue} when:
|
|
47
|
+
# - `Rails.env.test?` is true
|
|
48
|
+
# - `ActiveJob::Base.queue_adapter_name == :test`
|
|
49
|
+
#
|
|
50
|
+
# ## Usage
|
|
51
|
+
#
|
|
52
|
+
# @example Creating and queueing a job
|
|
53
|
+
# class ProcessPayment < Postburner::Job
|
|
54
|
+
# queue 'critical'
|
|
55
|
+
# queue_priority 0
|
|
56
|
+
#
|
|
57
|
+
# def perform(args)
|
|
58
|
+
# payment = Payment.find(args['payment_id'])
|
|
59
|
+
# payment.process!
|
|
60
|
+
# log "Payment #{payment.id} processed"
|
|
61
|
+
# end
|
|
62
|
+
# end
|
|
63
|
+
#
|
|
64
|
+
# job = ProcessPayment.create!(args: { 'payment_id' => 123 })
|
|
65
|
+
# job.queue!(delay: 1.hour)
|
|
66
|
+
#
|
|
67
|
+
# @example Switching queue strategies
|
|
68
|
+
# # Production with graceful premature handling (default)
|
|
69
|
+
# Postburner.nice_async_strategy!
|
|
70
|
+
#
|
|
71
|
+
# # Production with strict premature errors
|
|
72
|
+
# Postburner.async_strategy!
|
|
73
|
+
#
|
|
74
|
+
# # Test mode with explicit time control
|
|
75
|
+
# Postburner.inline_test_strategy!
|
|
76
|
+
#
|
|
77
|
+
# # Test mode with automatic time travel
|
|
78
|
+
# Postburner.inline_immediate_test_strategy!
|
|
79
|
+
#
|
|
80
|
+
# @example Using Beanstalkd connection
|
|
81
|
+
# Postburner.connected do |conn|
|
|
82
|
+
# conn.tubes['my.tube'].stats
|
|
83
|
+
# conn.tubes['my.tube'].kick(3)
|
|
84
|
+
# end
|
|
85
|
+
#
|
|
86
|
+
# @example Checking if in test mode
|
|
87
|
+
# if Postburner.testing?
|
|
88
|
+
# # Jobs execute inline
|
|
89
|
+
# else
|
|
90
|
+
# # Jobs queued to Beanstalkd
|
|
91
|
+
# end
|
|
92
|
+
#
|
|
93
|
+
# @see Postburner::Job
|
|
94
|
+
# @see NiceQueue
|
|
95
|
+
# @see Queue
|
|
96
|
+
# @see TestQueue
|
|
97
|
+
# @see ImmediateTestQueue
|
|
98
|
+
#
|
|
5
99
|
module Postburner
|
|
100
|
+
# @!attribute [rw] queue_strategy
|
|
101
|
+
# The current queue strategy class used for job execution.
|
|
102
|
+
#
|
|
103
|
+
# Defaults to {NiceQueue} for production, auto-switches to {TestQueue}
|
|
104
|
+
# in Rails test environment.
|
|
105
|
+
#
|
|
106
|
+
# @return [Class] One of Queue, NiceQueue, TestQueue, or ImmediateTestQueue
|
|
107
|
+
#
|
|
108
|
+
# @example
|
|
109
|
+
# Postburner.queue_strategy
|
|
110
|
+
# # => Postburner::NiceQueue
|
|
111
|
+
#
|
|
112
|
+
# @see #nice_async_strategy!
|
|
113
|
+
# @see #async_strategy!
|
|
114
|
+
# @see #inline_test_strategy!
|
|
115
|
+
# @see #inline_immediate_test_strategy!
|
|
116
|
+
#
|
|
117
|
+
mattr_accessor :queue_strategy
|
|
6
118
|
|
|
119
|
+
# Initialize with NiceQueue (production) by default
|
|
120
|
+
# NiceQueue re-inserts premature jobs with appropriate delay
|
|
121
|
+
self.queue_strategy = Postburner::NiceQueue
|
|
122
|
+
|
|
123
|
+
# Auto-detect Rails test mode and switch to TestQueue
|
|
124
|
+
if defined?(Rails) && Rails.env.test? && defined?(ActiveJob::Base)
|
|
125
|
+
if ActiveJob::Base.queue_adapter_name == :test
|
|
126
|
+
self.queue_strategy = Postburner::TestQueue
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Activates strict test mode with inline job execution.
|
|
131
|
+
#
|
|
132
|
+
# Sets queue strategy to {TestQueue}, which executes jobs synchronously
|
|
133
|
+
# without Beanstalkd. Scheduled jobs (with future run_at) raise
|
|
134
|
+
# {Postburner::Job::PrematurePerform} exception, forcing explicit time
|
|
135
|
+
# management with `travel_to`.
|
|
136
|
+
#
|
|
137
|
+
# Use this strategy when you want explicit control over time progression
|
|
138
|
+
# in tests and want to catch scheduling bugs by failing loudly.
|
|
139
|
+
#
|
|
140
|
+
# @return [void]
|
|
141
|
+
#
|
|
142
|
+
# @example
|
|
143
|
+
# Postburner.inline_test_strategy!
|
|
144
|
+
# job = MyJob.create!(args: {})
|
|
145
|
+
# job.queue! # Executes immediately
|
|
146
|
+
# assert job.reload.processed_at
|
|
147
|
+
#
|
|
148
|
+
# @example With scheduled jobs
|
|
149
|
+
# Postburner.inline_test_strategy!
|
|
150
|
+
# job = MyJob.create!(args: {})
|
|
151
|
+
# job.queue!(delay: 1.hour)
|
|
152
|
+
# # Raises PrematurePerform - use travel_to instead
|
|
153
|
+
#
|
|
154
|
+
# @see TestQueue
|
|
155
|
+
# @see #inline_immediate_test_strategy!
|
|
156
|
+
#
|
|
157
|
+
def self.inline_test_strategy!
|
|
158
|
+
self.queue_strategy = Postburner::TestQueue
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Activates test mode with automatic time travel for scheduled jobs.
|
|
162
|
+
#
|
|
163
|
+
# Sets queue strategy to {ImmediateTestQueue}, which executes jobs
|
|
164
|
+
# synchronously and automatically uses time travel for jobs with future
|
|
165
|
+
# run_at timestamps.
|
|
166
|
+
#
|
|
167
|
+
# Use this strategy for integration/feature tests where you want
|
|
168
|
+
# convenience over explicit time control.
|
|
169
|
+
#
|
|
170
|
+
# @return [void]
|
|
171
|
+
#
|
|
172
|
+
# @example
|
|
173
|
+
# Postburner.inline_immediate_test_strategy!
|
|
174
|
+
# job = MyJob.create!(args: {})
|
|
175
|
+
# job.queue!(delay: 1.hour)
|
|
176
|
+
# # Automatically travels to scheduled time and executes
|
|
177
|
+
# assert job.reload.processed_at
|
|
178
|
+
#
|
|
179
|
+
# @note Jobs execute in queue order, not scheduled time order
|
|
180
|
+
# @note Requires ActiveSupport::Testing::TimeHelpers
|
|
181
|
+
#
|
|
182
|
+
# @see ImmediateTestQueue
|
|
183
|
+
# @see #inline_test_strategy!
|
|
184
|
+
#
|
|
185
|
+
def self.inline_immediate_test_strategy!
|
|
186
|
+
self.queue_strategy = Postburner::ImmediateTestQueue
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Activates strict production mode with asynchronous job execution.
|
|
190
|
+
#
|
|
191
|
+
# Sets queue strategy to {Queue}, which queues jobs to Beanstalkd and
|
|
192
|
+
# raises {Postburner::Job::PrematurePerform} if a job is executed before
|
|
193
|
+
# its scheduled run_at time.
|
|
194
|
+
#
|
|
195
|
+
# Use this strategy for production debugging or when you want strict
|
|
196
|
+
# enforcement of scheduling. For most production use cases, prefer
|
|
197
|
+
# {#nice_async_strategy!} instead.
|
|
198
|
+
#
|
|
199
|
+
# @return [void]
|
|
200
|
+
#
|
|
201
|
+
# @example
|
|
202
|
+
# Postburner.async_strategy!
|
|
203
|
+
# job = MyJob.create!(args: {})
|
|
204
|
+
# job.queue!(delay: 1.hour)
|
|
205
|
+
# # Queued to Beanstalkd, will raise if picked up early
|
|
206
|
+
#
|
|
207
|
+
# @note Requires Beanstalkd server running
|
|
208
|
+
# @note NOT the default production strategy
|
|
209
|
+
#
|
|
210
|
+
# @see Queue
|
|
211
|
+
# @see #nice_async_strategy!
|
|
212
|
+
#
|
|
213
|
+
def self.async_strategy!
|
|
214
|
+
self.queue_strategy = Postburner::Queue
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Activates default production mode with graceful premature handling.
|
|
218
|
+
#
|
|
219
|
+
# Sets queue strategy to {NiceQueue} (the default), which queues jobs to
|
|
220
|
+
# Beanstalkd and gracefully handles premature execution by re-inserting
|
|
221
|
+
# jobs with appropriate delay.
|
|
222
|
+
#
|
|
223
|
+
# This is the recommended production strategy and is set by default on
|
|
224
|
+
# initialization.
|
|
225
|
+
#
|
|
226
|
+
# @return [void]
|
|
227
|
+
#
|
|
228
|
+
# @example
|
|
229
|
+
# Postburner.nice_async_strategy!
|
|
230
|
+
# job = MyJob.create!(args: {})
|
|
231
|
+
# job.queue!(delay: 1.hour)
|
|
232
|
+
# # Queued to Beanstalkd, automatically re-inserted if picked up early
|
|
233
|
+
#
|
|
234
|
+
# @note This is the DEFAULT strategy
|
|
235
|
+
# @note Requires Beanstalkd server running
|
|
236
|
+
#
|
|
237
|
+
# @see NiceQueue
|
|
238
|
+
# @see #async_strategy!
|
|
239
|
+
#
|
|
240
|
+
def self.nice_async_strategy!
|
|
241
|
+
self.queue_strategy = Postburner::NiceQueue
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# Activates null mode for creating jobs without queueing to Beanstalkd.
|
|
245
|
+
#
|
|
246
|
+
# Sets queue strategy to {NullQueue}, which creates job records in the
|
|
247
|
+
# database but does NOT queue them to Beanstalkd. Jobs can be executed
|
|
248
|
+
# later by manually calling {NullQueue.handle_perform!}, which includes
|
|
249
|
+
# automatic time travel for scheduled jobs.
|
|
250
|
+
#
|
|
251
|
+
# Use this strategy for deferred batch processing, conditional execution,
|
|
252
|
+
# or scenarios where you want to create jobs in advance and execute them
|
|
253
|
+
# manually on-demand.
|
|
254
|
+
#
|
|
255
|
+
# @return [void]
|
|
256
|
+
#
|
|
257
|
+
# @example Create job without queueing
|
|
258
|
+
# Postburner.null_strategy!
|
|
259
|
+
# job = MyJob.create!(args: {})
|
|
260
|
+
# job.queue!
|
|
261
|
+
# # Job created but NOT queued to Beanstalkd
|
|
262
|
+
# job.bkid # => nil
|
|
263
|
+
#
|
|
264
|
+
# @example Manually execute later
|
|
265
|
+
# Postburner.null_strategy!
|
|
266
|
+
# job = MyJob.create!(args: {})
|
|
267
|
+
# job.queue!(delay: 1.hour)
|
|
268
|
+
# # Later, manually execute with automatic time travel
|
|
269
|
+
# Postburner::Job.perform(job.id)
|
|
270
|
+
# # Job executes as if it's 1 hour in the future
|
|
271
|
+
#
|
|
272
|
+
# @note Jobs execute when manually triggered via Postburner::Job.perform
|
|
273
|
+
# @note Does not require Beanstalkd to be running
|
|
274
|
+
# @note Useful for batch processing and deferred execution patterns
|
|
275
|
+
#
|
|
276
|
+
# @see NullQueue
|
|
277
|
+
# @see Postburner::Job.perform
|
|
278
|
+
#
|
|
279
|
+
def self.null_strategy!
|
|
280
|
+
self.queue_strategy = Postburner::NullQueue
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# Checks if currently using a test queue strategy.
|
|
284
|
+
#
|
|
285
|
+
# Returns true if the current queue strategy is {TestQueue} or
|
|
286
|
+
# {ImmediateTestQueue}, indicating that jobs execute inline/synchronously
|
|
287
|
+
# without Beanstalkd.
|
|
288
|
+
#
|
|
289
|
+
# @return [Boolean] true if using test strategy, false if using production strategy
|
|
290
|
+
#
|
|
291
|
+
# @example
|
|
292
|
+
# Postburner.nice_async_strategy!
|
|
293
|
+
# Postburner.testing? # => false
|
|
294
|
+
#
|
|
295
|
+
# Postburner.inline_test_strategy!
|
|
296
|
+
# Postburner.testing? # => true
|
|
297
|
+
#
|
|
298
|
+
# @see TestQueue
|
|
299
|
+
# @see ImmediateTestQueue
|
|
300
|
+
#
|
|
301
|
+
def self.testing?
|
|
302
|
+
queue_strategy.testing
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# Returns a cached Beanstalkd connection.
|
|
306
|
+
#
|
|
307
|
+
# Creates a new {Postburner::Connection} using the configured Beanstalkd
|
|
308
|
+
# URL and caches it. Automatically reconnects if the connection is stale.
|
|
309
|
+
#
|
|
310
|
+
# For most use cases, prefer {#connected} which handles connection cleanup.
|
|
311
|
+
#
|
|
312
|
+
# @return [Postburner::Connection] Beanstalkd connection object
|
|
313
|
+
#
|
|
314
|
+
# @raise [Beaneater::NotConnected] if connection fails
|
|
315
|
+
#
|
|
316
|
+
# @example
|
|
317
|
+
# conn = Postburner.connection
|
|
318
|
+
# conn.tubes['my.tube'].stats
|
|
319
|
+
#
|
|
320
|
+
# @note Connection is cached in @_connection instance variable
|
|
321
|
+
# @note Automatically reconnects if connection is not active
|
|
322
|
+
#
|
|
323
|
+
# @see #connected
|
|
324
|
+
#
|
|
7
325
|
def self.connection
|
|
8
|
-
@_connection ||=
|
|
9
|
-
Backburner.configuration.beanstalk_url
|
|
10
|
-
)
|
|
326
|
+
@_connection ||= Postburner::Connection.new
|
|
11
327
|
@_connection.reconnect! unless @_connection.connected?
|
|
12
328
|
@_connection
|
|
13
329
|
end
|
|
14
330
|
|
|
331
|
+
# Yields a Beanstalkd connection or returns cached connection.
|
|
332
|
+
#
|
|
333
|
+
# When called with a block, yields the connection and ensures it's closed
|
|
334
|
+
# after the block completes. When called without a block, returns the
|
|
335
|
+
# cached connection.
|
|
336
|
+
#
|
|
337
|
+
# @overload connected
|
|
338
|
+
# Returns the cached Beanstalkd connection.
|
|
339
|
+
# @return [Postburner::Connection] Beanstalkd connection
|
|
340
|
+
#
|
|
341
|
+
# @overload connected {|conn| ... }
|
|
342
|
+
# Yields connection and ensures cleanup.
|
|
343
|
+
# @yieldparam conn [Postburner::Connection] Beanstalkd connection
|
|
344
|
+
# @return [void]
|
|
345
|
+
#
|
|
346
|
+
# @example With block (recommended)
|
|
347
|
+
# Postburner.connected do |conn|
|
|
348
|
+
# conn.tubes.to_a.each do |tube|
|
|
349
|
+
# puts tube.name
|
|
350
|
+
# end
|
|
351
|
+
# end
|
|
352
|
+
# # Connection automatically closed
|
|
353
|
+
#
|
|
354
|
+
# @example Without block
|
|
355
|
+
# conn = Postburner.connected
|
|
356
|
+
# conn.tubes['my.tube'].stats
|
|
357
|
+
#
|
|
358
|
+
# @example Direct tube operations
|
|
359
|
+
# Postburner.connected do |conn|
|
|
360
|
+
# conn.tubes['critical'].kick(10)
|
|
361
|
+
# conn.tubes['background'].stats
|
|
362
|
+
# end
|
|
363
|
+
#
|
|
364
|
+
# @see #connection
|
|
365
|
+
#
|
|
15
366
|
def self.connected
|
|
16
367
|
if block_given?
|
|
17
368
|
begin
|
|
@@ -24,9 +375,87 @@ module Postburner
|
|
|
24
375
|
end
|
|
25
376
|
end
|
|
26
377
|
|
|
378
|
+
# Removes all jobs from all tubes (not yet implemented).
|
|
379
|
+
#
|
|
380
|
+
# This is a destructive operation intended for development/testing cleanup.
|
|
381
|
+
# Requires confirmation string "CONFIRM" to prevent accidental execution.
|
|
382
|
+
#
|
|
383
|
+
# @param confirm [String] Must be exactly "CONFIRM" to execute
|
|
384
|
+
#
|
|
385
|
+
# @return [void]
|
|
386
|
+
#
|
|
387
|
+
# @example
|
|
388
|
+
# Postburner.remove_all!("CONFIRM")
|
|
389
|
+
#
|
|
390
|
+
# @note Currently a no-op - implementation pending
|
|
391
|
+
# @todo Implement job removal from all tubes
|
|
392
|
+
#
|
|
27
393
|
def self.remove_all!(confirm)
|
|
28
394
|
return unless confirm == "CONFIRM"
|
|
29
395
|
|
|
30
396
|
# TODO
|
|
31
397
|
end
|
|
398
|
+
|
|
399
|
+
# Returns array of watched tube names with environment prefix.
|
|
400
|
+
#
|
|
401
|
+
# Expands configured queue names to full tube names and memoizes the result.
|
|
402
|
+
#
|
|
403
|
+
# @return [Array<String>] Array of expanded tube names
|
|
404
|
+
#
|
|
405
|
+
# @example
|
|
406
|
+
# Postburner.watched_tube_names
|
|
407
|
+
# # => ['postburner.production.default', 'postburner.production.critical']
|
|
408
|
+
#
|
|
409
|
+
def self.watched_tube_names
|
|
410
|
+
@__watched_tube_names ||= configuration.queue_names.map { |q| configuration.expand_tube_name(q) }
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
# Returns array of watched Beaneater::Tube instances.
|
|
414
|
+
#
|
|
415
|
+
# Creates Beaneater tube instances for all configured queues and memoizes the result.
|
|
416
|
+
#
|
|
417
|
+
# @return [Array<Beaneater::Tube>] Array of tube instances
|
|
418
|
+
#
|
|
419
|
+
# @example
|
|
420
|
+
# Postburner.watched_tubes.each { |tube| puts tube.stats }
|
|
421
|
+
#
|
|
422
|
+
def self.watched_tubes
|
|
423
|
+
@__watched_tubes ||= watched_tube_names.map { |tube_name| connection.tubes[tube_name] }
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
# Returns statistics and introspection data about Beanstalkd and configured queues.
|
|
427
|
+
#
|
|
428
|
+
# Provides Beaneater tube instances for configured tubes and all tubes that exist
|
|
429
|
+
# on the Beanstalkd server. Tube instances support introspection methods:
|
|
430
|
+
#
|
|
431
|
+
# - tube.name - Tube name
|
|
432
|
+
# - tube.stats - Tube statistics hash (current-jobs-ready, current-jobs-buried, etc.)
|
|
433
|
+
# - tube.peek_ready - Next ready job
|
|
434
|
+
# - tube.peek_delayed - Next delayed job
|
|
435
|
+
# - tube.peek_buried - Next buried job
|
|
436
|
+
# - tube.kick(n) - Kick n buried jobs back to ready
|
|
437
|
+
# - tube.pause(delay) - Pause tube for delay seconds
|
|
438
|
+
# - tube.clear - Delete all jobs in tube
|
|
439
|
+
#
|
|
440
|
+
# @return [Hash] Statistics hash with the following keys:
|
|
441
|
+
# - watched_tubes: Array of configured/watched Beaneater::Tube instances
|
|
442
|
+
# - tubes: Array of all Beaneater::Tube instances on the server
|
|
443
|
+
#
|
|
444
|
+
# @raise [Beaneater::NotConnected] if connection to Beanstalkd fails
|
|
445
|
+
#
|
|
446
|
+
# @example
|
|
447
|
+
# stats = Postburner.stats
|
|
448
|
+
# stats[:watched_tubes].each { |tube| puts "#{tube.name}: #{tube.stats}" }
|
|
449
|
+
# stats[:tubes].first.peek_ready
|
|
450
|
+
#
|
|
451
|
+
def self.stats
|
|
452
|
+
connected do |conn|
|
|
453
|
+
|
|
454
|
+
{
|
|
455
|
+
watched_tubes: self.watched_tubes,
|
|
456
|
+
# Get all tube instances that exist on Beanstalkd
|
|
457
|
+
tubes: conn.beanstalk.tubes.all
|
|
458
|
+
}
|
|
459
|
+
end
|
|
460
|
+
end
|
|
32
461
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: postburner
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0.pre.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Matt Smith
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: rails
|
|
@@ -16,28 +15,28 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - ">="
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
18
|
+
version: '7.2'
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
25
|
+
version: '7.2'
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
27
|
+
name: beaneater
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
30
29
|
requirements:
|
|
31
|
-
- - "
|
|
30
|
+
- - "~>"
|
|
32
31
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 1.
|
|
32
|
+
version: '1.0'
|
|
34
33
|
type: :runtime
|
|
35
34
|
prerelease: false
|
|
36
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
36
|
requirements:
|
|
38
|
-
- - "
|
|
37
|
+
- - "~>"
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 1.
|
|
39
|
+
version: '1.0'
|
|
41
40
|
- !ruby/object:Gem::Dependency
|
|
42
41
|
name: pg
|
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -52,6 +51,20 @@ dependencies:
|
|
|
52
51
|
- - ">="
|
|
53
52
|
- !ruby/object:Gem::Version
|
|
54
53
|
version: 1.2.3
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: ostruct
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: 0.6.0
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: 0.6.0
|
|
55
68
|
- !ruby/object:Gem::Dependency
|
|
56
69
|
name: haml-rails
|
|
57
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -66,10 +79,27 @@ dependencies:
|
|
|
66
79
|
- - ">="
|
|
67
80
|
- !ruby/object:Gem::Version
|
|
68
81
|
version: 2.0.1
|
|
69
|
-
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: concurrent-ruby
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '1.2'
|
|
89
|
+
type: :runtime
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '1.2'
|
|
96
|
+
description: 'Fast Beanstalkd-backed job queue with optional PostgreSQL audit trail.
|
|
97
|
+
Dual-mode execution: lite jobs (Beanstalkd only) or tracked jobs (full audit with
|
|
98
|
+
logs, timing, errors).'
|
|
70
99
|
email:
|
|
71
100
|
- matt@nearapogee.com
|
|
72
|
-
executables:
|
|
101
|
+
executables:
|
|
102
|
+
- postburner
|
|
73
103
|
extensions: []
|
|
74
104
|
extra_rdoc_files: []
|
|
75
105
|
files:
|
|
@@ -79,6 +109,7 @@ files:
|
|
|
79
109
|
- Rakefile
|
|
80
110
|
- app/assets/config/postburner_manifest.js
|
|
81
111
|
- app/assets/stylesheets/postburner/application.css
|
|
112
|
+
- app/concerns/postburner/callbacks.rb
|
|
82
113
|
- app/controllers/postburner/application_controller.rb
|
|
83
114
|
- app/controllers/postburner/jobs_controller.rb
|
|
84
115
|
- app/controllers/postburner/static_controller.rb
|
|
@@ -88,18 +119,38 @@ files:
|
|
|
88
119
|
- app/models/postburner/application_record.rb
|
|
89
120
|
- app/models/postburner/job.rb
|
|
90
121
|
- app/models/postburner/mailer.rb
|
|
122
|
+
- app/models/postburner/tracked_job.rb
|
|
91
123
|
- app/views/layouts/postburner/application.html.haml
|
|
92
124
|
- app/views/postburner/jobs/index.html.haml
|
|
93
125
|
- app/views/postburner/jobs/show.html.haml
|
|
126
|
+
- bin/postburner
|
|
127
|
+
- bin/rails
|
|
94
128
|
- config/environment.rb
|
|
129
|
+
- config/postburner.yml
|
|
130
|
+
- config/postburner.yml.example
|
|
95
131
|
- config/routes.rb
|
|
96
132
|
- lib/generators/postburner/install/USAGE
|
|
97
133
|
- lib/generators/postburner/install/install_generator.rb
|
|
98
134
|
- lib/generators/postburner/install/templates/migrations/create_postburner_jobs.rb.erb
|
|
99
135
|
- lib/postburner.rb
|
|
136
|
+
- lib/postburner/active_job/adapter.rb
|
|
137
|
+
- lib/postburner/active_job/execution.rb
|
|
138
|
+
- lib/postburner/active_job/payload.rb
|
|
139
|
+
- lib/postburner/beanstalkd.rb
|
|
140
|
+
- lib/postburner/configuration.rb
|
|
141
|
+
- lib/postburner/connection.rb
|
|
100
142
|
- lib/postburner/engine.rb
|
|
101
|
-
- lib/postburner/
|
|
143
|
+
- lib/postburner/queue_config.rb
|
|
144
|
+
- lib/postburner/strategies/immediate_test_queue.rb
|
|
145
|
+
- lib/postburner/strategies/nice_queue.rb
|
|
146
|
+
- lib/postburner/strategies/null_queue.rb
|
|
147
|
+
- lib/postburner/strategies/queue.rb
|
|
148
|
+
- lib/postburner/strategies/test_queue.rb
|
|
149
|
+
- lib/postburner/time_helpers.rb
|
|
150
|
+
- lib/postburner/tracked.rb
|
|
102
151
|
- lib/postburner/version.rb
|
|
152
|
+
- lib/postburner/workers/base.rb
|
|
153
|
+
- lib/postburner/workers/worker.rb
|
|
103
154
|
- lib/tasks/postburner_tasks.rake
|
|
104
155
|
homepage: https://gitlab.nearapogee.com/opensource/postburner
|
|
105
156
|
licenses:
|
|
@@ -108,7 +159,6 @@ metadata:
|
|
|
108
159
|
homepage_uri: https://gitlab.nearapogee.com/opensource/postburner
|
|
109
160
|
source_code_uri: https://gitlab.nearapogee.com/opensource/postburner
|
|
110
161
|
changelog_uri: https://gitlab.nearapogee.com/opensource/postburner/-/blob/master/CHANGELOG.md
|
|
111
|
-
post_install_message:
|
|
112
162
|
rdoc_options: []
|
|
113
163
|
require_paths:
|
|
114
164
|
- lib
|
|
@@ -123,8 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
123
173
|
- !ruby/object:Gem::Version
|
|
124
174
|
version: '0'
|
|
125
175
|
requirements: []
|
|
126
|
-
rubygems_version: 3.
|
|
127
|
-
signing_key:
|
|
176
|
+
rubygems_version: 3.6.9
|
|
128
177
|
specification_version: 4
|
|
129
|
-
summary:
|
|
178
|
+
summary: PostgreSQL-backed job queue with optional audit trail for ActiveJob
|
|
130
179
|
test_files: []
|
data/lib/postburner/tube.rb
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
module Postburner
|
|
2
|
-
class Tube
|
|
3
|
-
def initialize(tube)
|
|
4
|
-
@tube = tube
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
# Get all tubes as Postburner::Tube instances.
|
|
8
|
-
#
|
|
9
|
-
def self.all
|
|
10
|
-
Postburner.connection.tubes.all.map { |tube| self.new(tube) }
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# Get all peeked ids across all known tubes.
|
|
14
|
-
#
|
|
15
|
-
def self.peek_ids
|
|
16
|
-
self.all.map(&:peek_ids).flatten.sort
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Get all peeked ids.
|
|
20
|
-
#
|
|
21
|
-
def peek_ids
|
|
22
|
-
[ :buried, :ready, :delayed ].map { |type| @tube.peek(type) }.
|
|
23
|
-
reject(&:nil?).map(&:id).map(&:to_i)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Get paginated array of jobs.
|
|
27
|
-
#
|
|
28
|
-
# Attempts to do this efficiently as possible, by peeking at known
|
|
29
|
-
# ids and exiting when count has been fulfilled.
|
|
30
|
-
#
|
|
31
|
-
# Just pass the last known id to after for the next batch.
|
|
32
|
-
#
|
|
33
|
-
def jobs(count=20, limit: 1000, after: nil)
|
|
34
|
-
stats = @tube.stats
|
|
35
|
-
jobs = Array.new
|
|
36
|
-
|
|
37
|
-
min_known = (
|
|
38
|
-
peek_ids.any? ? self.peek_ids.min : self.class.peek_ids.min
|
|
39
|
-
).to_i
|
|
40
|
-
min = after ? after + 1 : min_known
|
|
41
|
-
max = min + limit
|
|
42
|
-
|
|
43
|
-
for i in min..max
|
|
44
|
-
job = @tube.client.jobs.find(i)
|
|
45
|
-
jobs << job if job && stats[:name] == job.stats[:tube]
|
|
46
|
-
break if jobs.length >= count
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
return jobs
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
end
|
|
53
|
-
end
|