postburner 1.0.0.pre.3 → 1.0.0.pre.5

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.
@@ -6,8 +6,8 @@
6
6
  (#{@job.run_at.to_i - Time.zone.now.to_i} seconds)
7
7
 
8
8
  %h3 Stats
9
- - if @job.beanstalk_job
10
- %pre= JSON.pretty_generate @job.beanstalk_job.stats.as_json
9
+ - if @job.bk
10
+ %pre= JSON.pretty_generate @job.bk.stats.as_json
11
11
 
12
12
  %h3 Job
13
13
  %pre= JSON.pretty_generate @job.as_json
data/bin/postburner CHANGED
@@ -55,37 +55,6 @@ require File.expand_path('config/environment', Dir.pwd)
55
55
 
56
56
  # Postburner is loaded automatically via the Rails engine when the gem is in your Gemfile
57
57
 
58
- # Load configuration
59
- config_path = File.expand_path(options[:config], Dir.pwd)
60
-
61
- begin
62
- config = Postburner::Configuration.load_yaml(config_path, options[:env], options[:worker])
63
- rescue ArgumentError => e
64
- Rails.logger.error "[Postburner] ERROR: #{e.message}"
65
- exit 1
66
- end
67
-
68
- # Filter queues if --queues option provided
69
- if options[:queues]
70
- # Validate that all specified queues exist in config
71
- invalid_queues = options[:queues] - config.queue_names
72
- unless invalid_queues.empty?
73
- config.logger.error "[Postburner] ERROR: Unknown queue(s): #{invalid_queues.join(', ')}"
74
- config.logger.error "[Postburner] Available queues: #{config.queue_names.join(', ')}"
75
- exit 1
76
- end
77
-
78
- # Filter config to only include specified queues
79
- filtered_queues = config.queues.select { |name, _| options[:queues].include?(name.to_s) }
80
- config.queues = filtered_queues
81
- end
82
-
83
- config.logger.info "[Postburner] Configuration: #{config_path}"
84
- config.logger.info "[Postburner] Environment: #{options[:env]}"
85
- config.logger.info "[Postburner] Worker: #{options[:worker] || '(auto-selected)'}" if options[:worker] || options[:queues].nil?
86
- config.logger.info "[Postburner] Queues: #{config.queue_names.join(', ')}"
87
- config.logger.info "[Postburner] Defaults: forks=#{config.default_forks}, threads=#{config.default_threads}, gc_limit=#{config.default_gc_limit || 'none'}"
88
-
89
- # Create and start worker
90
- worker = Postburner::Workers::Worker.new(config)
91
- worker.start
58
+ # Create and run worker
59
+ runner = Postburner::Runner.new(options)
60
+ runner.run
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Postburner
4
+ # Shared runner logic for bin/postburner and rake tasks.
5
+ #
6
+ # Provides a unified interface for starting Postburner workers from
7
+ # both the command-line executable and Rake tasks. Handles configuration
8
+ # loading, queue filtering, logging, and worker startup.
9
+ #
10
+ # @example Using from bin/postburner
11
+ # options = { config: 'config/postburner.yml', env: 'production', worker: 'default' }
12
+ # runner = Postburner::Runner.new(options)
13
+ # runner.run
14
+ #
15
+ # @example Using from Rake task
16
+ # options = { worker: ENV['WORKER'], queues: ENV['QUEUES']&.split(',') }
17
+ # runner = Postburner::Runner.new(options)
18
+ # runner.run
19
+ #
20
+ class Runner
21
+ attr_reader :options
22
+
23
+ # Initialize runner with options.
24
+ #
25
+ # @param options [Hash] Runner options
26
+ # @option options [String] :config Path to YAML configuration file (default: 'config/postburner.yml')
27
+ # @option options [String] :env Environment name (default: RAILS_ENV or 'development')
28
+ # @option options [String, nil] :worker Worker name from config (required if multiple workers defined)
29
+ # @option options [Array<String>, nil] :queues List of queue names to filter (overrides config)
30
+ def initialize(options = {})
31
+ @options = {
32
+ config: 'config/postburner.yml',
33
+ env: ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development',
34
+ worker: nil,
35
+ queues: nil
36
+ }.merge(options)
37
+ end
38
+
39
+ # Load configuration, filter queues, and start worker.
40
+ #
41
+ # @return [void]
42
+ def run
43
+ config = load_configuration
44
+ filter_queues(config) if options[:queues]
45
+ log_configuration(config)
46
+ start_worker(config)
47
+ end
48
+
49
+ private
50
+
51
+ # Load configuration from YAML file.
52
+ #
53
+ # @return [Postburner::Configuration]
54
+ def load_configuration
55
+ config_path = File.expand_path(options[:config], root_directory)
56
+ Postburner::Configuration.load_yaml(config_path, options[:env], options[:worker])
57
+ rescue ArgumentError => e
58
+ logger.error "[Postburner] ERROR: #{e.message}"
59
+ exit 1
60
+ end
61
+
62
+ # Filter configuration to only include specified queues.
63
+ #
64
+ # @param config [Postburner::Configuration]
65
+ # @return [void]
66
+ def filter_queues(config)
67
+ # Validate that all specified queues exist in config
68
+ invalid_queues = options[:queues] - config.queue_names
69
+ unless invalid_queues.empty?
70
+ config.logger.error "[Postburner] ERROR: Unknown queue(s): #{invalid_queues.join(', ')}"
71
+ config.logger.error "[Postburner] Available queues: #{config.queue_names.join(', ')}"
72
+ exit 1
73
+ end
74
+
75
+ # Filter config to only include specified queues
76
+ filtered_queues = config.queues.select { |name, _| options[:queues].include?(name.to_s) }
77
+ config.queues = filtered_queues
78
+ end
79
+
80
+ # Log configuration details.
81
+ #
82
+ # @param config [Postburner::Configuration]
83
+ # @return [void]
84
+ def log_configuration(config)
85
+ config_path = File.expand_path(options[:config], root_directory)
86
+ config.logger.info "[Postburner] Configuration: #{config_path}"
87
+ config.logger.info "[Postburner] Environment: #{options[:env]}"
88
+ config.logger.info "[Postburner] Worker: #{options[:worker] || '(auto-selected)'}" if options[:worker] || options[:queues].nil?
89
+ config.logger.info "[Postburner] Queues: #{config.queue_names.join(', ')}"
90
+ config.logger.info "[Postburner] Defaults: forks=#{config.default_forks}, threads=#{config.default_threads}, gc_limit=#{config.default_gc_limit || 'none'}"
91
+ end
92
+
93
+ # Returns root directory for config file resolution.
94
+ #
95
+ # Uses Rails.root when Rails is defined, otherwise falls back to current directory.
96
+ #
97
+ # @return [String] Root directory path
98
+ def root_directory
99
+ if defined?(Rails) && Rails.respond_to?(:root)
100
+ Rails.root.to_s
101
+ else
102
+ Dir.pwd
103
+ end
104
+ end
105
+
106
+ # Create and start worker.
107
+ #
108
+ # @param config [Postburner::Configuration]
109
+ # @return [void]
110
+ def start_worker(config)
111
+ worker = Postburner::Workers::Worker.new(config)
112
+ worker.start
113
+ end
114
+
115
+ # Returns logger for error reporting during initialization.
116
+ #
117
+ # @return [Logger]
118
+ def logger
119
+ if defined?(Rails)
120
+ Rails.logger
121
+ else
122
+ Logger.new($stderr)
123
+ end
124
+ end
125
+ end
126
+ end
@@ -76,20 +76,27 @@ module Postburner
76
76
  #debugger
77
77
  Postburner::Job.transaction do
78
78
  Postburner.connected do |conn|
79
- tube_name = job.tube_name
79
+ tube_name = job.expanded_tube_name
80
80
  data = { class: job.class.name, args: [job.id] }
81
81
 
82
82
  # Get priority, TTR from job instance (respects instance overrides) or options
83
83
  pri = options[:pri] || job.priority || Postburner.configuration.default_priority
84
- delay = options[:delay] || 0
84
+ delay = options[:delay].present? ? [0, options[:delay].to_i].max : 0
85
85
  ttr = options[:ttr] || job.ttr || Postburner.configuration.default_ttr
86
+ payload = JSON.generate(data)
86
87
 
87
- response = conn.tubes[tube_name].put(
88
- JSON.generate(data),
89
- pri: pri,
90
- delay: delay,
91
- ttr: ttr
92
- )
88
+ begin
89
+ response = conn.tubes[tube_name].put(
90
+ payload,
91
+ pri: pri,
92
+ delay: delay,
93
+ ttr: ttr
94
+ )
95
+ rescue Beaneater::BadFormatError => e
96
+ raise Postburner::Job::BadFormat.new(
97
+ "Beanstalkd BAD_FORMAT: tube=#{tube_name} payload=#{payload} pri=#{pri.inspect} delay=#{delay.inspect} ttr=#{ttr.inspect}"
98
+ ), cause: e
99
+ end
93
100
 
94
101
  response
95
102
  end
@@ -1,3 +1,3 @@
1
1
  module Postburner
2
- VERSION = '1.0.0.pre.3'
2
+ VERSION = '1.0.0.pre.5'
3
3
  end
data/lib/postburner.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require "postburner/version"
2
2
  require "postburner/configuration"
3
3
  require "postburner/connection"
4
- require "postburner/queue_config"
5
4
  require "postburner/beanstalkd"
6
5
  require "postburner/tracked"
7
6
  require "postburner/active_job/payload"
@@ -9,6 +8,7 @@ require "postburner/active_job/execution"
9
8
  require "postburner/active_job/adapter"
10
9
  require "postburner/workers/base"
11
10
  require "postburner/workers/worker"
11
+ require "postburner/runner"
12
12
  require "postburner/engine"
13
13
  require "postburner/strategies/queue"
14
14
  require "postburner/strategies/nice_queue"
@@ -450,7 +450,6 @@ module Postburner
450
450
  #
451
451
  def self.stats
452
452
  connected do |conn|
453
-
454
453
  {
455
454
  watched_tubes: self.watched_tubes,
456
455
  # Get all tube instances that exist on Beanstalkd
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :postburner do
4
+ desc "Start Postburner worker (ENV: WORKER=name, QUEUES=queue1,queue2, CONFIG=path)"
5
+ task work: :environment do
6
+ # Parse options from environment variables
7
+ options = {
8
+ config: ENV['CONFIG'] || 'config/postburner.yml',
9
+ env: Rails.env,
10
+ worker: ENV['WORKER'],
11
+ queues: ENV['QUEUES']&.split(',')&.map(&:strip)
12
+ }
13
+
14
+ # Create and run worker
15
+ runner = Postburner::Runner.new(options)
16
+ runner.run
17
+ end
18
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: postburner
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre.3
4
+ version: 1.0.0.pre.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Smith
@@ -104,12 +104,17 @@ extensions: []
104
104
  extra_rdoc_files: []
105
105
  files:
106
106
  - CHANGELOG.md
107
- - MIT-LICENSE
108
107
  - README.md
109
108
  - Rakefile
110
109
  - app/assets/config/postburner_manifest.js
111
110
  - app/assets/stylesheets/postburner/application.css
112
111
  - app/concerns/postburner/callbacks.rb
112
+ - app/concerns/postburner/commands.rb
113
+ - app/concerns/postburner/execution.rb
114
+ - app/concerns/postburner/insertion.rb
115
+ - app/concerns/postburner/logging.rb
116
+ - app/concerns/postburner/properties.rb
117
+ - app/concerns/postburner/statistics.rb
113
118
  - app/controllers/postburner/application_controller.rb
114
119
  - app/controllers/postburner/jobs_controller.rb
115
120
  - app/controllers/postburner/static_controller.rb
@@ -141,7 +146,7 @@ files:
141
146
  - lib/postburner/configuration.rb
142
147
  - lib/postburner/connection.rb
143
148
  - lib/postburner/engine.rb
144
- - lib/postburner/queue_config.rb
149
+ - lib/postburner/runner.rb
145
150
  - lib/postburner/strategies/immediate_test_queue.rb
146
151
  - lib/postburner/strategies/nice_queue.rb
147
152
  - lib/postburner/strategies/null_queue.rb
@@ -152,6 +157,7 @@ files:
152
157
  - lib/postburner/version.rb
153
158
  - lib/postburner/workers/base.rb
154
159
  - lib/postburner/workers/worker.rb
160
+ - lib/tasks/postburner.rake
155
161
  - lib/tasks/postburner_tasks.rake
156
162
  homepage: https://gitlab.nearapogee.com/opensource/postburner
157
163
  licenses:
data/MIT-LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright 2021 Matt Smith
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.