Module: Postburner
- Defined in:
- lib/postburner.rb,
lib/postburner/tube.rb,
lib/postburner/engine.rb,
lib/postburner/runner.rb,
lib/postburner/worker.rb,
lib/postburner/tracked.rb,
lib/postburner/version.rb,
lib/postburner/scheduler.rb,
app/models/postburner/job.rb,
lib/postburner/beanstalkd.rb,
lib/postburner/connection.rb,
lib/postburner/test_helpers.rb,
lib/postburner/time_helpers.rb,
app/models/postburner/mailer.rb,
lib/postburner/advisory_lock.rb,
lib/postburner/configuration.rb,
app/models/postburner/schedule.rb,
lib/postburner/instrumentation.rb,
app/concerns/postburner/logging.rb,
app/concerns/postburner/commands.rb,
app/concerns/postburner/callbacks.rb,
app/concerns/postburner/execution.rb,
app/concerns/postburner/insertion.rb,
app/models/postburner/tracked_job.rb,
lib/postburner/active_job/payload.rb,
app/concerns/postburner/properties.rb,
app/concerns/postburner/statistics.rb,
app/models/postburner/orphaned_job.rb,
app/jobs/postburner/application_job.rb,
lib/postburner/active_job/execution.rb,
lib/postburner/strategies/null_queue.rb,
lib/postburner/strategies/strict_queue.rb,
lib/postburner/strategies/default_queue.rb,
app/models/postburner/application_record.rb,
app/models/postburner/schedule_execution.rb,
app/helpers/postburner/application_helper.rb,
app/mailers/postburner/application_mailer.rb,
app/controllers/postburner/jobs_controller.rb,
lib/postburner/strategies/inline_test_queue.rb,
app/controllers/postburner/static_controller.rb,
lib/postburner/strategies/time_travel_test_queue.rb,
app/controllers/postburner/application_controller.rb
Overview
Postburner - PostgreSQL-backed job queue system built on Beanstalkd.
Postburner is a Ruby on Rails Engine that provides a database-backed job queue with full audit trails, inspection capabilities, and multiple execution strategies. Every job is stored as an ActiveRecord model, enabling database queries, foreign key relationships, and comprehensive statistics tracking.
## Core Concepts
-
Jobs: Subclass Job and implement ‘perform` method
-
**Queue Strategies:** Control how jobs are executed (async, inline, test modes)
-
**Beanstalkd Integration:** Production queuing via Beanstalkd
-
**Database Persistence:** Full audit trail with timestamps, logs, and errors
-
Callbacks: ActiveJob-style lifecycle hooks (enqueue, attempt, processing, processed)
## Queue Strategies
Postburner uses a strategy pattern to control job execution:
-
**DefaultQueue** (default): Async via Beanstalkd, gracefully handles premature execution
-
**StrictQueue**: Async via Beanstalkd, strict premature execution errors
-
**InlineTestQueue**: Inline/synchronous, requires explicit time travel for scheduled jobs
-
**TimeTravelTestQueue**: Inline/synchronous with automatic time travel
-
**NullQueue**: Creates jobs without queueing, manual execution with time travel
## Auto-Detection
Postburner automatically detects Rails test mode and switches to InlineTestQueue when:
-
‘Rails.env.test?` is true
-
‘ActiveJob::Base.queue_adapter_name == :test`
## Usage
Defined Under Namespace
Modules: ActiveJob, ApplicationHelper, Beanstalkd, Callbacks, Commands, Execution, Insertion, Instrumentation, Logging, Properties, Statistics, TestHelpers, TimeHelpers, Tracked Classes: AdvisoryLock, ApplicationController, ApplicationJob, ApplicationMailer, ApplicationRecord, Configuration, Connection, DefaultQueue, Engine, InlineTestQueue, InstallGenerator, Job, JobsController, Mailer, NullQueue, OrphanedJob, Runner, Schedule, ScheduleExecution, Scheduler, StaticController, StrictQueue, TimeTravelTestQueue, TrackedJob, Tube, Worker
Constant Summary collapse
- VERSION =
'1.0.0.rc.4'- TestQueue =
Backward compatibility alias
InlineTestQueue- ImmediateTestQueue =
Backward compatibility alias
TimeTravelTestQueue
Instance Attribute Summary collapse
-
#queue_strategy ⇒ Class
The current queue strategy class used for job execution.
Class Method Summary collapse
-
.clear_all!(silent: false) ⇒ Hash
Clears all configured tubes including scheduler.
-
.clear_jobs!(tube_names = nil, silent: false) ⇒ Hash
Clears jobs from specified tubes or shows stats for all tubes.
-
.configuration ⇒ Configuration
Returns the global configuration instance.
-
.configuration=(config) ⇒ Configuration
Sets the global configuration instance.
-
.configure {|config| ... } ⇒ void
Configures Postburner via block.
-
.connected ⇒ Object
Yields a Beanstalkd connection or returns cached connection.
-
.connection ⇒ Postburner::Connection
Returns a cached Beanstalkd connection.
-
.default_strategy! ⇒ void
Activates default production mode with graceful premature handling.
-
.disconnect_all! ⇒ void
Closes and clears Beanstalkd connections on all known threads.
-
.inline_test_strategy! ⇒ void
Activates strict test mode with inline job execution.
-
.null_strategy! ⇒ void
Activates null mode for creating jobs without queueing to Beanstalkd.
-
.scheduler_tube_name ⇒ String
Returns the scheduler tube name with environment prefix.
-
.stats(tube_names = nil) ⇒ Hash
Returns detailed statistics about Beanstalkd tubes.
-
.strict_strategy! ⇒ void
Activates strict production mode with asynchronous job execution.
-
.testing? ⇒ Boolean
Checks if currently using a test queue strategy.
-
.time_travel_test_strategy! ⇒ void
Activates test mode with automatic time travel for scheduled jobs.
-
.tube_prefix(env = nil) ⇒ String
Returns the Beanstalkd tube name prefix for the given environment.
-
.watched_tube_names ⇒ Array<String>
Returns array of watched tube names with environment prefix.
-
.watched_tubes ⇒ Array<Beaneater::Tube>
Returns array of watched Beaneater::Tube instances.
Instance Attribute Details
#queue_strategy ⇒ Class
The current queue strategy class used for job execution.
Defaults to DefaultQueue for production, auto-switches to InlineTestQueue in Rails test environment.
119 |
# File 'lib/postburner.rb', line 119 mattr_accessor :queue_strategy |
Class Method Details
.clear_all!(silent: false) ⇒ Hash
Clears all configured tubes including scheduler.
Convenience method that clears all watched tubes plus the scheduler tube in a single call. Use this to completely reset Postburner’s Beanstalkd state, such as during test setup or when recovering from a stuck state.
Equivalent to:
Postburner.clear_jobs!(Postburner.watched_tube_names + [Postburner.scheduler_tube_name])
484 485 486 487 |
# File 'lib/postburner.rb', line 484 def self.clear_all!(silent: false) all_tubes = watched_tube_names + [scheduler_tube_name] clear_jobs!(all_tubes, silent: silent) end |
.clear_jobs!(tube_names = nil, silent: false) ⇒ Hash
Clears jobs from specified tubes or shows stats for all tubes.
High-level method with formatted output. Delegates to Connection#clear_tubes! for the actual work, then pretty-prints the results.
SAFETY: Only allows clearing tubes that are defined in the loaded configuration. This prevents accidentally clearing tubes from other applications or environments sharing the same Beanstalkd server.
448 449 450 451 452 453 454 455 456 457 458 459 |
# File 'lib/postburner.rb', line 448 def self.clear_jobs!(tube_names = nil, silent: false) require 'json' tube_names = Array(tube_names) if tube_names result = connection.clear_tubes!(tube_names) unless silent puts JSON.pretty_generate(result) end result end |
.configuration ⇒ Configuration
Returns the global configuration instance.
276 277 278 |
# File 'lib/postburner/configuration.rb', line 276 def self.configuration @configuration ||= Configuration.new end |
.configuration=(config) ⇒ Configuration
Sets the global configuration instance.
285 286 287 |
# File 'lib/postburner/configuration.rb', line 285 def self.configuration=(config) @configuration = config end |
.configure {|config| ... } ⇒ void
This method returns an undefined value.
Configures Postburner via block.
302 303 304 |
# File 'lib/postburner/configuration.rb', line 302 def self.configure yield(configuration) end |
.connected ⇒ Postburner::Connection .connected({|conn| ... }) {|conn| ... } ⇒ Object
Yields a Beanstalkd connection or returns cached connection.
When called with a block, yields the thread-local connection. When called without a block, returns the thread-local connection.
368 369 370 371 372 373 374 |
# File 'lib/postburner.rb', line 368 def self.connected if block_given? yield connection else connection end end |
.connection ⇒ Postburner::Connection
Connection is cached in Thread.current (thread-local)
Automatically reconnects if connection is not active
Returns a cached Beanstalkd connection.
Creates a new Connection using the configured Beanstalkd URL and caches it. Automatically reconnects if the connection is stale.
For most use cases, prefer #connected which handles connection cleanup.
327 328 329 330 331 332 |
# File 'lib/postburner.rb', line 327 def self.connection Thread.current[:postburner_connection] ||= Postburner::Connection.new conn = Thread.current[:postburner_connection] conn.reconnect! unless conn.connected? conn end |
.default_strategy! ⇒ void
This is the DEFAULT strategy
Requires Beanstalkd server running
This method returns an undefined value.
Activates default production mode with graceful premature handling.
Sets queue strategy to DefaultQueue (the default), which queues jobs to Beanstalkd and gracefully handles premature execution by re-inserting jobs with appropriate delay.
This is the recommended production strategy and is set by default on initialization.
242 243 244 |
# File 'lib/postburner.rb', line 242 def self.default_strategy! self.queue_strategy = Postburner::DefaultQueue end |
.disconnect_all! ⇒ void
This method returns an undefined value.
Closes and clears Beanstalkd connections on all known threads.
Call this on worker shutdown to release sockets cleanly. Because connections are thread-local, a single ‘connection.close` call from the main thread would only close that thread’s socket. This method iterates every live thread and closes each thread’s connection, if any.
390 391 392 393 394 395 396 397 398 399 400 401 402 |
# File 'lib/postburner.rb', line 390 def self.disconnect_all! Thread.list.each do |thread| if (conn = thread[:postburner_connection]) begin conn.close if conn.respond_to?(:close) && conn.connected? rescue => e warn "Postburner: failed to close connection on shutdown: #{e.}" if $VERBOSE ensure thread[:postburner_connection] = nil end end end end |
.inline_test_strategy! ⇒ void
This method returns an undefined value.
Activates strict test mode with inline job execution.
Sets queue strategy to InlineTestQueue, which executes jobs synchronously without Beanstalkd. Scheduled jobs (with future run_at) raise Postburner::Job::PrematurePerform exception, forcing explicit time management with ‘travel_to`.
Use this strategy when you want explicit control over time progression in tests and want to catch scheduling bugs by failing loudly.
159 160 161 |
# File 'lib/postburner.rb', line 159 def self.inline_test_strategy! self.queue_strategy = Postburner::InlineTestQueue end |
.null_strategy! ⇒ void
Jobs execute when manually triggered via Postburner::Job.perform
Does not require Beanstalkd to be running
Useful for batch processing and deferred execution patterns
This method returns an undefined value.
Activates null mode for creating jobs without queueing to Beanstalkd.
Sets queue strategy to NullQueue, which creates job records in the database but does NOT queue them to Beanstalkd. Jobs can be executed later by manually calling Postburner::NullQueue.handle_perform!, which includes automatic time travel for scheduled jobs.
Use this strategy for deferred batch processing, conditional execution, or scenarios where you want to create jobs in advance and execute them manually on-demand.
281 282 283 |
# File 'lib/postburner.rb', line 281 def self.null_strategy! self.queue_strategy = Postburner::NullQueue end |
.scheduler_tube_name ⇒ String
Returns the scheduler tube name with environment prefix.
527 528 529 |
# File 'lib/postburner.rb', line 527 def self.scheduler_tube_name configuration.scheduler_tube_name end |
.stats(tube_names = nil) ⇒ Hash
Beanstalkd tubes are created lazily - they only exist when jobs have been put into them. Tubes that don’t exist yet are silently skipped and won’t appear in the results. This means configured queues (e.g., ‘default’, ‘mailers’) won’t appear in stats until at least one job has been enqueued to them.
Returns detailed statistics about Beanstalkd tubes.
Collects job counts (ready, delayed, buried, reserved) for each tube and provides aggregate totals across all tubes.
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 |
# File 'lib/postburner.rb', line 587 def self.stats(tube_names = nil) connected do |conn| # Get tubes to inspect tubes_to_inspect = if tube_names&.any? tube_names.map { |name| conn.tubes[name] } else conn.beanstalk.tubes.all end result = { tubes: [], totals: { ready: 0, delayed: 0, buried: 0, reserved: 0, total: 0 } } # Collect stats from each tube tubes_to_inspect.each do |tube| begin stats = tube.stats # Note: beaneater transforms hyphenated beanstalkd stats to underscores tube_data = { name: tube.name, ready: stats.current_jobs_ready || 0, delayed: stats.current_jobs_delayed || 0, buried: stats.current_jobs_buried || 0, reserved: stats.current_jobs_reserved || 0, total: (stats.current_jobs_ready || 0) + (stats.current_jobs_delayed || 0) + (stats.current_jobs_buried || 0) + (stats.current_jobs_reserved || 0) } rescue Beaneater::NotFoundError # Tube doesn't exist yet, skip it next end result[:tubes] << tube_data # Aggregate totals result[:totals][:ready] += tube_data[:ready] result[:totals][:delayed] += tube_data[:delayed] result[:totals][:buried] += tube_data[:buried] result[:totals][:reserved] += tube_data[:reserved] result[:totals][:total] += tube_data[:total] end result end end |
.strict_strategy! ⇒ void
Requires Beanstalkd server running
NOT the default production strategy
This method returns an undefined value.
Activates strict production mode with asynchronous job execution.
Sets queue strategy to StrictQueue, which queues jobs to Beanstalkd and raises Postburner::Job::PrematurePerform if a job is executed before its scheduled run_at time.
Use this strategy for production debugging or when you want strict enforcement of scheduling. For most production use cases, prefer #default_strategy! instead.
215 216 217 |
# File 'lib/postburner.rb', line 215 def self.strict_strategy! self.queue_strategy = Postburner::StrictQueue end |
.testing? ⇒ Boolean
Checks if currently using a test queue strategy.
Returns true if the current queue strategy is InlineTestQueue or TimeTravelTestQueue, indicating that jobs execute inline/synchronously without Beanstalkd.
303 304 305 |
# File 'lib/postburner.rb', line 303 def self.testing? queue_strategy.testing end |
.time_travel_test_strategy! ⇒ void
Jobs execute in queue order, not scheduled time order
Requires ActiveSupport::Testing::TimeHelpers
This method returns an undefined value.
Activates test mode with automatic time travel for scheduled jobs.
Sets queue strategy to TimeTravelTestQueue, which executes jobs synchronously and automatically uses time travel for jobs with future run_at timestamps.
Use this strategy for integration/feature tests where you want convenience over explicit time control.
187 188 189 |
# File 'lib/postburner.rb', line 187 def self.time_travel_test_strategy! self.queue_strategy = Postburner::TimeTravelTestQueue end |
.tube_prefix(env = nil) ⇒ String
Returns the Beanstalkd tube name prefix for the given environment.
Delegates to Postburner::Configuration#tube_prefix. Postburner automatically prefixes all queue names with this value.
546 547 548 |
# File 'lib/postburner.rb', line 546 def self.tube_prefix(env = nil) configuration.tube_prefix(env) end |
.watched_tube_names ⇒ Array<String>
Returns array of watched tube names with environment prefix.
Expands configured queue names to full tube names and memoizes the result.
499 500 501 |
# File 'lib/postburner.rb', line 499 def self.watched_tube_names @__watched_tube_names ||= configuration.queue_names.map { |q| configuration.(q) } end |
.watched_tubes ⇒ Array<Beaneater::Tube>
Returns array of watched Beaneater::Tube instances.
Creates Beaneater tube instances for all configured queues and memoizes the result.
512 513 514 |
# File 'lib/postburner.rb', line 512 def self.watched_tubes @__watched_tubes ||= watched_tube_names.map { |tube_name| connection.tubes[tube_name] } end |