+
    jHàj  ã                  óž   € R t ^ RIHt ^ RIt^ RIHt ]P                  ! ]4      tRRRRRRRR/t	R R	 lt
R
 R ltR R ltR R ltR R ltR# )ax  Write a queued cron delivery's terminal outcome back onto the run that queued it.

An agent run hands its send to ``cron.delivery_queue`` and books ``last_status =
"delivery_queued"`` / ledger ``delivery_outcome = "queued"``. Once a gateway drain sends,
refuses, suppresses or fences the send ``unknown``, the job record and the execution
ledger must carry the real result (main's inline ``ok``/``delivered`` and
``delivery_failed``/``failed`` + ``last_delivery_error``); otherwise ``hermes cron list``
says "delivery still in progress" forever and refused sends never surface.

Both sides call :func:`settle_queued_delivery`: the drain right after it terminalizes a
row, and the run right after its own bookkeeping (a drain can finish before the run's
``mark_job_run`` lands). Every write is fenced on the execution id, so the call is
idempotent and never rewrites a later run's status.
)ÚannotationsN)ÚOptionalÚ	deliveredÚ
suppressedÚfailedÚunknownc               ó(   € V ^8„  d   QhRRRRRRRR/# )é   Újob_idÚstrÚexecution_idÚdelivery_errorúOptional[str]ÚreturnÚbool© )Úformats   "Ú:/home/ubuntu/.hermes/hermes-agent/cron/delivery_outcome.pyÚ__annotate__r      s)   € ÷ 9ñ 9˜sð 9°#ð 9À}ð 9ÐY]ñ 9ó    c                ó¢   aaa€ ^ RI Hp ^ RIHpHo V! V 4      pVe   VP                  R4      S8w  d   R# VVV3R lp\        V! WRR7      4      # )z¤Stamp the outcome onto the job only while *execution_id* is still its current run:
the ledger's latest attempt for the job AND the job's latest recorded completion.)Úlatest_execution)Ú	_with_jobÚ	save_jobsÚidFc                ó.  <€ VP                  R 4      ;'       g    . pV'       d   VR,          S8w  d   R# VP                  R4      pVR8X  d   S'       d   RMRpVS3VP                  R4      VP                  R4      38X  d   R# WBR&   SVR&   S! V 4       R# )	Úcanonical_completionsFÚlast_statusÚdelivery_queuedÚdelivery_failedÚokÚlast_delivery_errorTéÿÿÿÿ)Úget)ÚjobsÚ_iÚjobÚcompletionsÚstatusr   r   r   s   &&&  €€€r   ÚapplyÚ!_settle_job_record.<locals>.apply'   s‘   ø€ Ø—g‘gÐ5Ó6×<Ð<¸"ˆß˜k¨"�o°Ô=ÙØ—‘˜Ó'ˆØÐ&Ô&ß*8Ñ&¸dˆFØ�NÐ#¨¯©°Ó(>ÀÇÁÐH]Ó@^Ð'_Ô_ÙØ#ˆMÑØ%3ˆÐ!Ñ"Ù�$ŒÙr   )Úmissing)Úcron.executionsr   Ú	cron.jobsr   r   r#   r   )r
   r   r   r   r   Úlatestr)   r   s   &ff    @r   Ú_settle_job_recordr/      sF   ú€ õ 1ß.á˜fÓ%€FØ‚~˜Ÿ™ DÓ)¨\Ô9Ù÷ô ‘	˜&°Ô7Ó8Ð8r   c               ó    € V ^8„  d   QhRRRR/# )r	   r   r   r   z#Optional[tuple[str, Optional[str]]]r   )r   s   "r   r   r   8   s   € ÷ 
:ñ 
:˜Cð 
:Ð$Gñ 
:r   c                ó  € ^ RI Hp V! \        V 4      4      pV'       d   VR,          \        9  d   R# RpVR,          R9   d/   \        VP	                  R4      ;'       g    RVR,           24      p\        VR,          ,          V3# )zO``(ledger_outcome, delivery_error)`` once the queue row is terminal, else None.)Ú
get_statusr(   NÚerrorz	delivery )r   r   )Úcron.delivery_queuer2   r   Ú_LEDGER_OUTCOMEr#   )r   r2   Úrowr   s   &   r   Ú	_terminalr7   8   sq   € å.á
”S˜Ó&Ó
'€Cß�#�h•-¤Ô6ÙØ€NØ
ˆ8…}Ð-Ô-Ü˜SŸW™W WÓ-×LÐL°9¸SÀ½]¸OÐ1LÓMˆÜ˜3˜x�=Õ)¨>Ð9Ð9r   c               ó    € V ^8„  d   QhRRRR/# )r	   r   r   r   r   r   )r   s   "r   r   r   E   s   € ÷ -ñ - #ð -¨-ñ -r   c                ó>   € \        V 4      pV'       d
   V^ ,          # R# )zRThe ledger outcome a drain already reached for *execution_id* (None while queued).N)r7   )r   Úterminals   & r   Úsettled_outcomer;   E   s   € ä˜Ó&€Hß"ˆ8�A�;Ð,¨Ð,r   c               ó$   € V ^8„  d   QhRRRRRR/# )r	   r
   r   r   r   r   r   )r   s   "r   r   r   K   s"   € ÷ ñ  =ð Àð ÐRVñ r   c                óè   € V '       d	   V'       g   R# \        \        V4      4      pVf   R# ^ RIHp V! \        V4      V^ ,          4       \	        \        V 4      \        V4      V^,          4       R# )zSApply the queue's terminal outcome for *execution_id*; False while still in flight.F)Úsettle_delivery_outcomeT)r7   r   r,   r>   r/   )r
   r   r:   r>   s   &&  r   Úsettle_queued_deliveryr?   K   sT   € çŸÙÜœ˜\Ó*Ó+€HØÒÙÝ7áœC Ó-¨x¸­{Ô;Ü”s˜6“{¤C¨Ó$5°xÀµ{ÔCÙr   c               ó$   € V ^8„  d   QhRRRRRR/# )r	   r
   r   r   r   ÚNoner   )r   s   "r   r   r   Y   s&   € ÷ cñ c˜=ð c¸ð cÈ$ñ cr   c                ór   €  \        W4       R#   \         d    \        P                  RTRR7        R# i ; i)zOBookkeeping failure must not undo a terminal at-most-once send or fail its run.z+Cron delivery %s: outcome write-back failedT)Úexc_infoN)r?   Ú	ExceptionÚloggerÚwarning)r
   r   s   &&r   Úsettle_quietlyrG   Y   s5   € ðcÜ˜vÖ4øÜô cÜ�‰ÐDÀlÐ]aˆ×bðcús   ‚ �#6µ6)Ú__doc__Ú
__future__r   ÚloggingÚtypingr   Ú	getLoggerÚ__name__rE   r5   r/   r7   r;   r?   rG   r   r   r   Ú<module>rN      sZ   ðñõ #ã Ý à	×	Ò	˜8Ó	$€ð
 �˜l¨L¸(ÀHÈiÐYað€õ
9õ6
:õ-õ÷cr   