+
    „WÝjEU  ã                  ó°  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t
^ RIt
^ RIt^ RIHt ^ RIHt ^ RIHtHtHtHt ^ RIHt ^ RIHt ^RIHtHt ]P8                  ! ]4      t^t^t ^t!^t"R	t#^t$R
t%Rt&]'! RR04      t(^t)R t*R R lt+] ! R R4      4       t,]! RR7       ! R R4      4       t-R R lt.R R lt/RR/R R llt0Rt1 ! R R4      t2R# )!aH  Transmit exported shared-metrics packages to the Nous telemetry service.

Sender side of the ingest contract (telemetry repo ``CONTRACT.md``): ``202`` durably stored,
mark sent; ``400`` permanently malformed, never retry; ``429`` keep, retry after
``Retry-After``; ``5xx`` / timeout / connection error keep, retry with backoff.
)ÚannotationsN)Úcontextmanager)Ú	dataclass)ÚdatetimeÚ	timedeltaÚtimezoneÚUTC)Úparse_retry_after_seconds)Ú	write_txn)Ú
_isoformatÚ_utc_nowi   i,  i�  i�  c               ó    € V ^8„  d   QhRRRR/# )é   ÚvalueÚstrÚreturnr   © )Úformats   "ÚbC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\observability\shared_metrics_sender.pyÚ__annotate__r   G   s   € ÷ 9ñ 9˜ð 9 ñ 9ó    c                óT   € \         P                  ! V 4      P                  \        4      # )zBParse a stamp this module itself wrote (Z-suffixed ISO-8601, UTC).)r   ÚfromisoformatÚ
astimezoner   )r   s   &r   Ú_parse_stampr   G   s   € ä×!Ò! %Ó(×3Ñ3´CÓ8Ð8r   c                  óF   € ] tR t^Lt$ Rt^ tR]R&   ^ tR]R&   ^ tR]R&   Rt	R# )ÚSendOutcomez6What one pass did. Returned for tests and diagnostics.ÚintÚsentÚrejectedÚdeferredr   N)
Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   Ú__annotations__r   r    Ú__static_attributes__r   r   r   r   r   L   s"   ‡ á@à€Dˆ#ƒMØ€HˆcÓØ€Hˆc×r   r   T)Úslotsc                  ó6   € ] tR t^Ut$ R]R&   R]R&   R]R&   RtR# )	Ú	_Responser   Ústatusú
str | NoneÚretry_afterr   Úbodyr   N)r!   r"   r#   r$   r&   r'   r   r   r   r*   r*   U   s   ‡ àƒKØÓØ
‡Ir   r*   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úendpointr   ÚpayloadÚbytesÚtimeoutr   r   r*   r   )r   s   "r   r   r   \   s(   € ÷ 
ñ 
�Cð 
 %ð 
°Sð 
¸Yñ 
r   c          
     ó,  € RRRR/pTp\        V4      \        8”  d   \        P                  ! V^ R7      pRVR&   \        P
                  P                  WVRR	7      p \        P
                  P                  WRR
7      ;_uu_ 4       p\        VP                  VP                  P                  R4      VP                  R4      P                  RR4      4      uuRRR4       #   + '       g   i     R# ; i  \        P                  P                   d‚   p\        TP                   TP                  '       d   TP                  P                  R4      MRTP"                  '       d"   TP                  R4      P                  RR4      MR4      u Rp?# Rp?ii ; i)zDPOST one package. Raises on transport failure; never on HTTP status.zContent-Typezapplication/jsonz
User-Agentzhermes-agent-shared-metrics/1)ÚmtimeÚgzipzContent-EncodingÚPOST)ÚdataÚheadersÚmethod©r3   zRetry-Afteri   úutf-8ÚreplaceNÚ )ÚlenÚGZIP_THRESHOLD_BYTESr6   ÚcompressÚurllibÚrequestÚRequestÚurlopenr*   r+   r9   ÚgetÚreadÚdecodeÚerrorÚ	HTTPErrorÚcodeÚfp)r0   r1   r3   r9   r.   rC   ÚresponseÚexcs   &&$     r   Ú_postrO   \   s7  € ð 	Ð*ØÐ5ð€Gð €DÜ
ˆ7ƒ|Ô*Ô*ä�}Š}˜W¨AÔ.ˆØ&,ˆÐ"Ñ#ä�n‰n×$Ñ$ XÀ'ÐRXÐ$ÓY€Gð
Ü�^‰^×#Ñ# GÐ#×=Ô=ÀÜØ—‘Ø× Ñ ×$Ñ$ ]Ó3Ø—‘˜dÓ#×*Ñ*¨7°IÓ>ó÷ >×=×=Ó=ûô �<‰<×!Ñ!ô 
äØ�H‰HØ.1¯k¯k¨kˆC�K‰K�O‰O˜MÔ*¸tØ9<¿¿¸ˆC�H‰H�T‹N×!Ñ! '¨9Ô5ÀRó
õ 	
ûð
úsD   Á(C3 ÂACÃ
C3 ÃC0	Ã*C3 Ã0C3 Ã3FÄAFÅ"&FÆFÆFc               ó$   € V ^8„  d   QhRRRRRR/# )r   r   r,   Údefaultr   r   r   )r   s   "r   r   r   y   s!   € ÷ -ñ - 
ð -°Sð -¸Sñ -r   c                ób   € \        V 4      pVf   V# \        ^\        \        V4      R4      4      # )Ni€Q )r	   ÚmaxÚminr   )r   rQ   Úsecondss   && r   Ú_retry_after_secondsrV   y   s.   € Ü'¨Ó.€GØ‚Øˆäˆq”#”c˜'“l FÓ+Ó,Ð,r   Únowc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Ú
connectionúsqlite3.ConnectionÚsend_enabledÚboolrW   zdatetime | Noner   ÚNoner   )r   s   "r   r   r   �   s0   € ÷ >
ñ >
Ø"ð>
àð>
ð 
ð	>
ð
 
ñ>
r   c               óÚ  € \        T;'       g    \        4       4      pTpV P                  R4      P                  4       pVeE   \        \	        \        V^ ,          4      4      \        \        R7      ,           4      p\        W64      pV P                  RV34       \        V P                  R4      P                  4       4      pVR,          pVP                  R4      p	V P                  R4      P                  4       p
V'       dI   V
f)   \        R	 W‰3 4       4      pV P                  R
W»34       R# V P                  RWŠ^ ,          34       R# V
e   V P                  RWJ^ ,          34       R# R# )zéReconcile the consent-window table with the observed config state.

THE ONLY writer of consent state; must run inside a write transaction. Idempotent in
(config, now, store): call it from anywhere, any number of times, in any order.
z2SELECT stamp FROM consent_marks WHERE name = 'obs'N©rU   z•
        INSERT INTO consent_marks(name, stamp) VALUES ('obs', ?)
        ON CONFLICT(name) DO UPDATE SET stamp = MAX(stamp, excluded.stamp)
        z%SELECT name, stamp FROM consent_marksÚobsr8   z>SELECT rowid FROM send_consent_windows WHERE closed_at IS NULLc              3  ó0   "  € T F  qf   K  Vx € K  	  R # 5i©Nr   )Ú.0Úxs   & r   Ú	<genexpr>Ú)reconcile_send_consent.<locals>.<genexpr>§   s   é € ÐA¡K˜qŸš£Kùs   ‚Œ
zLINSERT INTO send_consent_windows(opened_at, last_confirmed_at) VALUES (?, ?)z]UPDATE send_consent_windows SET last_confirmed_at = MAX(last_confirmed_at, ?) WHERE rowid = ?zUUPDATE send_consent_windows SET closed_at = MIN(last_confirmed_at, ?) WHERE rowid = ?)r   r   ÚexecuteÚfetchoner   r   r   ÚMAX_OBS_ADVANCE_SECONDSrT   ÚdictÚfetchallrF   rS   )rY   r[   rW   ÚstampÚ	raw_stampÚprevious_obsÚceilingÚmarksr`   r8   Úopen_rowÚopeneds   &&$         r   Úreconcile_send_consentrs   �   sh  € ô �s×(Ð(œh›jÓ)€EØ€IØ×%Ñ%Ø<óç�hƒjð ð ÒÜÜœ˜\¨!�_Ó-Ó.´ÔCZÔ1[Õ[ó
ˆô �EÓ#ˆØ×Ñð	ð 
ˆôô �×#Ñ#Ð$KÓL×UÑUÓWÓX€EØ
��,€CØ�9‰9�VÓ€Dà×!Ñ!ØHóç�hƒjð ÷ ØÒÜÑA S¡KÓAÓAˆFØ×Ñð!àÐ öð ×Ñð#ð ˜q•kÐ"ö	ð 
Ò	ð 	×Ñðð  �Ð$ö		
ñ 
r   zôEXISTS (
    SELECT 1 FROM send_consent_windows w
    WHERE package_outbox.period_start >= w.opened_at
      AND package_outbox.period_end <=
          CASE WHEN w.closed_at IS NULL THEN w.last_confirmed_at
               ELSE w.closed_at END
)c            
      ó  € ] tR t^ÎtRtR]R]P                  R]R]	RR/R R	 llt
]R
 4       tR R lt]R R l4       t]R R l4       tRR/R R lltR R ltRR/R R lltR R lt]R R l4       tR R ltR R ltR  R! ltR"tR# )#ÚSharedMetricsSenderz4Sends exported packages, one bounded pass at a time.ÚpostÚsleeprW   Úmax_attemptsÚconsent_checkNc               ó$   € V ^8„  d   QhRRRRRR/# )r   r0   r   rx   r   r   r]   r   )r   s   "r   r   Ú SharedMetricsSender.__annotate__Ñ   s*   € ÷ ,ñ ,ð ð,ð ð,ð 
ñ,r   c               	óZ   € Wn         W n        W0n        W@n        WPn        W`n        Wpn        R # rb   )Ú_storeÚ	_endpointrO   Ú_sleepÚ_nowÚ_max_attemptsÚ_consent_check)ÚselfÚstorer0   rv   rw   rW   rx   ry   s   &&&$$$$$r   Ú__init__ÚSharedMetricsSender.__init__Ñ   s+   € ð ŒØ!ŒØŒ
ØŒØŒ	Ø)Ôð ,Ör   c           	   #  óò   "  € V P                   P                  4       ;_uu_ 4       p\        V4      ;_uu_ 4        Vx € RRR4       RRR4       R#   + '       g   i     L; i  + '       g   i     R# ; i5i)z0One store connection inside a write transaction.N)r}   Ú_connectionr
   )rƒ   rY   s   & r   Ú_writeÚSharedMetricsSender._writeæ   sL   é € ð �[‰[×$Ñ$×&Ô&¨*Ü˜:×&Õ&Ø Ò ÷ '÷ 'Ñ&ß&×&ú÷ '×&Ð&üs2   ‚#A7¥A#¹A	¾A#Á
A7ÁA ÁA#Á#A4	Á.	A7c               ó$   € V ^8„  d   QhRRRRRR/# )r   rW   r   Úseenzset[str]r   zdict | Noner   )r   s   "r   r   r{   ï   s!   € ÷ 6ñ 6˜xð 6¨xð 6¸Kñ 6r   c                óü  € V P                  4       ;_uu_ 4       p\        V4      pV\        \        R7      ,           pRP	                  R V 4       4      pV'       d   RV R2MRpVP                  R\         RV R	2V\        .\        V4      O54      P                  4       pVf    R
R
R
4       R
# \        V^ ,          4      p	V^,          ;'       g    V P                  W9V^,          4      p
V
f   RV	RR/uuR
R
R
4       # \        \        P                  ! 4       4      pVP                  R\        V4      W¹34       RV	R\        V^,          4      R\        V
4      RVRR/uuR
R
R
4       #   + '       g   i     R
# ; i)a=  Claim exactly ONE package, immediately before it is sent (see _CLAIM_LEASE_SECONDS).

``seen`` (packages this pass finished with) is excluded IN SQL: with LIMIT 1,
returning None for a seen row would look like an empty queue and abandon everything
behind it, and rows can legitimately become eligible again mid-pass.
r_   Ú,c              3  ó&   "  € T F  pR x € K	  	  R# 5i)Ú?Nr   )rc   Ú_s   & r   re   Ú2SharedMetricsSender._claim_next.<locals>.<genexpr>ú   s   é € Ð#6±¨A¥C³ùs   ‚z AND package_id NOT IN (Ú)r>   aO  
                    SELECT package_id, payload_json, sent_install_id
                    FROM package_outbox
                    WHERE exported_at IS NOT NULL
                      AND (send_state IS NULL OR send_state = 'pending')
                      AND (next_attempt_at IS NULL OR next_attempt_at <= ?)
                      AND zC
                      AND send_attempts < ?
                      ze
                    ORDER BY created_at, package_id
                    LIMIT 1
                    NÚ
package_idÚskipTa(  
                    UPDATE package_outbox
                    SET send_state = 'pending',
                        send_attempts = send_attempts + 1,
                        next_attempt_at = ?,
                        claim_token = ?
                    WHERE package_id = ?
                    Úpayload_jsonÚderivedÚclaim_tokenF)r‰   r   r   Ú_CLAIM_LEASE_SECONDSÚjoinrg   ÚCONSENT_GATE_SQLÚMAX_SEND_ATTEMPTSÚsortedrh   r   Ú_freeze_identityÚuuidÚuuid4)rƒ   rW   rŒ   rY   rl   Úlease_untilÚplaceholdersÚ	exclusionÚrowr”   r—   Útokens   &&&         r   Ú_claim_nextÚSharedMetricsSender._claim_nextï   sk  € ð �[‰[�]Œ]˜jÜ˜s“OˆEØ¤	Ô2FÔ GÕGˆKàŸ8™8Ñ#6±Ó#6Ó6ˆLßFJÐ2°<°.ÀÑBÐPRˆIà×$Ñ$ðô ,Ð,ð -à �kð "ðð Ô)Ð9¬F°4«LÑ9ó÷ ‰h‹jð ð Š{Ø÷/ ‰]ô2 ˜S �V›ˆJØ˜!•f×UÐU × 5Ñ 5°jÈcÐRSÍfÓ UˆGØŠà$ j°&¸$Ð?÷; Š]ô< œŸ
š
›Ó%ˆEØ×Ñðô ˜KÓ(¨%Ð<ôð ˜j¨.¼#¸cÀ!½f»+ÀyÔRUÐV]ÓR^Ø˜u f¨eð÷Y �]�]‹]ús   ™BE*Â0!E*Ã#E*Ä AE*Å*E;	c               ó$   € V ^8„  d   QhRRRRRR/# )r   rY   rZ   r”   r   r   r,   r   )r   s   "r   r   r{   (  s$   € ÷ 'ñ 'Ø&ð'Ø47ð'à	ñ'r   c                ó  € Rp \         P                  ! V4      p\        V\        4      '       d   VP	                  R4      MRp\        V\        4      '       g   R\        V4      P                   R2pM2\        V\        4      '       d   VP                  4       '       g   RpMRp Ve,   \        P                  RW4       V P                  RWQ34       R# V P                  R	W134       \        V4      #   \        \        3 d    Rp Lbi ; i)
zÕRecord the transmitted install_id on the row, or reject an unusable one.

Rejecting rather than raising matters: an exception would roll back the claim
transaction and block every healthy package behind this one.
NÚ
install_idzpayload is z, expected objectz payload has no usable install_idzunreadable payloadz-Shared-metrics package %s cannot be sent (%s)z˜
                UPDATE package_outbox
                SET send_state = 'rejected', last_error = ?
                WHERE package_id = ?
                zBUPDATE package_outbox SET sent_install_id = ? WHERE package_id = ?)ÚjsonÚloadsÚ
isinstancerj   rF   Útyper!   r   ÚstripÚ	TypeErrorÚ
ValueErrorÚloggerÚwarningrg   )rY   r”   r–   rª   r1   Úreasons   &&&   r   rž   Ú$SharedMetricsSender._freeze_identity'  sû   € ð ˆ
ð	Ü—j’j Ó.ˆGô
 7AÀÌ$×6OÒ6O˜Ÿ™ \Ô2ÐUYˆJÜ˜g¤t×,Ò,Ø&¤t¨G£}×'=Ñ'=Ð&>Ð>OÐP‘Ü 
¬C×0Ò0¸
×8HÑ8H×8JÒ8JØ;‘à‘àÒÜ�N‰NÐJÈJÔ_Ø×Ñðð
 Ð$ôñ à×ÑØPØÐ$ô	
ô �:‹Ðøô9 œ:Ð&ô 	*Ø)ŠFð	*ús   „C2 Ã2DÄDc               ó$   € V ^8„  d   QhRRRRRR/# )r   r–   r   Útransmitted_idr   r2   r   )r   s   "r   r   r{   T  s&   € ÷ Mñ M˜Cð M°ð M¸ñ Mr   c                ó˜   € \        \        P                  ! V 4      4      pWR&   \        P                  ! V^RR7      P	                  R4      # )z¨Rebuild the exact bytes to send: deterministic json.dumps of the stored package
with install_id from the frozen ``sent_install_id`` column (resends are byte-identical).rª   T)ÚindentÚ	sort_keysr<   )rj   r«   r¬   ÚdumpsÚencode)r–   r·   r1   s   && r   Ú_bodyÚSharedMetricsSender._bodyS  s=   € ô ”t—z’z ,Ó/Ó0ˆØ .�ÑÜ�zŠz˜'¨!°tÔ<×CÑCÀGÓLÐLr   r¥   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r”   r   r¥   r,   r   r]   r   )r   s   "r   r   r{   [  s"   € ÷ ñ  ð ¨zð ÐPTñ r   c               ó8  € RP                  R V 4       4      pRp. VP                  4       OVNpVe   VR,          pVP                  V4       V P                  4       ;_uu_ 4       pVP	                  RV RV 2V4       RRR4       R#   + '       g   i     R# ; i)zìWrite send state for one package.

Guarded on send_state so a lapsed pass cannot resurrect a row another process already
finished. With ``token`` the write is also compare-and-set on claim_token: a
superseded claimant writes zero rows.
z, c              3  ó*   "  € T F	  q R 2x € K  	  R# 5i)z = ?Nr   )rc   Únames   & r   re   Ú,SharedMetricsSender._mark.<locals>.<genexpr>b  s   é € ÐB¹'°$ &¨¥»'ùs   ‚z3 AND (send_state IS NULL OR send_state = 'pending')Nz AND claim_token = ?zUPDATE package_outbox SET z WHERE package_id = ?)rš   ÚvaluesÚappendr‰   rg   )rƒ   r”   r¥   ÚcolumnsÚassignmentsÚ	predicateÚparamsrY   s   &&$,    r   Ú_markÚSharedMetricsSender._mark[  s‹   € ð —i‘iÑB¹'ÓBÓBˆØIˆ	Ø6˜Ÿ™Ó)Ð6¨:Ð6ˆØÒØÐ/Õ/ˆIØ�M‰M˜%Ô Ø�[‰[�]Œ]˜jØ×ÑØ,¨[¨MÐ9NÈyÈkÐZØô÷ �]�]Š]ús   Á%BÂB	c               ó$   € V ^8„  d   QhRRRRRR/# )r   r”   r   r¥   r,   r   r\   r   )r   s   "r   r   r{   n  s!   € ÷ ñ  sð °:ð À$ñ r   c                óŠ  € Vf   R#  V P                  4       pV\        \        R7      ,           pV P                  4       ;_uu_ 4       pVP	                  R\        V4      W\        V4      34      pVP                  ^8H  uuRRR4       #   + '       g   i     R# ; i  \         d    \        P                  RRR7        R# i ; i)aG  Atomically re-assert ownership and extend the lease (CAS, one row; rowcount == 1
is the only grant).

A read-only check is not enough: a claimant whose lease expired while suspended still
has its token in the row and would POST while another process reclaims. Renewing in
the same CAS keeps the 30s POST inside the 300s lease.
NFr_   aQ  
                        UPDATE package_outbox
                        SET next_attempt_at = ?
                        WHERE package_id = ?
                          AND claim_token = ?
                          AND (send_state IS NULL OR send_state = 'pending')
                          AND next_attempt_at > ?
                        z$Unable to renew shared-metrics claimT©Úexc_info)
r€   r   r™   r‰   rg   r   ÚrowcountÚ	Exceptionr²   r³   )rƒ   r”   r¥   rW   r¡   rY   Úcursors   &&&    r   Ú_renew_claimÚ SharedMetricsSender._renew_claimn  s¡   € ð Š=Ùð	Ø—)‘)“+ˆCØ¤	Ô2FÔ GÕGˆKØ—‘—” *Ø#×+Ñ+ðô   Ó,¨jÄÈCÃÐQó
�ð —‘¨!Ñ+÷ ——“ûô ô 	ä�N‰NÐAÈDˆNÔQÚð	ús/   ˆ?B Á6BÁ=
B ÂB	ÂB ÂB Â"CÃCc          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r   r”   r   Údelay_secondsr   r´   r¥   r,   r   r]   r   )r   s   "r   r   r{   �  s4   € ÷ 
ñ 
Øð
Ø.1ð
Ø;>ð
ØJTð
à	ñ
r   c               	óö   € V P                  4       P                  4       \        ^\        V4      4      ,           pV P	                  VVR\        \        P                  ! V\        R7      4      VR,          R7       R# )é   Úpending)Útz:Niô  N)r¥   Ú
send_stateÚnext_attempt_atÚ
last_errorN)	r€   Ú	timestamprS   r   rÊ   r   r   Úfromtimestampr   )rƒ   r”   rÖ   r´   r¥   Úretry_ats   &&&&$ r   Ú_deferÚSharedMetricsSender._defer�  s_   € ð —9‘9“;×(Ñ(Ó*¬S°´C¸Ó4FÓ-GÕGˆØ�
‰
ØØØ Ü&¤x×'=Ò'=¸hÌ3Ô'OÓPØ˜d•|ð 	ö 	
r   c               ó    € V ^8„  d   QhRRRR/# )r   Úpackagerj   r   r   r   )r   s   "r   r   r{   š  s   € ÷ 7Eñ 7E ð 7E¨#ñ 7Er   c                ój  a aa	€ VR,          oVP                  R4      o	S P                  VR,          VR,          4      pR VV V	3R llp\        ^S P                  ^,           4       EF‹  pS P	                  SS	4      '       g   \
        P                  RS4        R#  S P                  S P                  V\        R	7      pVP                  ^Ê8X  d1   S P                  SS	R
\        S P                  4       4      RR7        R
# VP                  \        9   d[   \
        P                  RSVP                  4       S P                  SS	RRVP                   RVP                   R,           2R7        R# VP                  R8X  d$   V! \#        VP$                  \&        4      R4      u # RVP                   2pVS P                  8¼  d   V! \&        V4      u # S P/                  S P1                  V4      4       EKŽ  	  V! \&        R4      #   \(         d%   p\+        T4      P,                   RT 2p Rp?L|Rp?ii ; i)zÝTry one package. Returns 'sent', 'rejected', or 'deferred'.

Delivery is at-least-once: renewal plus token-fenced writes close the claim->POST
and settle-after-reclaim gaps, but a suspension MID-POST can still duplicate.
r”   r˜   r–   r—   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Údelayr   r´   r   r   r   )r   s   "r   r   Ú3SharedMetricsSender._send_one.<locals>.__annotate__¤  s!   € ÷ 	ñ 	˜ð 	 cð 	¨cñ 	r   c                ó0   <€ SP                  SWSR 7       R# ))r¥   r    )rá   )rç   r´   r”   rƒ   r¥   s   &&€€€r   ÚdeferÚ,SharedMetricsSender._send_one.<locals>.defer¤  s   ø€ Ø�K‰K˜
 E¸ˆKÔ?Ùr   z:Shared-metrics claim on %s superseded or expired; yieldingr    r;   r   N)r¥   rÛ   Úsent_atrÝ   z8Telemetry package %s rejected with HTTP %s; not retryingr   zHTTP z: :Ni�  N)r¥   rÛ   rÝ   i­  zrate limitedzattempts exhausted)rF   r½   Úranger�   rÓ   r²   ÚinforO   r~   ÚREQUEST_TIMEOUT_SECONDSr+   rÊ   r   r€   Ú_PERMANENT_STATUSESr³   r.   rV   r-   Ú_FAILURE_BACKOFF_SECONDSrÑ   r®   r!   r   Ú_backoff)
rƒ   rä   r.   rê   ÚattemptrM   r´   rN   r”   r¥   s
   f&      @@r   Ú	_send_oneÚSharedMetricsSender._send_oneš  sù  ú€ ð ˜\Õ*ˆ
Ø—‘˜MÓ*ˆØ�z‰z˜' .Õ1°7¸9Õ3EÓFˆ÷	ò 	ô ˜Q × 2Ñ 2°QÕ 6×7ˆGð ×$Ñ$ Z°×7Ò7Ü—‘ØPÐR\ôò "ð3ØŸ:™: d§n¡n°dÔD[˜:Ó\�ð —?‘? cÔ)Ø—J‘JØ"¨%¸FÜ *¨4¯9©9«;Ó 7ÀDð ô ò "Ø—?‘?Ô&9Ô9Ü—N‘NØRØ"Ø Ÿ™ôð
 —J‘JØ"¨%¸JØ%*¨8¯?©?Ð*;¸2¸h¿m¹mÈDÕ>QÐ=RÐ#Sð ô ò &Ø—?‘? cÔ)Ù Ü,¨X×-AÑ-AÔC[Ó\Ø&óò ð
 ! §¡Ð 1Ð2�Ø˜$×,Ñ,Ô,ÙÔ5°vÓ>Ò>Ø�K‰K˜Ÿ™ gÓ.×/ñO 8ñR Ô-Ð/CÓDÐDøô? ô 8Ü  ›I×.Ñ.Ð/¨r°#°Ð7•ûð8ús   Â"HÈH2ÈH-È-H2c               ó    € V ^8„  d   QhRRRR/# )r   ró   r   r   Úfloatr   )r   s   "r   r   r{   Ô  s   € ÷ ]ñ ]˜#ð ] %ñ ]r   c                ój   € \         P                  ! ^ \        \        V ^,
          ,          ,          4      # )z1s, 5s, 25s with full jitter.)ÚrandomÚuniformÚ_BACKOFF_BASE_SECONDSÚ_BACKOFF_FACTOR)ró   s   &r   rò   ÚSharedMetricsSender._backoffÓ  s%   € ô �~Š~˜aÔ!6¼/ÈgÐXYÍkÕ:ZÕ![Ó\Ð\r   c               ó   € V ^8„  d   QhRR/# )r   r   r   r   )r   s   "r   r   r{   Ú  s   € ÷  ñ  ˜kñ  r   c           	     ó’  € \        4       p\        4       p\        \        4       FË  pV P	                  4       '       g+   \
        P                  R4       V P                  RR7        V#  V P                  V P                  4       V4      pTf    T# TP                  TR,          4       TP                  R4      '       d   R	pM T P                  T4      p\        Y\!        Y4      ^,           4       KÍ  	  V#   \         d    \
        P                  RRR7         T# i ; i  \         d    \
        P                  R
RR7       Rp Lri ; i)z“Run one bounded pass, one claim+send at a time, re-checking consent before each
send so revoking `send` mid-pass stops the remainder. Never raises.z2Shared-metrics sending disabled mid-pass; stoppingF)r[   z(Unable to select shared-metrics packagesTrÎ   r”   r•   r   z%Unable to send shared-metrics packager    )r   Úsetrí   ÚMAX_PACKAGES_PER_PASSÚ_still_consentedr²   rî   Ú
_reconciler¦   r€   rÑ   r³   ÚaddrF   rô   ÚsetattrÚgetattr)rƒ   ÚoutcomerŒ   r‘   rä   Úresults   &     r   Úsend_pendingÚ SharedMetricsSender.send_pendingÚ  s1  € ô “-ˆÜ›ˆäÔ,Ö-ˆAØ×(Ñ(×*Ò*ô —‘ÐPÔQØ—‘¨U�Ô3Øð( ˆð'Ø×*Ñ*¨4¯9©9«;¸Ó=�ð ŠØð ˆð �H‰H�W˜\Õ*Ô+Ø�{‰{˜6×"Ò"à#‘ð(Ø!Ÿ^™^¨GÓ4�Fô �G¤W¨WÓ%=ÀÕ%AÖBñ3 .ð4 ˆøô# ô Ü—‘ÐIÐTX�ÔYÙð ˆð#ûô !ô (Ü—N‘NÐ#JÐUY�NÔZØ'’Fð(ús$   Á( C5ÃDÃ5"DÄDÄ$EÅEc               ó    € V ^8„  d   QhRRRR/# )r   r[   r\   r   r]   r   )r   s   "r   r   r{   ü  s   € ÷ Xñ X¨$ð X°4ñ Xr   c               óú   €  V P                  4       ;_uu_ 4       p\        W!V P                  4       R7       RRR4       R#   + '       g   i     R# ; i  \         d    \        P                  RRR7        R# i ; i)z1Run the single consent writer from within a pass.)rW   Nz*Unable to reconcile shared-metrics consentTrÎ   )r‰   rs   r€   rÑ   r²   r³   )rƒ   r[   rY   s   &$ r   r  ÚSharedMetricsSender._reconcileü  sS   € ð	XØ—‘—” *Ü& zÀTÇYÁYÃ[ÕQ÷ ——’ûäô 	XÜ�N‰NÐGÐRVˆN×Wð	Xús-   ‚A šA ¶A Á A	ÁA ÁA Á"A:Á9A:c               ó   € V ^8„  d   QhRR/# )r   r   r\   r   )r   s   "r   r   r{     s   € ÷ 
ñ 
 $ñ 
r   c                ó¨   € V P                   f   R#  \        V P                  4       4      #   \         d    \        P	                  RRR7        R# i ; i)z€Re-read profile-owned send consent: docs promise ``send: false`` stops transmission
immediately, and a pass can run for minutes.Tz7Unable to confirm shared-metrics send consent; stoppingrÎ   F)r‚   r\   rÑ   r²   r³   )rƒ   s   &r   r  Ú$SharedMetricsSender._still_consented  sP   € ð ×ÑÒ&Ùð	Ü˜×+Ñ+Ó-Ó.Ð.øÜô 	ä�N‰NÐTÐ_cˆNÔdÚð	ús   ’+ «"AÁA)r‚   r~   r�   r€   rO   r   r}   )r!   r"   r#   r$   r%   rO   Útimerw   r   ÚMAX_ATTEMPTSr…   r   r‰   r¦   Ústaticmethodrž   r½   rÊ   rÓ   rá   rô   rò   r	  r  r  r'   r   r   r   ru   ru   Î   sÖ   † Ù>ð,ð
 ð,ð �j‰jð,ð ð,ð )ð,ð ÷,ð* ñ!ó ð!õ6ðp ô'ó ð'ðV ôMó ðMð¸D÷ õ&ð>
ØW[÷
õ7Eðr ô]ó ð]õ õDX÷
ñ 
r   ru   i„  i �' )3r%   Ú
__future__r   r6   r«   Úloggingrù   Úsqlite3r  Úurllib.errorrB   Úurllib.requestrŸ   Ú
contextlibr   Údataclassesr   r   r   r   r   Úagent.retry_utilsr	   Úhermes_cli.sqlite_utilr
   Úshared_metricsr   r   Ú	getLoggerr!   r²   rï   r  rû   rü   r@   r  r™   rñ   Ú	frozensetrð   rœ   ri   r   r   r*   rO   rV   rs   r›   ru   r   r   r   Ú<module>r      s  ðñõ #ã Û Û Û Û Û Û Û Û Ý %Ý !ß 7Ó 7å 7Ý ,ç 0à	×	Ò	˜8Ó	$€ð Ð ð €ØÐ Ø€ð Ð ð Ð ð Ð ð #Ð ñ    c 
Ó+Ð ð Ð ð
 )Ð õ9ð
 ÷ð ó ðñ �Ô÷ð ó ðõ
õ:-ð>
ð  ÷	>
ðHÐ ÷@ó @r   