@@ -117,37 +117,74 @@ def increment(label:)
117117 end
118118 end
119119
120- test "emits each lost message attempt and stops from its instrumentation callback" do
121- worker = new_worker
122- reference = Counter . ref ( "one" ) . async . increment ( label : "slow" )
123- observed = [ ]
124- SolidObjects . configuration . retry_delay = -> ( _ ) { 0 }
125- SolidObjects . configuration . instrumentation = -> ( event ) do
126- next unless event . fetch ( "name" ) == "solid_objects.activation.lost"
120+ %w[ completion failure rejection ] . each do |outcome |
121+ test "reports each lost #{ outcome } and stops from its instrumentation callback" do
122+ worker = new_worker
123+ reference = Counter . ref ( "one" ) . async . increment ( label : "slow" )
124+ Counter . before_commit = -> ( _ ) do
125+ @clock [ :now ] += 0.201
126+ raise SolidObjects ::Rejected . new ( code : "declined" , message : "declined" ) if outcome == "rejection"
127+ raise "handler failed" if outcome == "failure"
128+ end
129+ observed = [ ]
130+ SolidObjects . configuration . retry_delay = -> ( _ ) { 0 }
131+ SolidObjects . configuration . instrumentation = -> ( event ) do
132+ next unless event . fetch ( "name" ) == "solid_objects.activation.lost"
127133
128- observed << event
129- worker . request_shutdown if observed . length == 3
130- end
131- forced_shutdown = false
132- guard = Thread . new do
133- sleep 2
134- forced_shutdown = true
135- worker . request_shutdown
134+ observed << event
135+ worker . request_shutdown if observed . length == 3
136+ end
137+ forced_shutdown = false
138+ guard = Thread . new do
139+ sleep 2
140+ forced_shutdown = true
141+ worker . request_shutdown
142+ end
143+ begin
144+ worker . run
145+ ensure
146+ guard . kill
147+ guard . join
148+ end
149+ assert_not forced_shutdown
150+ assert_predicate worker , :stopped?
151+ assert_equal [ 1 , 2 , 3 ] , observed . map { |event | event . fetch ( "attempt" ) }
152+ assert observed . all? { |event | event . fetch ( "messageId" ) == reference . id . to_s }
153+ observed . each { |event | assert_portable_attributes ( event ) }
154+ assert worker . shutdown_requested?
155+ assert_empty stored_message ( reference ) . instance . state
156+ assert_empty SolidObjects ::DeadLetter . all
136157 end
137- begin
138- worker . run
139- ensure
140- guard . kill
141- guard . join
158+ end
159+
160+ %w[ failure rejection ] . each do |outcome |
161+ test "reports lease loss while saving a handler #{ outcome } and recovers" do
162+ worker = new_worker
163+ reference = Counter . ref ( "one" ) . async . increment ( label : "slow" )
164+ Counter . before_commit = -> ( _ ) do
165+ @clock [ :now ] += 0.201
166+ raise SolidObjects ::Rejected . new ( code : "declined" , message : "declined" ) if outcome == "rejection"
167+
168+ raise "handler failed"
169+ end
170+ assert_equal 0 , worker . run_once
171+ losses = @events . select { |event | event . fetch ( "name" ) == "solid_objects.activation.lost" }
172+ assert_equal [ 1 ] , losses . map { |event | event . fetch ( "attempt" ) }
173+ assert_equal [ reference . id . to_s ] , losses . map { |event | event . fetch ( "messageId" ) }
174+ losses . each { |event | assert_portable_attributes ( event ) }
175+ assert_empty stored_message ( reference ) . instance . state
176+ assert_nil stored_message ( reference ) . error
177+ assert_nil stored_message ( reference ) . rejection
178+ assert_empty SolidObjects ::DeadLetter . all
179+ assert_empty SolidObjects ::Effect . all
180+ assert_not @events . any? { |event | %w[ solid_objects.message.failed solid_objects.message.rejected ] . include? ( event . fetch ( "name" ) ) }
181+
182+ Counter . before_commit = nil
183+ assert_equal 1 , worker . run_once
184+ assert_equal 1 , stored_message ( reference ) . result
185+ assert_equal 2 , stored_message ( reference ) . attempt_count
186+ assert_equal 1 , SolidObjects ::Effect . count
142187 end
143- assert_not forced_shutdown
144- assert_predicate worker , :stopped?
145- assert_equal [ 1 , 2 , 3 ] , observed . map { |event | event . fetch ( "attempt" ) }
146- assert observed . all? { |event | event . fetch ( "messageId" ) == reference . id . to_s }
147- observed . each { |event | assert_portable_attributes ( event ) }
148- assert worker . shutdown_requested?
149- assert_empty stored_message ( reference ) . instance . state
150- assert_empty SolidObjects ::DeadLetter . all
151188 end
152189
153190 test "keeps a handler failure terminal with one allowed attempt" do
0 commit comments