postburner 1.0.0.pre.13 → 1.0.0.pre.14
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 +152 -81
- data/app/concerns/postburner/insertion.rb +17 -1
- data/app/models/postburner/schedule.rb +50 -0
- data/app/models/postburner/schedule_execution.rb +19 -0
- data/bin/postburner +13 -5
- data/lib/generators/postburner/install/templates/config/postburner.yml +24 -139
- data/lib/postburner/active_job/adapter.rb +51 -1
- data/lib/postburner/instrumentation.rb +196 -0
- data/lib/postburner/scheduler.rb +74 -20
- data/lib/postburner/strategies/{nice_queue.rb → default_queue.rb} +10 -10
- data/lib/postburner/strategies/{test_queue.rb → inline_test_queue.rb} +10 -7
- data/lib/postburner/strategies/{queue.rb → strict_queue.rb} +12 -12
- data/lib/postburner/strategies/{immediate_test_queue.rb → time_travel_test_queue.rb} +15 -12
- data/lib/postburner/test_helpers.rb +133 -0
- data/lib/postburner/version.rb +1 -1
- data/lib/postburner/worker.rb +26 -12
- data/lib/postburner.rb +51 -49
- metadata +7 -5
|
@@ -4,13 +4,13 @@ module Postburner
|
|
|
4
4
|
# Default production queue strategy with graceful handling of premature execution.
|
|
5
5
|
#
|
|
6
6
|
# This is the recommended production strategy and the default for Postburner.
|
|
7
|
-
# Unlike the strict {
|
|
7
|
+
# Unlike the strict {StrictQueue} strategy, DefaultQueue automatically re-inserts jobs
|
|
8
8
|
# that are executed before their scheduled run_at time, ensuring they run at
|
|
9
9
|
# the correct time without raising exceptions.
|
|
10
10
|
#
|
|
11
11
|
# @note This is the DEFAULT strategy set on Postburner initialization
|
|
12
12
|
#
|
|
13
|
-
# ## When to Use
|
|
13
|
+
# ## When to Use DefaultQueue
|
|
14
14
|
#
|
|
15
15
|
# Choose this strategy for production environments:
|
|
16
16
|
# - **Default choice:** This should be your go-to production strategy
|
|
@@ -42,12 +42,12 @@ module Postburner
|
|
|
42
42
|
# ## Usage
|
|
43
43
|
#
|
|
44
44
|
# @example Default behavior (automatically set)
|
|
45
|
-
# # No configuration needed -
|
|
45
|
+
# # No configuration needed - DefaultQueue is the default
|
|
46
46
|
# job = MyJob.create!(args: { user_id: 123 })
|
|
47
47
|
# job.queue!(delay: 1.hour)
|
|
48
48
|
#
|
|
49
|
-
# @example Explicitly activate
|
|
50
|
-
# Postburner.
|
|
49
|
+
# @example Explicitly activate DefaultQueue
|
|
50
|
+
# Postburner.default_strategy!
|
|
51
51
|
# job = MyJob.create!(args: {})
|
|
52
52
|
# job.queue!(at: Time.zone.now + 2.days)
|
|
53
53
|
#
|
|
@@ -58,15 +58,15 @@ module Postburner
|
|
|
58
58
|
# # Job is automatically re-inserted with 55-minute delay
|
|
59
59
|
# # "PREMATURE; RE-INSERTED" logged to job.logs
|
|
60
60
|
#
|
|
61
|
-
# @see
|
|
62
|
-
# @see
|
|
63
|
-
# @see Postburner.
|
|
61
|
+
# @see StrictQueue Strict production strategy that raises on premature execution
|
|
62
|
+
# @see InlineTestQueue Test strategy with inline execution
|
|
63
|
+
# @see Postburner.default_strategy!
|
|
64
64
|
#
|
|
65
|
-
class
|
|
65
|
+
class DefaultQueue < StrictQueue
|
|
66
66
|
class << self
|
|
67
67
|
# Handles jobs executed before their scheduled run_at time.
|
|
68
68
|
#
|
|
69
|
-
# Unlike the parent {
|
|
69
|
+
# Unlike the parent {StrictQueue} strategy, DefaultQueue gracefully handles premature
|
|
70
70
|
# execution by re-inserting the job with the appropriate delay instead of
|
|
71
71
|
# raising an exception.
|
|
72
72
|
#
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Postburner
|
|
4
|
-
#
|
|
4
|
+
# Inline test queue strategy with strict scheduling enforcement.
|
|
5
5
|
#
|
|
6
6
|
# This strategy executes jobs inline/synchronously without Beanstalkd, making
|
|
7
7
|
# tests fast and predictable. It raises {Postburner::Job::PrematurePerform} if
|
|
@@ -9,7 +9,7 @@ module Postburner
|
|
|
9
9
|
#
|
|
10
10
|
# @note Auto-detected when Rails.env.test? and ActiveJob adapter is :test
|
|
11
11
|
#
|
|
12
|
-
# ## When to Use
|
|
12
|
+
# ## When to Use InlineTestQueue
|
|
13
13
|
#
|
|
14
14
|
# Choose this strategy for test environments where you want:
|
|
15
15
|
# - **Explicit time management:** Forces you to use `travel_to` for scheduled jobs
|
|
@@ -33,10 +33,10 @@ module Postburner
|
|
|
33
33
|
#
|
|
34
34
|
# @example Automatically activated in Rails test environment
|
|
35
35
|
# # In test_helper.rb or rails_helper.rb
|
|
36
|
-
# #
|
|
36
|
+
# # InlineTestQueue is automatically set if Rails.env.test?
|
|
37
37
|
# # and ActiveJob.queue_adapter == :test
|
|
38
38
|
#
|
|
39
|
-
# @example Explicitly activate
|
|
39
|
+
# @example Explicitly activate InlineTestQueue
|
|
40
40
|
# Postburner.inline_test_strategy!
|
|
41
41
|
# job = MyJob.create!(args: { user_id: 123 })
|
|
42
42
|
# job.queue!
|
|
@@ -70,11 +70,11 @@ module Postburner
|
|
|
70
70
|
# end
|
|
71
71
|
# end
|
|
72
72
|
#
|
|
73
|
-
# @see
|
|
73
|
+
# @see ImmediateInlineTestQueue Test strategy with automatic time travel
|
|
74
74
|
# @see NiceQueue Default production strategy
|
|
75
75
|
# @see Postburner.inline_test_strategy!
|
|
76
76
|
#
|
|
77
|
-
class
|
|
77
|
+
class InlineTestQueue < Queue
|
|
78
78
|
class << self
|
|
79
79
|
# Returns whether this strategy is for testing.
|
|
80
80
|
#
|
|
@@ -121,8 +121,11 @@ 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.current) / 60).round(1)} minutes from now). Use `travel_to(job.run_at)` in your test, or set `Postburner.
|
|
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.time_travel_test_strategy!` i.e. `Postburner::TimeTravelTestQueue` to execute scheduled jobs immediately."
|
|
125
125
|
end
|
|
126
126
|
end
|
|
127
127
|
end
|
|
128
|
+
|
|
129
|
+
# Backward compatibility alias
|
|
130
|
+
TestQueue = InlineTestQueue
|
|
128
131
|
end
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Postburner
|
|
4
|
-
#
|
|
4
|
+
# Strict production queue strategy that queues jobs to Beanstalkd asynchronously.
|
|
5
5
|
#
|
|
6
6
|
# This is the strict production strategy that raises an exception if a job
|
|
7
|
-
# is executed before its scheduled run_at time. Unlike {
|
|
7
|
+
# is executed before its scheduled run_at time. Unlike {DefaultQueue}, it does
|
|
8
8
|
# not automatically re-insert premature jobs.
|
|
9
9
|
#
|
|
10
|
-
# @note This is NOT the default strategy - use {
|
|
10
|
+
# @note This is NOT the default strategy - use {DefaultQueue} for production
|
|
11
11
|
#
|
|
12
|
-
# ## When to Use
|
|
12
|
+
# ## When to Use StrictQueue
|
|
13
13
|
#
|
|
14
14
|
# Choose this strategy when you want strict enforcement of job scheduling:
|
|
15
15
|
# - You want jobs to fail loudly if executed prematurely
|
|
16
16
|
# - You're debugging scheduling issues
|
|
17
17
|
# - You want to catch configuration errors in production
|
|
18
18
|
#
|
|
19
|
-
# For most production use cases, use {
|
|
19
|
+
# For most production use cases, use {DefaultQueue} instead, which handles
|
|
20
20
|
# premature execution gracefully by re-inserting with appropriate delay.
|
|
21
21
|
#
|
|
22
22
|
# ## Strategy Behavior
|
|
@@ -28,23 +28,23 @@ module Postburner
|
|
|
28
28
|
#
|
|
29
29
|
# ## Usage
|
|
30
30
|
#
|
|
31
|
-
# @example Activate
|
|
32
|
-
# Postburner.
|
|
31
|
+
# @example Activate StrictQueue strategy
|
|
32
|
+
# Postburner.strict_strategy!
|
|
33
33
|
# job = MyJob.create!(args: { user_id: 123 })
|
|
34
34
|
# job.queue!(delay: 1.hour)
|
|
35
35
|
#
|
|
36
36
|
# @example Premature execution raises exception
|
|
37
|
-
# Postburner.
|
|
37
|
+
# Postburner.strict_strategy!
|
|
38
38
|
# job = MyJob.create!(args: {})
|
|
39
39
|
# job.queue!(delay: 1.hour)
|
|
40
40
|
# # Worker picks up job too early...
|
|
41
41
|
# # => raises PrematurePerform: "Job has future run_at: ..."
|
|
42
42
|
#
|
|
43
|
-
# @see
|
|
44
|
-
# @see
|
|
45
|
-
# @see Postburner.
|
|
43
|
+
# @see DefaultQueue Default production strategy with graceful premature handling
|
|
44
|
+
# @see InlineTestQueue Test strategy with inline execution
|
|
45
|
+
# @see Postburner.strict_strategy!
|
|
46
46
|
#
|
|
47
|
-
class
|
|
47
|
+
class StrictQueue
|
|
48
48
|
class << self
|
|
49
49
|
# Returns whether this strategy is for testing.
|
|
50
50
|
#
|
|
@@ -5,25 +5,25 @@ require_relative '../time_helpers'
|
|
|
5
5
|
module Postburner
|
|
6
6
|
# Test queue strategy with automatic time travel for scheduled jobs.
|
|
7
7
|
#
|
|
8
|
-
# This strategy executes jobs inline/synchronously like {
|
|
8
|
+
# This strategy executes jobs inline/synchronously like {InlineTestQueue}, but
|
|
9
9
|
# automatically uses time travel for scheduled jobs instead of raising
|
|
10
10
|
# exceptions. When a job has a future run_at, it travels to that time,
|
|
11
11
|
# executes the job, then returns to the present.
|
|
12
12
|
#
|
|
13
13
|
# @note Requires ActiveSupport::Testing::TimeHelpers (Rails testing framework)
|
|
14
14
|
#
|
|
15
|
-
# ## When to Use
|
|
15
|
+
# ## When to Use TimeTravelTestQueue
|
|
16
16
|
#
|
|
17
17
|
# Choose this strategy for test environments where you want:
|
|
18
18
|
# - **Automatic time management:** No need to manually call `travel_to`
|
|
19
19
|
# - **Simple scheduled job testing:** Test delayed/scheduled jobs without boilerplate
|
|
20
20
|
# - **Fast tests:** Jobs execute immediately regardless of schedule
|
|
21
21
|
# - **No Beanstalkd:** Tests run without external dependencies
|
|
22
|
-
# - **Convenience over control:** Less explicit but easier to use than {
|
|
22
|
+
# - **Convenience over control:** Less explicit but easier to use than {InlineTestQueue}
|
|
23
23
|
#
|
|
24
24
|
# This is ideal for integration/feature tests where you want to verify that
|
|
25
25
|
# scheduled jobs execute correctly without managing time travel yourself. The
|
|
26
|
-
# tradeoff is less explicit control over timing compared to {
|
|
26
|
+
# tradeoff is less explicit control over timing compared to {InlineTestQueue}.
|
|
27
27
|
#
|
|
28
28
|
# ## Strategy Behavior
|
|
29
29
|
#
|
|
@@ -48,15 +48,15 @@ module Postburner
|
|
|
48
48
|
#
|
|
49
49
|
# ## Usage
|
|
50
50
|
#
|
|
51
|
-
# @example Explicitly activate
|
|
52
|
-
# Postburner.
|
|
51
|
+
# @example Explicitly activate TimeTravelTestQueue
|
|
52
|
+
# Postburner.time_travel_test_strategy!
|
|
53
53
|
# job = MyJob.create!(args: { user_id: 123 })
|
|
54
54
|
# job.queue!(delay: 1.hour)
|
|
55
55
|
# # Job executes immediately at scheduled time
|
|
56
56
|
# assert job.reload.processed_at
|
|
57
57
|
#
|
|
58
58
|
# @example Scheduled jobs execute automatically
|
|
59
|
-
# Postburner.
|
|
59
|
+
# Postburner.time_travel_test_strategy!
|
|
60
60
|
# job = SendReminderEmail.create!(args: { user_id: 123 })
|
|
61
61
|
#
|
|
62
62
|
# # Job executes immediately despite 2-day delay
|
|
@@ -67,7 +67,7 @@ module Postburner
|
|
|
67
67
|
# assert_not_nil job.processed_at
|
|
68
68
|
#
|
|
69
69
|
# @example Multiple jobs execute in queue order, not schedule order
|
|
70
|
-
# Postburner.
|
|
70
|
+
# Postburner.time_travel_test_strategy!
|
|
71
71
|
#
|
|
72
72
|
# job1 = MyJob.create!(args: { id: 1 })
|
|
73
73
|
# job2 = MyJob.create!(args: { id: 2 })
|
|
@@ -80,7 +80,7 @@ module Postburner
|
|
|
80
80
|
#
|
|
81
81
|
# @example Testing feature with scheduled job
|
|
82
82
|
# test "sends reminder email after 24 hours" do
|
|
83
|
-
# Postburner.
|
|
83
|
+
# Postburner.time_travel_test_strategy!
|
|
84
84
|
#
|
|
85
85
|
# user = users(:john)
|
|
86
86
|
# reminder = ReminderJob.create!(args: { user_id: user.id })
|
|
@@ -91,11 +91,11 @@ module Postburner
|
|
|
91
91
|
# assert_emails 1
|
|
92
92
|
# end
|
|
93
93
|
#
|
|
94
|
-
# @see
|
|
94
|
+
# @see InlineTestQueue Test strategy requiring explicit time travel
|
|
95
95
|
# @see NiceQueue Default production strategy
|
|
96
|
-
# @see Postburner.
|
|
96
|
+
# @see Postburner.time_travel_test_strategy!
|
|
97
97
|
#
|
|
98
|
-
class
|
|
98
|
+
class TimeTravelTestQueue < InlineTestQueue
|
|
99
99
|
class << self
|
|
100
100
|
include TimeHelpers
|
|
101
101
|
|
|
@@ -147,4 +147,7 @@ module Postburner
|
|
|
147
147
|
end
|
|
148
148
|
end
|
|
149
149
|
end
|
|
150
|
+
|
|
151
|
+
# Backward compatibility alias
|
|
152
|
+
ImmediateTestQueue = TimeTravelTestQueue
|
|
150
153
|
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Postburner
|
|
4
|
+
# Test helper methods for switching queue strategies in tests.
|
|
5
|
+
#
|
|
6
|
+
# Provides instance methods for managing queue strategies in a test-safe,
|
|
7
|
+
# thread-safe manner. Use these methods to switch between strategies for
|
|
8
|
+
# individual tests or groups of tests.
|
|
9
|
+
#
|
|
10
|
+
# @example Using in setup/teardown
|
|
11
|
+
# class MyTest < ActiveSupport::TestCase
|
|
12
|
+
# include Postburner::TestHelpers
|
|
13
|
+
#
|
|
14
|
+
# def setup
|
|
15
|
+
# switch_queue_strategy!(:time_travel_test)
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# def teardown
|
|
19
|
+
# restore_queue_strategy!
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
# def test_something
|
|
23
|
+
# job = MyJob.create!(args: {})
|
|
24
|
+
# job.queue!(delay: 1.hour)
|
|
25
|
+
# assert job.reload.processed_at
|
|
26
|
+
# end
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# @example Using block form
|
|
30
|
+
# class MyTest < ActiveSupport::TestCase
|
|
31
|
+
# include Postburner::TestHelpers
|
|
32
|
+
#
|
|
33
|
+
# def test_something
|
|
34
|
+
# use_queue_strategy(:time_travel_test) do
|
|
35
|
+
# job = MyJob.create!(args: {})
|
|
36
|
+
# job.queue!(delay: 1.hour)
|
|
37
|
+
# assert job.reload.processed_at
|
|
38
|
+
# end
|
|
39
|
+
# end
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
module TestHelpers
|
|
43
|
+
# Switch to a different queue strategy for testing.
|
|
44
|
+
#
|
|
45
|
+
# Stashes the current strategy in a thread-local variable so it can be
|
|
46
|
+
# restored later with {#restore_queue_strategy!}. This is thread-safe
|
|
47
|
+
# for parallel test execution.
|
|
48
|
+
#
|
|
49
|
+
# @param strategy [Class, Symbol] Strategy class or symbol name
|
|
50
|
+
# Symbols: :inline_test, :time_travel_test, :strict, :default, :null
|
|
51
|
+
#
|
|
52
|
+
# @return [Class] The newly activated strategy class
|
|
53
|
+
#
|
|
54
|
+
# @raise [ArgumentError] if strategy is invalid type or unknown symbol
|
|
55
|
+
#
|
|
56
|
+
# @example With class constant
|
|
57
|
+
# switch_queue_strategy!(Postburner::TimeTravelTestQueue)
|
|
58
|
+
#
|
|
59
|
+
# @example With symbol
|
|
60
|
+
# switch_queue_strategy!(:time_travel_test)
|
|
61
|
+
#
|
|
62
|
+
def switch_queue_strategy!(strategy)
|
|
63
|
+
Thread.current[:postburner_original_strategy] = Postburner.queue_strategy
|
|
64
|
+
|
|
65
|
+
Postburner.queue_strategy = case strategy
|
|
66
|
+
when Symbol
|
|
67
|
+
strategy_method = "#{strategy}_strategy!".to_sym
|
|
68
|
+
if Postburner.respond_to?(strategy_method, true)
|
|
69
|
+
Postburner.send(strategy_method)
|
|
70
|
+
Postburner.queue_strategy
|
|
71
|
+
else
|
|
72
|
+
raise ArgumentError, "Unknown strategy: #{strategy}. Available: inline_test, time_travel_test, strict, default, null"
|
|
73
|
+
end
|
|
74
|
+
when Class
|
|
75
|
+
strategy
|
|
76
|
+
else
|
|
77
|
+
raise ArgumentError, "Expected Class or Symbol, got #{strategy.class}"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Restore the previously stashed queue strategy.
|
|
82
|
+
#
|
|
83
|
+
# Restores the strategy that was active when {#switch_queue_strategy!}
|
|
84
|
+
# was called. Clears the thread-local stash after restoring.
|
|
85
|
+
#
|
|
86
|
+
# @return [Class] The restored strategy class
|
|
87
|
+
#
|
|
88
|
+
# @raise [RuntimeError] if no strategy was stashed
|
|
89
|
+
#
|
|
90
|
+
# @example Typical usage in teardown
|
|
91
|
+
# def teardown
|
|
92
|
+
# restore_queue_strategy!
|
|
93
|
+
# end
|
|
94
|
+
#
|
|
95
|
+
def restore_queue_strategy!
|
|
96
|
+
original = Thread.current[:postburner_original_strategy]
|
|
97
|
+
if original.nil?
|
|
98
|
+
raise "No strategy to restore. Did you call switch_queue_strategy! first?"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
Postburner.queue_strategy = original
|
|
102
|
+
Thread.current[:postburner_original_strategy] = nil
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Execute a block with a temporary queue strategy.
|
|
106
|
+
#
|
|
107
|
+
# Automatically switches to the specified strategy before the block
|
|
108
|
+
# and restores the original strategy after, even if an exception occurs.
|
|
109
|
+
#
|
|
110
|
+
# @param strategy [Class, Symbol] Strategy class or symbol name
|
|
111
|
+
# Symbols: :inline_test, :time_travel_test, :strict, :default, :null
|
|
112
|
+
#
|
|
113
|
+
# @yield Block to execute with the temporary strategy
|
|
114
|
+
#
|
|
115
|
+
# @return [Object] The return value of the block
|
|
116
|
+
#
|
|
117
|
+
# @raise [ArgumentError] if strategy is invalid type or unknown symbol
|
|
118
|
+
#
|
|
119
|
+
# @example
|
|
120
|
+
# use_queue_strategy(:time_travel_test) do
|
|
121
|
+
# job = MyJob.create!(args: {})
|
|
122
|
+
# job.queue!(delay: 1.hour)
|
|
123
|
+
# assert job.reload.processed_at
|
|
124
|
+
# end
|
|
125
|
+
#
|
|
126
|
+
def use_queue_strategy(strategy, &block)
|
|
127
|
+
switch_queue_strategy!(strategy)
|
|
128
|
+
yield
|
|
129
|
+
ensure
|
|
130
|
+
restore_queue_strategy!
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
data/lib/postburner/version.rb
CHANGED
data/lib/postburner/worker.rb
CHANGED
|
@@ -501,8 +501,8 @@ module Postburner
|
|
|
501
501
|
# from Beanstalkd after successful completion.
|
|
502
502
|
#
|
|
503
503
|
# Instruments with ActiveSupport::Notifications:
|
|
504
|
-
# - perform_start.postburner: Before job execution
|
|
505
|
-
# - perform.postburner: Around job execution (includes duration)
|
|
504
|
+
# - perform_start.job.postburner: Before job execution
|
|
505
|
+
# - perform.job.postburner: Around job execution (includes duration)
|
|
506
506
|
#
|
|
507
507
|
# @param beanstalk_job [Beaneater::Job] Reserved job from Beanstalkd
|
|
508
508
|
# @param payload [Hash] Parsed job body
|
|
@@ -511,13 +511,14 @@ module Postburner
|
|
|
511
511
|
# @api private
|
|
512
512
|
def execute_regular_job(beanstalk_job, payload)
|
|
513
513
|
job_description = format_job_description(payload)
|
|
514
|
-
|
|
514
|
+
job_payload = Postburner::Instrumentation.job_payload_from_hash(payload, beanstalk_job_id: beanstalk_job.id)
|
|
515
|
+
instrument_payload = { job: job_payload, beanstalk_job_id: beanstalk_job.id }
|
|
515
516
|
|
|
516
517
|
logger.info "[Postburner] Executing #{job_description} (bkid: #{beanstalk_job.id})"
|
|
517
518
|
|
|
518
|
-
ActiveSupport::Notifications.instrument('perform_start.postburner', instrument_payload)
|
|
519
|
+
ActiveSupport::Notifications.instrument('perform_start.job.postburner', instrument_payload)
|
|
519
520
|
|
|
520
|
-
ActiveSupport::Notifications.instrument('perform.postburner', instrument_payload) do
|
|
521
|
+
ActiveSupport::Notifications.instrument('perform.job.postburner', instrument_payload) do
|
|
521
522
|
Postburner::ActiveJob::Execution.execute(beanstalk_job.body)
|
|
522
523
|
end
|
|
523
524
|
|
|
@@ -547,9 +548,13 @@ module Postburner
|
|
|
547
548
|
|
|
548
549
|
# Handles job execution errors with retry logic.
|
|
549
550
|
#
|
|
550
|
-
# For tracked jobs and legacy Postburner::Job: Buries the job for inspection
|
|
551
|
+
# For tracked jobs and legacy Postburner::Job: Buries the job for inspection
|
|
552
|
+
# and emits retry_stopped.job.postburner event.
|
|
551
553
|
# For default ActiveJob: Applies exponential backoff retry with max 5 attempts.
|
|
552
554
|
#
|
|
555
|
+
# Instruments with ActiveSupport::Notifications:
|
|
556
|
+
# - retry_stopped.job.postburner: When tracked job is buried after failure
|
|
557
|
+
#
|
|
553
558
|
# @param beanstalk_job [Beaneater::Job] Failed job
|
|
554
559
|
# @param error [Exception] The error that caused the failure
|
|
555
560
|
# @return [void]
|
|
@@ -563,6 +568,14 @@ module Postburner
|
|
|
563
568
|
|
|
564
569
|
if payload['tracked'] || Postburner::ActiveJob::Payload.legacy_format?(payload)
|
|
565
570
|
logger.info "[Postburner] Burying tracked/legacy job for inspection"
|
|
571
|
+
|
|
572
|
+
job_payload = Postburner::Instrumentation.job_payload_from_hash(payload, beanstalk_job_id: beanstalk_job.id)
|
|
573
|
+
ActiveSupport::Notifications.instrument('retry_stopped.job.postburner', {
|
|
574
|
+
job: job_payload,
|
|
575
|
+
beanstalk_job_id: beanstalk_job.id,
|
|
576
|
+
error: error
|
|
577
|
+
})
|
|
578
|
+
|
|
566
579
|
beanstalk_job.bury
|
|
567
580
|
else
|
|
568
581
|
handle_default_retry(beanstalk_job, payload, error)
|
|
@@ -579,8 +592,8 @@ module Postburner
|
|
|
579
592
|
# After 5 failed attempts, discards the job permanently.
|
|
580
593
|
#
|
|
581
594
|
# Instruments with ActiveSupport::Notifications:
|
|
582
|
-
# - retry.postburner: When job is retried
|
|
583
|
-
# - discard.postburner: When job is discarded after max retries
|
|
595
|
+
# - retry.job.postburner: When job is retried
|
|
596
|
+
# - discard.job.postburner: When job is discarded after max retries
|
|
584
597
|
#
|
|
585
598
|
# @param beanstalk_job [Beaneater::Job] Failed job to retry
|
|
586
599
|
# @param payload [Hash] Parsed job body (modified with retry_count)
|
|
@@ -590,6 +603,7 @@ module Postburner
|
|
|
590
603
|
def handle_default_retry(beanstalk_job, payload, error)
|
|
591
604
|
retry_count = payload['retry_count'] || 0
|
|
592
605
|
max_retries = 5
|
|
606
|
+
job_payload = Postburner::Instrumentation.job_payload_from_hash(payload, beanstalk_job_id: beanstalk_job.id)
|
|
593
607
|
|
|
594
608
|
if retry_count < max_retries
|
|
595
609
|
payload['retry_count'] = retry_count + 1
|
|
@@ -609,8 +623,8 @@ module Postburner
|
|
|
609
623
|
)
|
|
610
624
|
end
|
|
611
625
|
|
|
612
|
-
ActiveSupport::Notifications.instrument('retry.postburner', {
|
|
613
|
-
|
|
626
|
+
ActiveSupport::Notifications.instrument('retry.job.postburner', {
|
|
627
|
+
job: job_payload,
|
|
614
628
|
beanstalk_job_id: beanstalk_job.id,
|
|
615
629
|
error: error,
|
|
616
630
|
wait: delay,
|
|
@@ -619,8 +633,8 @@ module Postburner
|
|
|
619
633
|
|
|
620
634
|
logger.info "[Postburner] Retrying default job #{payload['job_id']}, attempt #{retry_count + 1} in #{delay}s"
|
|
621
635
|
else
|
|
622
|
-
ActiveSupport::Notifications.instrument('discard.postburner', {
|
|
623
|
-
|
|
636
|
+
ActiveSupport::Notifications.instrument('discard.job.postburner', {
|
|
637
|
+
job: job_payload,
|
|
624
638
|
beanstalk_job_id: beanstalk_job.id,
|
|
625
639
|
error: error
|
|
626
640
|
})
|