@@ -301,6 +301,7 @@ async def exit(
301301 * ,
302302 exit_code : int = 0 ,
303303 event_listeners_timeout_secs : Optional [float ] = EVENT_LISTENERS_TIMEOUT_SECS ,
304+ status_message : Optional [str ] = None ,
304305 ) -> None :
305306 """Exit the actor instance.
306307
@@ -312,18 +313,21 @@ async def exit(
312313
313314 Args:
314315 exit_code (int, optional): The exit code with which the actor should fail (defaults to `0`).
315- event_listeners_timeout_secs (float, optional): How long should the actor wait for actor event listeners to finish before exiting
316+ event_listeners_timeout_secs (float, optional): How long should the actor wait for actor event listeners to finish before exiting.
317+ status_message (str, optional): The final status message that the actor should display.
316318 """
317319 return await cls ._get_default_instance ().exit (
318320 exit_code = exit_code ,
319321 event_listeners_timeout_secs = event_listeners_timeout_secs ,
322+ status_message = status_message ,
320323 )
321324
322325 async def _exit_internal (
323326 self ,
324327 * ,
325328 exit_code : int = 0 ,
326329 event_listeners_timeout_secs : Optional [float ] = EVENT_LISTENERS_TIMEOUT_SECS ,
330+ status_message : Optional [str ] = None ,
327331 ) -> None :
328332 self ._raise_if_not_initialized ()
329333
@@ -340,6 +344,9 @@ async def _exit_internal(
340344 self ._event_manager .emit (ActorEventTypes .PERSIST_STATE , {'isMigrating' : False })
341345 self ._was_final_persist_state_emitted = True
342346
347+ if status_message is not None :
348+ await self .set_status_message (status_message , is_terminal = True )
349+
343350 # Sleep for a bit so that the listeners have a chance to trigger
344351 await asyncio .sleep (0.1 )
345352
@@ -362,6 +369,7 @@ async def fail(
362369 * ,
363370 exit_code : int = 1 ,
364371 exception : Optional [BaseException ] = None ,
372+ status_message : Optional [str ] = None ,
365373 ) -> None :
366374 """Fail the actor instance.
367375
@@ -371,17 +379,20 @@ async def fail(
371379 Args:
372380 exit_code (int, optional): The exit code with which the actor should fail (defaults to `1`).
373381 exception (BaseException, optional): The exception with which the actor failed.
382+ status_message (str, optional): The final status message that the actor should display.
374383 """
375384 return await cls ._get_default_instance ().fail (
376385 exit_code = exit_code ,
377386 exception = exception ,
387+ status_message = status_message ,
378388 )
379389
380390 async def _fail_internal (
381391 self ,
382392 * ,
383393 exit_code : int = 1 ,
384394 exception : Optional [BaseException ] = None ,
395+ status_message : Optional [str ] = None ,
385396 ) -> None :
386397 self ._raise_if_not_initialized ()
387398
@@ -390,7 +401,7 @@ async def _fail_internal(
390401 if exception and not _is_running_in_ipython ():
391402 self .log .exception ('Actor failed with an exception' , exc_info = exception )
392403
393- await self .exit (exit_code = exit_code )
404+ await self .exit (exit_code = exit_code , status_message = status_message )
394405
395406 @classmethod
396407 async def main (cls , main_actor_function : Callable [[], MainReturnType ]) -> Optional [MainReturnType ]:
@@ -1210,28 +1221,30 @@ async def _add_webhook_internal(
12101221 )
12111222
12121223 @classmethod
1213- async def set_status_message (cls , status_message : str ) -> Optional [Dict ]:
1224+ async def set_status_message (cls , status_message : str , * , is_terminal : Optional [ bool ] = None ) -> Optional [Dict ]:
12141225 """Set the status message for the current actor run.
12151226
12161227 Args:
12171228 status_message (str): The status message to set to the run.
1229+ is_terminal (bool, optional): Set this flag to True if this is the final status message of the Actor run.
12181230
12191231 Returns:
12201232 dict: The updated actor run object
12211233 """
1222- return await cls ._get_default_instance ().set_status_message (status_message = status_message )
1234+ return await cls ._get_default_instance ().set_status_message (status_message = status_message , is_terminal = is_terminal )
12231235
1224- async def _set_status_message_internal (self , status_message : str ) -> Optional [Dict ]:
1236+ async def _set_status_message_internal (self , status_message : str , * , is_terminal : Optional [ bool ] = None ) -> Optional [Dict ]:
12251237 self ._raise_if_not_initialized ()
12261238
12271239 if not self .is_at_home ():
1228- self .log .error ('Actor.set_status_message() is only supported when running on the Apify platform.' )
1240+ title = 'Terminal status message' if is_terminal else 'Status message'
1241+ self .log .info (f'[{ title } ]: { status_message } ' )
12291242 return None
12301243
12311244 # If is_at_home() is True, config.actor_run_id is always set
12321245 assert self ._config .actor_run_id is not None
12331246
1234- return await self ._apify_client .run (self ._config .actor_run_id ).update (status_message = status_message )
1247+ return await self ._apify_client .run (self ._config .actor_run_id ).update (status_message = status_message , is_status_message_terminal = is_terminal )
12351248
12361249 @classmethod
12371250 async def create_proxy_configuration (
0 commit comments