@@ -4,8 +4,8 @@ use concepts::storage::{
44 CreateRequest , DbErrorWrite , DbErrorWriteNonRetriable , ExecutionEvent , ExecutionRequest ,
55 HistoryEvent , JoinSetRequest , JoinSetResponse , JoinSetResponseEvent , JoinSetResponseEventOuter ,
66 Locked , LockedBy , PendingStateBlockedByJoinSet , PendingStateFinished ,
7- PendingStateFinishedResultKind , PendingStateLocked , PendingStatePendingAt , ResponseCursor ,
8- ResponseWithCursor , VersionType ,
7+ PendingStateFinishedResultKind , PendingStateLocked , PendingStatePaused , PendingStatePendingAt ,
8+ ResponseCursor , ResponseWithCursor , VersionType ,
99} ;
1010use concepts:: storage:: { ExecutionLog , PendingState , Version } ;
1111use concepts:: { ComponentId , JoinSetId } ;
@@ -297,41 +297,47 @@ impl ExecutionJournal {
297297 }
298298 }
299299
300- fn update_pending_state ( & mut self ) {
300+ fn find_current_pending_state ( & self ) -> PendingState {
301+ if let Some ( last_event) = self . execution_events . last ( )
302+ && let ExecutionRequest :: Finished { result, .. } = & last_event. event
303+ {
304+ let idx = self . execution_events . len ( ) - 1 ;
305+ return PendingState :: Finished ( PendingStateFinished {
306+ version : VersionType :: try_from ( idx) . expect ( "version limit reached" ) ,
307+ finished_at : last_event. created_at ,
308+ result_kind : PendingStateFinishedResultKind :: from ( result) ,
309+ } ) ;
310+ }
311+
301312 let mut unpause_encountered = false ;
313+ let mut is_paused = false ;
302314
303- let pending_state = self
315+ // Find the underlying state (ignoring Paused/Unpaused for now), store it in
316+ // `PendingStatePaused` independent of whether the execution is actually paused.
317+ let underlying_state: PendingStatePaused = self
304318 . execution_events
305319 . iter ( )
306320 . enumerate ( )
307321 . rev ( )
308- . find_map ( |( idx, event) | match & event. event {
322+ . find_map ( |( _idx, event) | match & event. event {
323+ ExecutionRequest :: Finished { .. } => {
324+ unreachable ! ( "finished state was already handled above" )
325+ }
309326 ExecutionRequest :: Created { scheduled_at, .. } => {
310- Some ( PendingState :: PendingAt ( PendingStatePendingAt {
327+ Some ( PendingStatePaused :: PendingAt ( PendingStatePendingAt {
311328 scheduled_at : * scheduled_at,
312329 last_lock : None ,
313330 } ) )
314331 }
315332
316- ExecutionRequest :: Finished { result, .. } => {
317- assert_eq ! ( self . execution_events. len( ) - 1 , idx) ;
318- Some ( PendingState :: Finished {
319- finished : PendingStateFinished {
320- version : VersionType :: try_from ( idx) . expect ( "version limit reached" ) ,
321- finished_at : event. created_at ,
322- result_kind : PendingStateFinishedResultKind :: from ( result) ,
323- } ,
324- } )
325- }
326-
327333 ExecutionRequest :: Locked ( Locked {
328334 executor_id,
329335 lock_expires_at,
330336 run_id,
331337 component_id : _,
332338 deployment_id : _,
333339 retry_config : _,
334- } ) => Some ( PendingState :: Locked ( PendingStateLocked {
340+ } ) => Some ( PendingStatePaused :: Locked ( PendingStateLocked {
335341 locked_by : LockedBy {
336342 executor_id : * executor_id,
337343 run_id : * run_id,
@@ -350,7 +356,7 @@ impl ExecutionJournal {
350356 | ExecutionRequest :: Unlocked {
351357 backoff_expires_at : expires_at,
352358 ..
353- } => Some ( PendingState :: PendingAt ( PendingStatePendingAt {
359+ } => Some ( PendingStatePaused :: PendingAt ( PendingStatePendingAt {
354360 scheduled_at : * expires_at,
355361 last_lock : self . find_last_lock ( ) . map ( LockedBy :: from) ,
356362 } ) ) ,
@@ -393,13 +399,13 @@ impl ExecutionJournal {
393399 if let Some ( nth_created_at) = resp {
394400 // Original executor has a chance to continue, but after expiry any executor can pick up the execution.
395401 let scheduled_at = max ( * lock_expires_at, * nth_created_at) ;
396- Some ( PendingState :: PendingAt ( PendingStatePendingAt {
402+ Some ( PendingStatePaused :: PendingAt ( PendingStatePendingAt {
397403 scheduled_at,
398404 last_lock : self . find_last_lock ( ) . map ( LockedBy :: from) ,
399405 } ) )
400406 } else {
401407 // Still waiting for response
402- Some ( PendingState :: BlockedByJoinSet (
408+ Some ( PendingStatePaused :: BlockedByJoinSet (
403409 PendingStateBlockedByJoinSet {
404410 join_set_id : expected_join_set_id. clone ( ) ,
405411 lock_expires_at : * lock_expires_at,
@@ -419,9 +425,9 @@ impl ExecutionJournal {
419425 unpause_encountered = false ;
420426 None
421427 } else {
422- // No unpauses were found with bigger version
423- unpause_encountered = false ; // For sanity check below.
424- Some ( PendingState :: Paused )
428+ // No unpauses were found in the later events - execution is paused
429+ is_paused = true ;
430+ None // Continue looking for underlying state
425431 }
426432 }
427433 // No pending state change for following events:
@@ -444,7 +450,29 @@ impl ExecutionJournal {
444450 . expect ( "journal must begin with Created event" ) ;
445451
446452 assert ! ( !unpause_encountered, "unpause must be preceeded with pause" ) ;
447- self . pending_state = pending_state;
453+
454+ // Check if execution is finished (overrides paused state)
455+
456+ {
457+ if is_paused {
458+ PendingState :: Paused ( underlying_state)
459+ } else {
460+ // Convert PendingStatePaused to PendingState
461+ match underlying_state {
462+ PendingStatePaused :: Locked ( locked) => PendingState :: Locked ( locked) ,
463+ PendingStatePaused :: PendingAt ( pending_at) => {
464+ PendingState :: PendingAt ( pending_at)
465+ }
466+ PendingStatePaused :: BlockedByJoinSet ( blocked) => {
467+ PendingState :: BlockedByJoinSet ( blocked)
468+ }
469+ }
470+ }
471+ }
472+ }
473+
474+ fn update_pending_state ( & mut self ) {
475+ self . pending_state = self . find_current_pending_state ( ) ;
448476 self . component_id = self
449477 . find_last_lock ( )
450478 . map ( |locked| locked. component_id . clone ( ) )
0 commit comments