@@ -2289,64 +2289,80 @@ def execute(
22892289 logger = self ._logger ,
22902290 )
22912291 try :
2292- # Rebuild local state by replaying old history into the orchestrator function
2293- self ._logger .debug (
2294- f"{ instance_id } : Rebuilding local state with { len (old_events )} history event..."
2295- )
2296- ctx ._is_replaying = True # pyright: ignore[reportPrivateUsage]
2297- for old_event in old_events :
2298- self .process_event (ctx , old_event )
2299-
2300- # Get new actions by executing newly received events into the orchestrator function
2301- if self ._logger .level <= logging .DEBUG :
2302- summary = _get_new_event_summary (new_events )
2292+ try :
2293+ # Rebuild local state by replaying old history into the orchestrator function
23032294 self ._logger .debug (
2304- f"{ instance_id } : Processing { len (new_events )} new event(s): { summary } "
2295+ f"{ instance_id } : Rebuilding local state with { len (old_events )} history event... "
23052296 )
2306- ctx ._is_replaying = False # pyright: ignore[reportPrivateUsage]
2307- for new_event in new_events :
2308- self .process_event (ctx , new_event )
2309-
2310- except pe .VersionFailureException as ex :
2311- if self ._registry .versioning and self ._registry .versioning .failure_strategy == VersionFailureStrategy .FAIL :
2312- if ex .error_details :
2313- ctx .set_failed (ex .error_details )
2314- else :
2315- ctx .set_failed (ex )
2316- elif self ._registry .versioning and self ._registry .versioning .failure_strategy == VersionFailureStrategy .REJECT :
2317- raise pe .AbandonOrchestrationError
2297+ ctx ._is_replaying = True # pyright: ignore[reportPrivateUsage]
2298+ for old_event in old_events :
2299+ self .process_event (ctx , old_event )
2300+
2301+ # Get new actions by executing newly received events into the orchestrator function
2302+ if self ._logger .level <= logging .DEBUG :
2303+ summary = _get_new_event_summary (new_events )
2304+ self ._logger .debug (
2305+ f"{ instance_id } : Processing { len (new_events )} new event(s): { summary } "
2306+ )
2307+ ctx ._is_replaying = False # pyright: ignore[reportPrivateUsage]
2308+ for new_event in new_events :
2309+ self .process_event (ctx , new_event )
2310+
2311+ except pe .VersionFailureException as ex :
2312+ if self ._registry .versioning and self ._registry .versioning .failure_strategy == VersionFailureStrategy .FAIL :
2313+ if ex .error_details :
2314+ ctx .set_failed (ex .error_details )
2315+ else :
2316+ ctx .set_failed (ex )
2317+ elif self ._registry .versioning and self ._registry .versioning .failure_strategy == VersionFailureStrategy .REJECT :
2318+ raise pe .AbandonOrchestrationError
23182319
2319- except Exception as ex :
2320- # Unhandled exceptions fail the orchestration
2321- self ._logger .debug (f"{ instance_id } : Orchestration { orchestration_name } failed" )
2322- ctx .set_failed (ex )
2320+ except Exception as ex :
2321+ # Unhandled exceptions fail the orchestration
2322+ self ._logger .debug (f"{ instance_id } : Orchestration { orchestration_name } failed" )
2323+ ctx .set_failed (ex )
23232324
2324- if not ctx ._is_complete : # pyright: ignore[reportPrivateUsage]
2325- task_count = len (ctx ._pending_tasks ) # pyright: ignore[reportPrivateUsage]
2326- event_count = len (ctx ._pending_events ) # pyright: ignore[reportPrivateUsage]
2327- self ._logger .info (
2328- f"{ instance_id } : Orchestrator { orchestration_name } yielded with { task_count } task(s) "
2329- f"and { event_count } event(s) outstanding."
2330- )
2331- elif (
2332- ctx ._completion_status and ctx ._completion_status is not pb .ORCHESTRATION_STATUS_CONTINUED_AS_NEW # pyright: ignore[reportPrivateUsage]
2333- ):
2334- completion_status_str = ph .get_orchestration_status_str (
2335- ctx ._completion_status # pyright: ignore[reportPrivateUsage]
2336- )
2337- self ._logger .info (
2338- f"{ instance_id } : Orchestration { orchestration_name } completed with status: { completion_status_str } "
2339- )
2325+ if not ctx ._is_complete : # pyright: ignore[reportPrivateUsage]
2326+ task_count = len (ctx ._pending_tasks ) # pyright: ignore[reportPrivateUsage]
2327+ event_count = len (ctx ._pending_events ) # pyright: ignore[reportPrivateUsage]
2328+ self ._logger .info (
2329+ f"{ instance_id } : Orchestrator { orchestration_name } yielded with { task_count } task(s) "
2330+ f"and { event_count } event(s) outstanding."
2331+ )
2332+ elif (
2333+ ctx ._completion_status and ctx ._completion_status is not pb .ORCHESTRATION_STATUS_CONTINUED_AS_NEW # pyright: ignore[reportPrivateUsage]
2334+ ):
2335+ completion_status_str = ph .get_orchestration_status_str (
2336+ ctx ._completion_status # pyright: ignore[reportPrivateUsage]
2337+ )
2338+ self ._logger .info (
2339+ f"{ instance_id } : Orchestration { orchestration_name } completed with status: { completion_status_str } "
2340+ )
23402341
2341- actions = ctx .get_actions ()
2342- if self ._logger .level <= logging .DEBUG :
2343- self ._logger .debug (
2344- f"{ instance_id } : Returning { len (actions )} action(s): { _get_action_summary (actions )} "
2342+ actions = ctx .get_actions ()
2343+ if self ._logger .level <= logging .DEBUG :
2344+ self ._logger .debug (
2345+ f"{ instance_id } : Returning { len (actions )} action(s): { _get_action_summary (actions )} "
2346+ )
2347+ return ExecutionResults (
2348+ actions = actions , encoded_custom_status = ctx ._encoded_custom_status , # pyright: ignore[reportPrivateUsage]
2349+ orchestration_trace_context = ctx ._orchestration_trace_context , # pyright: ignore[reportPrivateUsage]
23452350 )
2346- return ExecutionResults (
2347- actions = actions , encoded_custom_status = ctx ._encoded_custom_status , # pyright: ignore[reportPrivateUsage]
2348- orchestration_trace_context = ctx ._orchestration_trace_context , # pyright: ignore[reportPrivateUsage]
2349- )
2351+ finally :
2352+ # Close after building the response, so the orchestrator's finally
2353+ # blocks do not change the actions or custom status we return.
2354+ if ctx ._generator is not None : # pyright: ignore[reportPrivateUsage]
2355+ try :
2356+ ctx ._generator .close () # pyright: ignore[reportPrivateUsage]
2357+ except Exception :
2358+ cleanup_name = next (
2359+ (e .executionStarted .name for e in new_events if e .HasField ("executionStarted" )),
2360+ orchestration_name ,
2361+ )
2362+ self ._logger .warning (
2363+ f"{ instance_id } : Failed to close orchestrator { cleanup_name } generator." ,
2364+ exc_info = True ,
2365+ )
23502366
23512367 def _build_rewind_result (
23522368 self ,
0 commit comments