Ë
    †Kài°  ã                  ó„   — d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	 ddl
mZmZmZmZ d	ZdZd
ZdZ G d„ ded   «      Zy)z×Debounce (trailing-edge / settle) admission control dependency.

Waits for submissions to settle, then fires once.  Uses two Redis keys
(winner + last_seen) so only one task bounces while the rest immediately
drop.
é    )ÚannotationsN)Ú	timedelta)ÚTracebackType)ÚAnyé   )ÚAdmissionBlockedÚ
DependencyÚcurrent_docketÚcurrent_executiona	  
local winner_key  = KEYS[1]
local seen_key    = KEYS[2]
local my_key      = ARGV[1]
local settle_ms   = tonumber(ARGV[2])
local now_ms      = tonumber(ARGV[3])
local ttl_ms      = tonumber(ARGV[4])

local winner = redis.call('GET', winner_key)

if not winner then
    -- No winner: I become winner, record last_seen = now
    redis.call('SET', winner_key, my_key, 'PX', ttl_ms)
    redis.call('SET', seen_key, tostring(now_ms), 'PX', ttl_ms)
    return {2, settle_ms}
end

if winner == my_key then
    -- I'm the winner, returning from reschedule
    local last_seen_str = redis.call('GET', seen_key)
    local last_seen = tonumber(last_seen_str) or 0
    local elapsed = now_ms - last_seen

    if elapsed >= settle_ms then
        -- Settled: clean up and proceed
        redis.call('DEL', winner_key, seen_key)
        return {1, 0}
    else
        -- Not settled yet: refresh TTLs and reschedule for remaining time
        local remaining = settle_ms - elapsed
        redis.call('PEXPIRE', winner_key, ttl_ms)
        redis.call('PEXPIRE', seen_key, ttl_ms)
        return {2, remaining}
    end
end

-- Someone else is the winner: update last_seen and refresh TTLs
redis.call('SET', seen_key, tostring(now_ms), 'PX', ttl_ms)
redis.call('PEXPIRE', winner_key, ttl_ms)
return {3, 0}
é   é   c                  óV   — e Zd ZU dZdZded<   ddœdd„Zdd„Zdd	„Z	 	 	 	 	 	 	 	 dd
„Z	y)ÚDebounceuË  Wait for submissions to settle, then fire once.

    Uses two Redis keys per scope â€” a "winner" key (which execution gets
    to proceed) and a "last_seen" timestamp.  Only the winner bounces
    via reschedule; all other submissions are immediately dropped.

    Works both as a default parameter and as ``Annotated`` metadata::

        # Per-task: wait for 5s of quiet, then execute once
        async def process_webhooks(
            debounce: Debounce = Debounce(timedelta(seconds=5)),
        ) -> None: ...

        # Per-parameter: independent settle window per customer
        async def sync_customer(
            customer_id: Annotated[int, Debounce(timedelta(seconds=5))],
        ) -> None: ...
    TÚboolÚsingleN©Úscopec               ó<   — || _         || _        d | _        d | _        y ©N)Úsettler   Ú_argument_nameÚ_argument_value)Úselfr   r   s      úi/home/jay/workspace/scripts/.codegraph-venv/lib/python3.12/site-packages/docket/dependencies/_debounce.pyÚ__init__zDebounce.__init__b   s    € ØˆŒØˆŒ
Ø*.ˆÔØ$(ˆÕó    c                ód   — t        | j                  | j                  ¬«      }||_        ||_        |S )Nr   )r   r   r   r   r   )r   ÚnameÚvalueÚbounds       r   Úbind_to_parameterzDebounce.bind_to_parameterh   s+   € Ü˜Ÿ™¨D¯J©JÔ7ˆØ#ˆÔØ %ˆÔØˆr   c              ƒ  ój  K  — t        j                  «       }t        j                  «       }| j                  xs |j                  }| j
                  #| j
                  › d| j                  › }|› d|› }n|j                  }|› d|› }|› d|› d}|› d|› d}t        | j                  j                  «       dz  «      }t        t        j                  «       dz  «      }	|dz  }
|j                  «       4 ƒd {  –—† }|j                  t        «      } |||g|j                  ||	|
g¬«      ƒ d {  –—† }d d d «      ƒd {  –—†  d	   }|d
   }|t         k(  r| S d| j                  › d|› }|t"        k(  rt%        ||t'        |¬«      ¬«      ‚t%        ||d¬«      ‚7 Œ¡7 Œl7 Œ^# 1 ƒd {  –—†7  sw Y   ŒnxY w­w)Nú:z
:debounce:z:{z}:winnerz}:last_seeniè  é
   )ÚkeysÚargsr   r   z
debounce (z) on )Úmilliseconds)ÚreasonÚretry_delayF)r(   Ú
reschedule)r   Úgetr
   r   r   r   r   Úfunction_nameÚintr   Útotal_secondsÚtimeÚredisÚregister_scriptÚ_DEBOUNCE_LUAÚkeyÚ_ACTION_PROCEEDÚ_ACTION_RESCHEDULEr   r   )r   Ú	executionÚdocketr   Úhash_tagÚbase_keyÚ
winner_keyÚseen_keyÚ	settle_msÚnow_msÚttl_msr0   ÚscriptÚresultÚactionÚremaining_msr(   s                    r   Ú
__aenter__zDebounce.__aenter__n   sÌ  è ø€ Ü%×)Ñ)Ó+ˆ	Ü×#Ñ#Ó%ˆà—
‘
Ò)˜fŸk™kˆØ×ÑÐ*Ø×-Ñ-Ð.¨a°×0DÑ0DÐ/EÐFˆHØ˜ 
¨8¨*Ð5‰Hà ×.Ñ.ˆHØ˜ 
¨8¨*Ð5ˆHð !z  X J¨iÐ8ˆ
ØZ˜s 8 *¨LÐ9ˆä˜Ÿ™×1Ñ1Ó3°dÑ:Ó;ˆ	Ü”T—Y‘Y“[ 4Ñ'Ó(ˆØ˜R‘ˆà—<‘<“>÷ 	ð 	 UØ×*Ñ*¬=Ó9ˆFÙ&,Ø  (Ð+Ø—m‘m Y°¸Ð?ô'÷ !ˆF÷	÷ 	ð ˜‘ˆØ˜a‘yˆà”_Ò$ØˆKà˜dŸk™k˜]¨%°¨zÐ:ˆàÔ'Ò'Ü"ØØÜ%°<Ô@ôð ô ˜y°ÀEÔJÐJð/	øð!øð	ø÷ 	÷ 	ñ 	üs[   ‚C4F3Ã6FÃ7F3Ã:3FÄ-FÄ.FÄ2F3Ä=FÄ>AF3ÆFÆF3ÆF0Æ$F'Æ%F0Æ,F3c              ƒ  ó   K  — y ­wr   © )r   Úexc_typeÚ	exc_valueÚ	tracebacks       r   Ú	__aexit__zDebounce.__aexit__›   s   è ø€ ð 	ùs   ‚)r   r   r   z
str | NoneÚreturnÚNone)r   Ústrr   r   rJ   r   )rJ   r   )rF   ztype[BaseException] | NonerG   zBaseException | NonerH   zTracebackType | NonerJ   rK   )
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Ú__annotations__r   r!   rC   rI   rE   r   r   r   r   L   sR   … ñð& €FˆDÓàAEõ )óó+KðZà,ðð (ðð (ð	ð
 
ôr   r   )rP   Ú
__future__r   r/   Údatetimer   Útypesr   Útypingr   Ú_baser   r	   r
   r   r2   r4   r5   Ú_ACTION_DROPr   rE   r   r   ú<module>rX      sN   ðñõ #ã Ý Ý Ý ç RÓ Rð(€ðT €ØÐ Ø€ôUˆz˜*Ñ%õ Ur   