Ë
    tPêjE  ã                   ó2  — U d Z ddlZddlmZmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZmZ ed   Zeez  ez  dz  Zeeef   Z ed	d	¬
«       G d„ d«      «       Z e
 edd¬«       edd¬«       edd¬«       edd¬«       edd¬«       eddd	¬«      dœ«      Zeeeef      ed<   dZeed<   dZeed <   d!Zeed"<    e
i eD � ci c]  } | d#“Œ c} ¥eD � ci c]  } | d$“Œ c} ¥«      Zeeeef      ed%<   d&ee   d'efd(„Zd)ed'efd*„Zd)ed'efd+„Zd)ed'efd,„Zd-ed.ed'e ed/f   fd0„Z!d1ee   d'efd2„Z"d-ed3ee   d'e e e ed/f   ef   d/f   fd4„Z#d-ed5e ed/f   d.ed'e ed/f   fd6„Z$d-ed'e ed/f   fd7„Z%d-ed8ee e ed/f   ef      d'e ee ed/f   f   fd9„Z&yc c} w c c} w ):aÚ  One multi-row ``INSERT ... ON CONFLICT DO UPDATE`` per batch of daily spend rows.

Emitting a statement per aggregated key put every replica's flush on the database as
hundreds of separate statements against the same handful of hot rows, each holding its
row locks for the rest of the enclosing batch transaction. Folding a batch into a single
statement keeps the aggregation identical while collapsing both the statement count and
the window in which those locks are held.
é    N)ÚMappingÚSequence)Ú	dataclass)Úgroupby)ÚMappingProxyType)ÚFinalÚLiteral)ÚuserÚteamÚorgÚtagÚend_userÚagentT)ÚfrozenÚslotsc                   ó4   — e Zd ZU dZeed<   eed<   dZeed<   y)ÚDailySpendTablez4The physical table behind one entity's daily rollup.ÚnameÚentity_id_columnFÚcarries_request_idN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚstrÚ__annotations__r   Úbool© ó    úm/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/db/daily_spend_bulk_upsert.pyr   r      s   … á>à
ƒIØÓØ$Ð˜Ô$r   r   ÚLiteLLM_DailyUserSpendÚuser_id)r   r   ÚLiteLLM_DailyTeamSpendÚteam_idÚLiteLLM_DailyOrganizationSpendÚorganization_idÚLiteLLM_DailyEndUserSpendÚend_user_idÚLiteLLM_DailyAgentSpendÚagent_idÚLiteLLM_DailyTagSpendr   )r   r   r   )r
   r   r   r   r   r   ÚDAILY_SPEND_TABLES)ÚdateÚapi_keyÚmodelÚcustom_llm_providerÚmcp_namespaced_tool_nameÚendpointÚ_KEY_COLUMNS)Úprompt_tokensÚcompletion_tokensÚapi_requestsÚsuccessful_requestsÚfailed_requestsÚcache_read_input_tokensÚcache_creation_input_tokensÚcompression_saved_tokensÚ_COUNTER_COLUMNS)ÚspendÚcompression_savings_spendÚprompt_caching_savings_spendÚ&gateway_injected_caching_savings_spendÚautorouter_savings_spendÚ_SPEND_COLUMNSÚbigintzdouble precisionÚ_CASTSÚcolumnsÚreturnc                 ó2   — dj                  d„ | D «       «      S )Nú, c              3   ó(   K  — | ]
  }d |› d �–— Œ y­w)ú"Nr   )Ú.0Úcolumns     r    ú	<genexpr>z_quoted.<locals>.<genexpr>N   s   è ø€ Ò9 v�q˜˜ ”]Ñ9ùs   ‚)Újoin)rE   s    r    Ú_quotedrO   M   s   € Ø�9‰9Ñ9°Ô9Ó9Ð9r   Úvaluec                 ó    — | €dS t        | «      S )NÚ )r   ©rP   s    r    Ú_as_textrT   Q   s   € Ø�ˆ2Ð.¤C¨£JÐ.r   c                 óH   — t        | t        t        f«      rt        | «      S dS )Nr   ©Ú
isinstanceÚintÚfloatrS   s    r    Ú_as_intrZ   U   s   € Ü# E¬C´¨<Ô8Œ3ˆu‹:Ð?¸aÐ?r   c                 óH   — t        | t        t        f«      rt        | «      S dS )Ng        rV   rS   s    r    Ú	_as_floatr\   Y   s   € Ü% e¬c´5¨\Ô:Œ5�‹<ÐCÀÐCr   ÚtableÚtransaction.c                 óP   ‡— t        ˆfd„| j                  gt        ¢­D «       «      S )zJThe tuple the database arbitrates the upsert on, normalized free of NULLs.c              3   óR   •K  — | ]  }t        ‰j                  |«      «      –— Œ  y ­w©N)rT   Úget©rK   rL   r^   s     €r    rM   zconflict_key.<locals>.<genexpr>_   s   øè ø€ Òi°v”˜+Ÿ/™/¨&Ó1×2Ñiùó   ƒ$')Útupler   r3   )r]   r^   s    `r    Úconflict_keyrf   ]   s#   ø€ äÓiÀ%×BXÑBXÐAhÔ[gÑAhÔiÓiÐir   Úgroupc           	      óì   ‡— t        | «      dk(  r| d   S i | d   ¥t        D �‡ci c]  Š‰t        ˆfd„| D «       «      “Œ c}¥t        D �‡ci c]  Š‰t        ˆfd„| D «       «      “Œ c}¥S c c}w c c}w )Né   r   c              3   óR   •K  — | ]  }t        |j                  ‰«      «      –— Œ  y ­wra   ©rZ   rb   ©rK   ÚrowrL   s     €r    rM   z_merge.<locals>.<genexpr>g   s   øè ø€ ÒA°C”w˜sŸw™w v›×/ÑAùrd   c              3   óR   •K  — | ]  }t        |j                  ‰«      «      –— Œ  y ­wra   ©r\   rb   rl   s     €r    rM   z_merge.<locals>.<genexpr>h   s   øè ø€ ÒC°c”y §¡¨£×1ÑCùrd   )Úlenr<   ÚsumrB   )rg   rL   s    `r    Ú_mergerr   b   s}   ø€ Ü
ˆ5ƒz�Q‚Ø�Q‰xˆðØ
�‰(ðäP`×
aÀfˆ6”3ÓA¸5ÔAÓAÑAÒ
aðô Sa×
aÈˆ6”3ÓC¸UÔCÓCÑCÒ
aðð ùâ
aùÚ
as   ¤A,ÁA1Útransactionsc                 ód   ‡ — t        |ˆ fd„¬«      }t        d„ t        |ˆ fd„¬«      D «       «      S )a÷  Batch entries keyed by the conflict tuple, in a deterministic order.

    The queue keys transactions by their raw field values, so two entries differing only
    in a NULL versus an empty member reach the writer separately while arbitrating to the
    same row. Postgres rejects a statement whose values touch one row twice, so they are
    summed here into the single row they were always destined to become. Ordering by the
    key keeps concurrent writers taking row locks in the same sequence.
    c                 ó   •— t        ‰| «      S ra   ©rf   )r^   r]   s    €r    ú<lambda>z'merge_by_conflict_key.<locals>.<lambda>x   s   ø€ Ä,ÈuÐVaÓBb€ r   )Úkeyc              3   óN   K  — | ]  \  }}|t        t        |«      «      f–— Œ y ­wra   )rr   re   )rK   rx   rg   s      r    rM   z(merge_by_conflict_key.<locals>.<genexpr>y   s"   è ø€ Òv±°°e�#”vœe E›lÓ+Ô,Ñvùs   ‚#%c                 ó   •— t        ‰| «      S ra   rv   )Útr]   s    €r    rw   z'merge_by_conflict_key.<locals>.<lambda>y   s   ø€ Ô^jÐkpÐrsÓ^t€ r   )Úsortedre   r   )r]   rs   Úordereds   `  r    Úmerge_by_conflict_keyr~   l   s+   ø€ ô ˜LÓ.bÔc€GÜÑv¼wÀwÓTtÔ?uÔvÓvÐvr   rx   c                 óD  ‡— ‰j                  d«      }t        t        j                  «       «      g|¢‰j                  d«      €d nt	        ‰j                  d«      «      ‘ˆfd„t
        D «       ¢ˆfd„t        D «       ¢| j                  r|€d f¢­S t	        |«      f¢­S d¢­S )NÚ
request_idÚmodel_groupc              3   óR   •K  — | ]  }t        ‰j                  |«      «      –— Œ  y ­wra   rk   rc   s     €r    rM   z_row_params.<locals>.<genexpr>†   s   øè ø€ Ò	J¨vŒ'�+—/‘/ &Ó)×
*Ñ	Jùrd   c              3   óR   •K  — | ]  }t        ‰j                  |«      «      –— Œ  y ­wra   ro   rc   s     €r    rM   z_row_params.<locals>.<genexpr>‡   s   øè ø€ Ò	J°Œ)�K—O‘O FÓ+×
,Ñ	Jùrd   r   )rb   r   ÚuuidÚuuid4rT   r<   rB   r   )r]   rx   r^   r€   s     ` r    Ú_row_paramsr†   |   sÁ   ø€ ð
 $Ÿ™¨Ó5€JäŒD�J‰J‹LÓðà	ðð —‘ Ó.Ð6‰¼HÀ[Ç_Á_ÐUbÓEcÓ<dðó 
KÔ9IÔ	Jð	ó
 
K¼>Ô	Jðð FK×E]ÒE]�:Ð%ˆ4Ð
Añð ô ,4°JÓ+?Ð
Añð ð dfñð r   c                 ól   — d| j                   gt        ¢d‘t        ¢t        ¢| j                  rd¢­S d¢­S )NÚidr�   )r€   r   )r   r3   r<   rB   r   )r]   s    r    Ú_insert_columnsr‰   Œ   sa   € àØ×Ñðô 
ðð 	ð	ô
 
ðô 
ðð #×5Ò5ˆ/ñð ð <>ñð r   Úbatchc                 ó¨  ‡ ‡‡— t        ‰ «      Šd‰ j                  › d�Šdj                  ˆfd„t        t	        |«      «      D «       «      }dj                  ˆfd„g t
        ¢t        ¢­D «       «      }‰ j                  rd‰› d�nd}d‰› d	t        ‰«      › d
|› dt        ‰ j                  gt        ¢­«      › d|› |› d�}|t        ˆ fd„|D «       «      fS )zMThe single statement writing one merged batch, plus its positional arguments.rJ   rH   c              3   ót   •‡K  — | ].  Šd dj                  ˆˆfd„t        ‰«      D «       «      z   dz   –— Œ0 y­w)ú(rH   c              3   ó€   •K  — | ]5  \  }}d ‰t        ‰«      z  |z   dz   › dt        j                  |d«      › �–— Œ7 y­w)ú$ri   z::ÚtextN)rp   rD   rb   )rK   ÚoffsetrL   rE   Ú	row_indexs      €€r    rM   z.build_bulk_upsert.<locals>.<genexpr>.<genexpr>¡   sJ   øè ø€ ò 
á�˜ð �	œC ›LÑ(¨6Ñ1°AÑ5Ð6°b¼¿¹ÀFÈFÓ9SÐ8TÔUñ
ùs   ƒ;>z, (NOW() AT TIME ZONE 'UTC'))N)rN   Ú	enumerate)rK   r’   rE   s    @€r    rM   z$build_bulk_upsert.<locals>.<genexpr>Ÿ   sH   ùè ø€ ò ð ð 	Ø
�)‰)ô 
ä"+¨GÓ"4ô
ó 
ñ	
ð
 *õ	*ñùs   „48c           
   3   ó<   •K  — | ]  }d |› d‰› d|› d|› d �	–— Œ y­w)rJ   z" = z."z" + EXCLUDED."Nr   )rK   rL   Úquoted_tables     €r    rM   z$build_bulk_upsert.<locals>.<genexpr>¨   s4   øè ø€ ò "àð ˆFˆ8�4˜�~ R¨ x¨~¸f¸XÀQÔGñ"ùs   ƒz1, "request_id" = COALESCE(EXCLUDED."request_id", z."request_id")rR   zINSERT INTO z (z, "updated_at")
VALUES z
ON CONFLICT (z) DO UPDATE SET
  z-,
  "updated_at" = (NOW() AT TIME ZONE 'UTC')c              3   óL   •K  — | ]  \  }}t        ‰||«      D ]  }|–— Œ Œ y ­wra   )r†   )rK   rx   r^   rP   r]   s       €r    rM   z$build_bulk_upsert.<locals>.<genexpr>º   s.   øè ø€ ÒlÑ 0  [Ä{ÐSXÐZ]Ð_jÓGkÒl¸e”eÐl�eÑlùs   ƒ!$)r‰   r   rN   Úrangerp   r<   rB   r   rO   r   r3   re   )r]   rŠ   ÚrowsÚ
incrementsÚrequest_id_updateÚsqlrE   r•   s   `     @@r    Úbuild_bulk_upsertrœ   ˜   s  ú€ ô
 % UÓ+€GØ˜eŸj™j˜\¨Ð+€LØ—)‘)ó ô œs 5›zÓ*ôó €Dð Ÿ	™	ó "à:Ô(Ð:¬>Ñ:ô"ó €Jð ×#Ò#ð <¸L¸>ÈÑXàð ð �|�n B¤w¨wÓ'7Ð&8ð 9Ø�ð Ü ×!7Ñ!7Ð G¼,Ñ GÓHÐIð JØˆLÐ*Ð+ð ,8ð	9ð ð ”Ól°EÔlÓlÐlÐlr   )'r   r„   Úcollections.abcr   r   Údataclassesr   Ú	itertoolsr   Útypesr   Útypingr   r	   ÚDailySpendEntityr   rX   rY   ÚSqlValueÚobjectÚSpendRowr   r,   r   r3   r<   rB   rD   rO   rT   rZ   r\   re   rf   rr   r~   r†   r‰   rœ   )rL   s   0r    ú<module>r¦      sç  ðòó ß -Ý !Ý Ý "ß !àÐLÑMÐ à�‰9�uÑ˜tÑ#€ð �3˜�;Ñ€ñ �$˜dÔ#÷%ð %ó $ð%ñ IYáÐ%=ÐPYÔZÙÐ%=ÐPYÔZÙÐ$DÐWhÔiÙ#Ð)DÐWdÔeÙ Ð&?ÐR\Ô]ÙÐ$;ÈeÐhlÔmñó	IÐ �E˜'Ð"2°OÐ"CÑDÑEó 	ð r€ˆeÓ qð	Ð �%ó 	ð€�ó ñ $4ðØ*:Ö
; ˆ6�8ÑÒ
;ðà4BÖ
C¨&ˆ6Ð%Ñ%Ò
Cðó$€ˆˆg�c˜3�hÑÑ ó ð:�X˜c‘]ð : só :ð/�Fð /˜só /ð@�6ð @˜có @ðD�Vð D ó Dðj˜ð j°hð jÀ5ÈÈcÈÁ?ó jð
�(˜8Ñ$ð ¨ó ðwØðwà˜8Ñ$ðwð ˆ5��s˜C�x‘ (Ð*Ñ+¨SÐ0Ñ1ówð Øðà	ˆs�Cˆx‰ðð ðð ˆ8�Sˆ=Ñó	ð 	˜?ð 	¨u°S¸#°X©ó 	ð"mØð"mà�E˜%  S ™/¨8Ð3Ñ4Ñ5ð"mð ˆ3��h �mÑ$Ð$Ñ%ô"mùòc <ùÚ
Cs   Ã
F
Ã
F
