
    KiT                        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 G d ded         Zy)a!  Rate limit admission control dependency.

Caps how many times a task (or a per-parameter scope) can execute within a
sliding window.  Uses a Redis sorted set as a sliding window log: members are
``{execution_key}:{now_ms}`` strings (unique per attempt), scores are
millisecond timestamps.
    )annotationsN)	timedelta)TracebackType)Any   )AdmissionBlocked
Dependencycurrent_docketcurrent_executionaa  
local key       = KEYS[1]
local member    = ARGV[1]
local now_ms    = tonumber(ARGV[2])
local window_ms = tonumber(ARGV[3])
local limit     = tonumber(ARGV[4])
local ttl_ms    = tonumber(ARGV[5])

-- Prune entries older than the window
local cutoff = now_ms - window_ms
redis.call('ZREMRANGEBYSCORE', key, '-inf', cutoff)

-- Count remaining entries
local count = redis.call('ZCARD', key)

if count < limit then
    -- Under limit: record this execution and set safety TTL
    redis.call('ZADD', key, now_ms, member)
    redis.call('PEXPIRE', key, ttl_ms)
    return {1, 0}
end

-- Over limit: compute when the oldest entry will expire
local oldest = redis.call('ZRANGE', key, 0, 0, 'WITHSCORES')
local oldest_score = tonumber(oldest[2])
local retry_after = oldest_score + window_ms - now_ms
if retry_after < 1 then
    retry_after = 1
end
return {2, retry_after}
   c                  Z    e Zd ZdZddd	 	 	 	 	 	 	 	 	 d	dZd
dZddZ	 	 	 	 	 	 	 	 ddZy)	RateLimita;  Cap executions within a sliding time window.

    Uses a Redis sorted set as a sliding window log.  Each execution adds
    an entry; entries older than the window are pruned atomically.

    When the limit is reached:
    - ``drop=False`` (default): the task is rescheduled to when a slot opens.
    - ``drop=True``: the task is quietly dropped.

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

        # Per-task: max 10 per minute, excess rescheduled
        async def sync_data(
            rate: RateLimit = RateLimit(10, per=timedelta(minutes=1)),
        ) -> None: ...

        # Per-parameter: max 5 per minute per customer, excess dropped
        async def process_customer(
            customer_id: Annotated[int, RateLimit(5, per=timedelta(minutes=1), drop=True)],
        ) -> None: ...
    FN)dropscopec               t    || _         || _        || _        || _        d | _        d | _        d | _        d | _        y N)limitperr   r   _argument_name_argument_value_ratelimit_key_member)selfr   r   r   r   s        j/home/jay/workspace/scripts/.codegraph-venv/lib/python3.12/site-packages/docket/dependencies/_ratelimit.py__init__zRateLimit.__init__Y   s?     
	
*.$(*.#'    c                    t        | j                  | j                  | j                  | j                        }||_        ||_        |S )N)r   r   r   )r   r   r   r   r   r   r   )r   namevaluebounds       r   bind_to_parameterzRateLimit.bind_to_parameterj   s7    $**$(($**U# %r   c           	       K   t        j                         }t        j                         }| j                  xs |j                  }| j
                  | d| j
                   d| j                   }n| d|j                   }t        | j                  j                         dz        }t        t        j                         dz        }|dz  }|j                   d| }|j                         4 d {   }	|	j                  t              }
 |
|g|||| j                   |g       d {   }d d d       d {    d   }|d   }|t"        k(  r|| _        || _        | S d| j                    d	| j                   d
| }| j(                  rt+        ||d      t+        ||t-        |            7 7 7 |# 1 d {  7  sw Y   xY ww)Nz:ratelimit::i  r   )keysargsr   r   zrate limit (/z) on F)reason
reschedule)milliseconds)r'   retry_delay)r   getr
   r   r   r   r   function_nameintr   total_secondstimekeyredisregister_script_RATELIMIT_LUAr   _ACTION_PROCEEDr   r   r   r   r   )r   	executiondocketr   ratelimit_key	window_msnow_msttl_msmemberr1   scriptresultactionretry_after_msr'   s                  r   
__aenter__zRateLimit.__aenter__p   s    %))+	##%

)fkk*'T%8%8$94;O;O:PQ   %g[1H1H0IJM..0478	TYY[4'(QMM?!F8,<<> 	 	U**>:F&,#_fiVD' !F	 	 _$"/D!DLK

|1TXXJeM?K99"9VNN!~>
 	
)	!	 	 	 	s[   C/G1F12G53F7(F3)F7-G8F59A9G3F75G7G	=G >G	Gc                v  K   || j                   t        |t              rz| j                  J t	        j
                         }|j                         4 d {   }|j                  | j                  | j                          d {    d d d       d {    y y y y 7 F7 7 # 1 d {  7  sw Y   y xY wwr   )r   
issubclassr   r   r
   r+   r1   zrem)r   exc_type	exc_value	tracebackr6   r1   s         r   	__aexit__zRateLimit.__aexit__   s      DLL$<($45**666'++-!<<> H HU**T%8%8$,,GGGH H H 6 %=HGH H H HsZ   AB9BB9*B$B B$
B9B"	B9 B$"B9$B6*B-+B62B9)
r   r-   r   r   r   boolr   z
str | NonereturnNone)r   strr   r   rI   r   )rI   r   )rD   ztype[BaseException] | NonerE   zBaseException | NonerF   zTracebackType | NonerI   rJ   )__name__
__module____qualname____doc__r   r!   r@   rG    r   r   r   r   B   s    6  (( 	(
 ( ( 
(")
VH,H (H (	H
 
Hr   r   )rO   
__future__r   r/   datetimer   typesr   typingr   _baser   r	   r
   r   r3   r4   _ACTION_BLOCKEDr   rP   r   r   <module>rW      sJ    #     R R@ dH
;' dHr   