+
    jHàjÏ  ã                  ój   € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIH	t	 R R lt
R
R R lltR R	 ltR# )u�  Cron: teardown of a worker that outlived its ``run_job``.

``ThreadPoolExecutor.shutdown(wait=False)`` after an inactivity timeout does not stop a
worker already inside ``run_conversation``. Finalizing its SessionDB from ``run_job``'s
``finally`` would close a handle the worker is still writing to â€” the checkpoint/WAL-unlink
overlap behind #102827. The worker's Future owns the teardown instead.
)ÚannotationsN)ÚOptionalc               ó    € V ^8„  d   QhRRRR/# )é   Úfuturezconcurrent.futures.FutureÚreturnÚNone© )Úformats   "ÚC/home/ubuntu/.hermes/hermes-agent/cron/scheduler_detached_worker.pyÚ__annotate__r      s   € ÷ !ñ !Ð*Cð !Èñ !ó    c                óÈ   € \         P                  ! \        4      ;_uu_ 4        V P                  4       pVe   ^ RIHp V! V4       RRR4       R#   + '       g   i     R# ; i)uÙ  Done-callback: close a SessionDB whose constructor finished after run_job's init timeout
(worker abandoned via ``shutdown(wait=False)``), else its .db/WAL/SHM handles leak to EMFILE.

If the constructor later completes inside that abandoned worker, the Future's result â€” an open
SessionDB holding .db / WAL / SHM file handles â€” would be orphaned and never closed, leaking
descriptors until EMFILE (#72782). This callback retrieves and closes that eventual late result.
N)Úrelease_or_close)Ú
contextlibÚsuppressÚ	ExceptionÚresultÚhermes_state_registryr   )r   Údbr   s   &  r   Ú_close_late_session_db_resultr      s?   € ô 
×	Ò	œY×	'Õ	'Ø�]‰]‹_ˆØŠ>Ý>Ù˜RÔ ÷	 
(×	'×	'Ò	'ús   £#AÁA!	c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r   r   z#Optional[concurrent.futures.Future]Újob_idÚstrÚjob_nameÚcron_session_idÚworkdirzOptional[str]r   Úboolr	   )r
   s   "r   r   r   !   s>   € ÷ ñ Ø/ðØLOðØ[^ðàðà#0ðð 
ñr   c           	     ó    aaaaaaaa	€ V e   V P                  4       '       d   R# ^ RIHoHo	 R VV	VVVVVV3R llpV P	                  V4       R# )z¢Return True when the worker is still running and its Future will finalize the session
and tear the agent down on completion; False when the caller must do it now.F)Ú_finalize_cron_sessionÚ_teardown_cron_agentc               ó   € V ^8„  d   QhRR/# )r   r   r   r	   )r
   s   "r   r   Ú6defer_teardown_to_running_worker.<locals>.__annotate__+   s   € ÷ 0ñ 0˜Dñ 0r   c           	     ód   <€  S'       d   S! SSSSSSR 7       S! SS4       R#   S! SS4       i ; i))r   Nr	   )	Ú_futurer   r    Úagentr   r   r   Ú
session_dbr   s	   &€€€€€€€€r   Ú_finishÚ1defer_teardown_to_running_worker.<locals>._finish+   s8   ø€ ð	0ßÙ& z°5¸&À(ÈOØ/6õ8ñ ! ¨Ö/øÑ  ¨Õ/ús   ƒ$ ‹$ ¤/T)ÚdoneÚcron.schedulerr   r    Úadd_done_callback)
r   r&   r%   r   r   r   r   r'   r   r    s
   &ffffff @@r   Ú defer_teardown_to_running_workerr,   !   s7   ÿ€ ð ‚~˜Ÿ™ŸšÙßK÷0÷ 0ð ×Ñ˜WÔ%Ùr   c               ó    € V ^8„  d   QhRRRR/# )r   Úprocesszsubprocess.Popenr   r   r	   )r
   s   "r   r   r   8   s   € ÷ ñ Ð0@ð ÀTñ r   c           	     ó„   € \         P                  ! V P                  R\        V RR4       2RR7      P	                  4        R# )aÝ  Keep the reap contract when the waiter returns before the worker exits.

The ledger turning terminal lets ``_wait_for_external_cron_worker_body``
return while the worker is still in final teardown. The gateway remains the
worker's parent, so if nobody calls ``wait()`` afterwards the worker lingers
as a zombie (STAT=Z) under the gateway until it is restarted (#114509). A
short-lived daemon thread holds that single responsibility and ends with
the process exit it waits for.
zcron-worker-reap-ÚpidÚ?T)ÚtargetÚnameÚdaemonN)Ú	threadingÚThreadÚwaitÚgetattrÚstart)r.   s   &r   Ú"reap_terminal_worker_in_backgroundr:   8   s9   € ô ×ÒØ�|‰|Ø ¤¨°%¸Ó!=Ð >Ð?Øô÷ �e†gr   )N)Ú__doc__Ú
__future__r   Úconcurrent.futuresÚ
concurrentr   Ú
subprocessr5   Útypingr   r   r,   r:   r	   r   r   Ú<module>rA      s-   ðñõ #ã Û Û Û Ý õ!÷÷.r   