
    4Rj                         U d dl mZ d dlZd dlZd dlZd dlmZmZ d dlZddl	m
Z
mZ ddlmZ ddlmZmZ dd	lmZ d
gZ ej(                  e      Zded<   dZ G d d
      Zy)    )annotationsN)CallableOptional   )AccessTokenAccessTokenProvider)WorkloadIdentityError)ADVISORY_REFRESH_SECONDSMANDATORY_REFRESH_SECONDS   )AnthropicError
TokenCachezlogging.Loggerlog   c                  h    e Zd ZdZeeej                  d	 	 	 	 	 	 	 	 	 d	dZd
dZddZ	ddZ
ddZy)r   u2  Thread-safe cache wrapping an :class:`AccessTokenProvider` with two-tier
    proactive refresh and single-flight semantics.

    Refresh policy on each :meth:`get_token` call:

    * No cached token → call provider (blocking), cache, return.
    * Cached with ``expires_at=None`` → return cached forever (never refresh).
    * More than ``advisory_refresh_seconds`` remaining → return cached.
    * Between ``mandatory_refresh_seconds`` and ``advisory_refresh_seconds``
      remaining (advisory window) → try provider; on success swap cache; on
      failure log a warning and return the stale cached token. If another
      caller is already refreshing, the advisory caller just returns the
      cached token — no second refresh, no waiting.
    * Less than ``mandatory_refresh_seconds`` remaining or already expired
      (mandatory window) → call provider; on failure RAISE. Concurrent
      mandatory callers wait on a shared ``Event`` so exactly one provider
      call is in flight.

    The lock is released before the provider call so a 30-second HTTP POST
    doesn't serialize unrelated callers through a single thread. This matters
    under async: ``asyncify(get_token)`` runs on the thread pool, and holding
    the lock across the network call would pin an async worker for the whole
    exchange.
    )advisory_refresh_secondsmandatory_refresh_secondstime_sourcec                   || _         || _        || _        || _        t	        j
                         | _        d | _        d | _        d| _	        d| _
        y )NFg        )	_provider	_advisory
_mandatory_time_source	threadingLock_lock_cached_refresh_event_next_force_last_advisory_failure_time)selfproviderr   r   r   s        h/var/www/html/meridian/meridian-ai/venv/lib/python3.12/site-packages/anthropic/lib/credentials/_cache.py__init__zTokenCache.__init__3   sT     "13'^^%
.2 :> ! 36(    c                   	 | j                  |      S # t        $ r(}dt        |      vr | j                         cY d}~S d}~ww xY w)z@Invoke ``self._provider``, tolerating legacy zero-arg callables.)force_refreshr'   N)r   	TypeErrorstr)r!   forceerrs      r#   _invoke_providerzTokenCache._invoke_providerL   sF    	$>>>66 	$ c#h.>>##	$s    	AA A Ac                r   | j                   5  | j                  }ddd       	 | j                        }| j                   5  d| _        ddd       |S # 1 sw Y   :xY w# t        $ rA}|j                  dk7  r t
        j                  d       | j                  d      }Y d}~od}~ww xY w# 1 sw Y   |S xY w)zBCall the provider, retrying once on a 401 from the token endpoint.N)r*   i  z*Token provider returned 401; retrying onceTF)r   r   r,   r	   status_coder   debug)r!   r*   resultr+   s       r#   _call_providerzTokenCache._call_providerX   s     ZZ 	%$$E	%	7***7F ZZ 	%$D	%	% 	% % 	7#%IIBC***6F		7
	%s.   AA B,A	B)(7B$$B),B6c                <   	 d}d}| j                   5  | j                  }||j                  |j                  cddd       S |j                  | j	                         z
  }|| j
                  kD  r|j                  cddd       S || j                  kD  rg| j                  |j                  cddd       S | j	                         | j                  z
  t        k  r|j                  cddd       S |}t        |      }| j                  | j                  }nt        j                         | _        d}ddd       |j                          H	 | j                         }| j                   5  || _        | j                  }d| _        ddd       J |j!                          |j                  S # 1 sw Y   }xY w# t        $ r}| j                   5  | j                  }d| _        ddd       n# 1 sw Y   nxY wJ |j!                          |t#        |t$        t&        j(                  f      r_t*        j-                  d||       | j                   5  | j	                         | _        ddd       n# 1 sw Y   nxY w|j                  cY d}~S  d}~ww xY w# 1 sw Y   xY w)z5Return a valid bearer token, refreshing if necessary.Nr   zGAdvisory token refresh failed (%ds remaining); serving cached token: %s)r   r   
expires_attokenr   r   r   r   r     ADVISORY_REFRESH_BACKOFF_SECONDSintr   Eventwaitr1   BaseExceptionset
isinstancer   httpx	HTTPErrorr   warning)	r!   advisory_fallbackremaining_secondscached	remainingwaiter_eventfreshr+   releaseds	            r#   	get_tokenzTokenCache.get_tokeni   s}   7; ! (%((0%||	( (
 !' 1 1D4E4E4G GI 4>>1%||( ( !4??2  ..:#)<<( (   ,,.1Q1QQTtt#)<<#( ($ -3),/	N)&&2>B>Q>QL +4//*;D'#'L7(: '!!# ++-$  +$..&*#+ '''LLN;;C( (T ! ZZ /#22H*.D'/ / /  +++$0ZnV[VeVeEf5gKKa)
  O;?;L;L;N8O O O,222"+ +s   &F)7F)&F)3/F),AF)
F5 &J)F25	J>J	
G'	J	'G0	,A J	I+"	J	+I4	0J	JJ		JJc                b    | j                   5  d| _        d| _        ddd       y# 1 sw Y   yxY w)zClear the cached token so the next :meth:`get_token` re-invokes the provider.

        Also sets a one-shot ``force_refresh`` flag so on-disk providers skip
        their freshness short-circuit instead of re-serving the revoked token.
        NT)r   r   r   )r!   s    r#   
invalidatezTokenCache.invalidate   s/     ZZ 	$DL#D	$ 	$ 	$s   %.N)
r"   r   r   r6   r   r6   r   zCallable[[], float]returnNone)r*   boolrI   r   )rI   r   )rI   r)   )rI   rJ   )__name__
__module____qualname____doc__r
   r   timer$   r,   r1   rF   rH    r%   r#   r   r      sb    : )A)B+/996%6 #&	6
 $'6 )6 
62
$"FP$r%   )
__future__r   rP   loggingr   typingr   r   r<   _typesr   r   	_workloadr	   
_constantsr
   r   _exceptionsr   __all__	getLoggerrL   r   __annotations__r5   r   rQ   r%   r#   <module>r\      sU    "    %  4 , K ).'g''1^ 1
 $%  `$ `$r%   