fix(interactions): survive a settlement install failure at boot and stop carrying request headers

This commit is contained in:
mateo-berri 2026-09-19 04:39:51 -07:00
parent 5ad24e5363
commit a2ba6e01d1
4 changed files with 41 additions and 5 deletions

View file

@ -211,7 +211,6 @@ _CARRIED_METADATA_KEYS: Final = frozenset(
"spend_logs_metadata",
"requester_metadata",
"requester_ip_address",
"requester_custom_headers",
"user_agent",
"agent_id",
"session_id",

View file

@ -169,7 +169,13 @@ async def configure_background_interaction_settlement(
async def install_background_interaction_settlement(prisma_client: "PrismaClient") -> None:
await configure_background_interaction_settlement(
table=BackgroundInteractionSettlementRepository(prisma_client).table,
claimed_by=f"{socket.gethostname()}:{os.getpid()}",
)
try:
await configure_background_interaction_settlement(
table=BackgroundInteractionSettlementRepository(prisma_client).table,
claimed_by=f"{socket.gethostname()}:{os.getpid()}",
)
except Exception as e: # noqa: BLE001 # a boot step must survive any DB error; billing then settles in-process as before
verbose_proxy_logger.warning(
"Durable background interaction settlement is off on this replica, so billing settles in-process only: %s",
e,
)

View file

@ -682,6 +682,23 @@ async def test_delete_settles_once_however_many_replicas_try():
assert second_calls == []
def test_create_context_carries_no_request_headers():
logging_obj = _logging_obj(
litellm_params={
"metadata": _create_metadata(
requester_custom_headers={"x-api-key": "sk-customer-secret"},
proxy_server_request={"headers": {"x-api-key": "sk-customer-secret"}},
)
}
)
carried = _create_context(logging_obj, "gemini").metadata
assert carried["user_api_key_team_id"] == "team-1"
assert "requester_custom_headers" not in carried
assert "proxy_server_request" not in carried
@pytest.mark.asyncio
async def test_restart_resumes_only_the_rows_no_replica_claimed():
store = InMemoryBackgroundSettlementStore()

View file

@ -17,6 +17,7 @@ from litellm.interactions.background_cost_polling import (
from litellm.litellm_core_utils.litellm_logging import Logging as LitellmLogging
from litellm.proxy.spend_tracking.background_interaction_settlement import (
configure_background_interaction_settlement,
install_background_interaction_settlement,
PrismaBackgroundSettlementStore,
)
from litellm.types.interactions import InteractionsAPIResponse
@ -233,6 +234,19 @@ async def test_configure_installs_the_store_and_resumes_the_orphaned_rows():
configure_background_settlement_store(previous_store)
class _PrismaClientWithoutSettlementTable:
pass
@pytest.mark.asyncio
async def test_install_keeps_booting_when_the_settlement_table_is_unreachable():
previous_store = bg._STORE.store
await install_background_interaction_settlement(_PrismaClientWithoutSettlementTable())
assert bg._STORE.store is previous_store
@dataclass(frozen=True)
class _JsonLike:
data: object