litellm/tests/unit/proxy/db
joshua-berri a12a6cd154
feat(accounting)!: make the SpendLogs ledger the default accounting path (#49872)
* fix(accounting): keep one undecodable delivery from blocking the ledger

A request whose metadata carried a 401-digit tokens_saved stored that number in
its delivery payload. The query engine could not decode it when the worker
claimed the batch, so every later delivery on the proxy stayed pending

The worker now claims the payload as text and decodes each row in Python. A row
that still cannot be decoded is parked alone while the rest of the batch
applies. The payload builder also clamps integers to the JSON-safe range, so
caller-supplied counts can no longer reach the engine at that size

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(accounting): take spend locks in one order so the ledger cannot deadlock

A ledger delivery updates many spend tables in one transaction, so it can
deadlock with any writer that locks the same rows in another order. It took the
team advisory lock after the user and team rows, while team roster writers take
it first

The delivery now takes every team advisory lock before any row, then writes
tables in one canonical order with ids sorted. It also runs under the rollup
lock_timeout, applies 500 deliveries per batch by default, and spreads retries
with jitter

The writers that could still collide with it now follow the same order. The
budget reset cascade, model allowlist rename, global spend reset, bulk user
update, org delete and the delete-by-list paths lock their rows in key order
first, and access group endpoints update teams and keys in one sorted pass

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(accounting): prove a ledger delivery waits instead of deadlocking

Real Postgres tests hold the first lock of a team roster change, an access group
update and a budget reset cascade, start a delivery, and let the other writer
finish. The delivery must wait and then charge once. Before the lock order fix
each case ends in a Postgres deadlock

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(accounting)!: make the SpendLogs ledger the default accounting path

use_spend_logs_ledger now defaults to true, so every request is charged through
LiteLLM_SpendLogDelivery. Setting it to false rolls back to the in-memory and
Redis spend queues, which stay in place. Tests that cover those legacy writers
pin the setting off, and the rest check the queued charge the ledger stores

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(proxy): let the mocked client open a transaction for key and team deletes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(proxy): take team locks first when a model rename rewrites allowlists

A rename locked team rows before user rows while a roster change holds the team
advisory lock and a user row, so the two could deadlock. The rename now takes the
advisory lock for every team that lists the model, sorted, before any row lock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(accounting): drain a backlog in one worker run, one batch per transaction

One run applied a single fresh batch, so at 500 per batch charges fell behind any
load above that rate. The worker now keeps claiming fresh batches while they come
back full, for up to five seconds, and each batch still commits on its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(accounting): queue only the charge when a request's spend log is suppressed

With logging off for a request, the ledger still queued the full row, so a failed
flush or a shutdown could leave its prompt and response in Redis. The queue now
holds only the fields the charge needs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* style(proxy): format the rename team listing query

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(accounting): remove expired delivery receipts as fast as the worker applies them

The worker now applies several batches per run but still removed one cleanup batch
of applied receipts, so the table could outgrow its retention window. Cleanup now
repeats while each pass removes a full batch, for up to five seconds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(proxy): retry a model rename when a team starts listing the model mid-lock

The team advisory locks come from a snapshot, so a team that gained the old name
before its row lock was locked without its advisory lock. That attempt now commits
without writing and the next one locks the fresh set of teams.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Joshua Valluru <326636767+joshua-berri@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 09:14:10 -08:00
..
db_transaction_queue fix(proxy): treat Postgres restart and shutdown errors as DB unavailable, not poison spend-log rows (#50132) 2026-11-04 17:39:30 -08:00
mcp_server refactor(mcp): drop the experimental label from the MCP server and client paths (#48513) 2026-10-27 17:47:50 +00:00
__init__.py ci: move tests/proxy_unit_tests to tests/unit/proxy and run the proxy-db shards from litellm-tests (#42903) 2026-09-24 22:59:11 +00:00
conftest.py test(proxy): move proxy_server, _experimental and db tests into tests/unit/proxy (#44012) 2026-10-01 18:14:24 +00:00
fake_prisma_engine.py fix(proxy): cancel the Admin UI's raw spend-log reads in Postgres after 30s (#49965) 2026-11-03 16:07:00 -08:00
test_autorouter_session_rollup.py test: migrate tests/proxy_behavior into integration and unit tiers (#45939) 2026-10-11 08:28:42 -07:00
test_budget_window_spend_writer.py feat(accounting): add opt-in SpendLogs ledger (#49856) 2026-11-04 17:49:15 -08:00
test_check_migration.py feat(proxy)!: add suppress_startup_output to turn off startup prints (#47708) 2026-10-29 03:47:04 -07:00
test_create_views.py test(proxy): move proxy_server, _experimental and db tests into tests/unit/proxy (#44012) 2026-10-01 18:14:24 +00:00
test_daily_spend_bulk_upsert.py fix(proxy): bound daily spend rollup row-lock waits with lock_timeout and requeue 55P03 (#44450) 2026-10-06 17:38:55 -05:00
test_db_lookup_gate.py test: make three flaky unit tests deterministic (#50114) 2026-11-04 14:38:44 -08:00
test_db_span.py fix(otel): name postgres service spans by operation and table (#44240) 2026-10-03 09:20:28 -07:00
test_db_spend_update_writer.py feat(accounting)!: make the SpendLogs ledger the default accounting path (#49872) 2026-11-05 09:14:10 -08:00
test_db_url_settings.py fix(proxy): sign RDS IAM tokens for the database's own region (#44782) 2026-10-09 15:41:07 -07:00
test_exception_handler.py fix(proxy): treat Postgres restart and shutdown errors as DB unavailable, not poison spend-log rows (#50132) 2026-11-04 17:39:30 -08:00
test_exception_handler_reconnect_retry.py test(proxy): move proxy_server, _experimental and db tests into tests/unit/proxy (#44012) 2026-10-01 18:14:24 +00:00
test_gateway_request_tracking.py feat(proxy): track failed requests by HTTP status and caller (#45244) 2026-10-09 14:27:56 -07:00
test_health_check_latest.py fix(proxy): show the newest health check per model group on the model hub (#47552) 2026-10-20 16:42:53 -07:00
test_log_db_metrics.py fix(proxy): keep the database error when the log_db_metrics failure hook raises (#44383) 2026-10-03 16:38:15 +00:00
test_log_db_metrics_service_spans.py test: replace 61 live logging and otel tests with offline unit and integration coverage (#45362) 2026-10-08 15:55:57 -07:00
test_master_key_migration.py fix(security): remove the publicly known master key from the repo (#44718) 2026-10-06 10:55:24 -07:00
test_model_access_group_spend.py refactor(router): move router callers onto the entry points and invert the proxy imports (#48847) 2026-10-29 17:26:33 +00:00
test_model_insights_tasks.py test(proxy): move proxy_server, _experimental and db tests into tests/unit/proxy (#44012) 2026-10-01 18:14:24 +00:00
test_model_usage_rollup.py fix(responses): bill a background response once, on the first read or poll that sees it finished (#45703) 2026-10-15 11:00:14 -07:00
test_object_permission_repository.py refactor(types): replace Any with proven types in 137 files (#44478) 2026-10-05 11:01:45 -07:00
test_pgbouncer.py test(unit): keep unix socket paths in unit tests under the macOS AF_UNIX limit (#45040) 2026-10-28 20:23:22 -07:00
test_prisma_client.py feat(proxy): replace the pre-migration row check with a rolled-back dry run of the pending migrations (#48961) 2026-10-29 09:39:26 -07:00
test_prisma_planned_engine_restart.py test(proxy): move proxy_server, _experimental and db tests into tests/unit/proxy (#44012) 2026-10-01 18:14:24 +00:00
test_prisma_query_span.py fix(proxy): cancel the Admin UI's raw spend-log reads in Postgres after 30s (#49965) 2026-11-03 16:07:00 -08:00
test_prisma_self_heal.py test(proxy): move proxy_server, _experimental and db tests into tests/unit/proxy (#44012) 2026-10-01 18:14:24 +00:00
test_proxy_worker_heartbeat.py fix(otel): name postgres service spans by operation and table (#44240) 2026-10-03 09:20:28 -07:00
test_query_engine_reaper.py test(proxy): move proxy_server, _experimental and db tests into tests/unit/proxy (#44012) 2026-10-01 18:14:24 +00:00
test_rds_iam_token_expiry.py test(proxy): move proxy_server, _experimental and db tests into tests/unit/proxy (#44012) 2026-10-01 18:14:24 +00:00
test_replica_identity.py test: migrate proxy security, schema migration and MCP legacy tests (#45937) 2026-10-11 16:17:24 -07:00
test_request_error_tracking.py feat(proxy): track failed requests by HTTP status and caller (#45244) 2026-10-09 14:27:56 -07:00
test_routing_prisma_wrapper.py refactor(proxy): give database shutdown one lifespan owner (#48506) 2026-10-30 22:57:53 +00:00
test_shadow_eval_funnel.py fix(otel): name postgres service spans by operation and table (#44240) 2026-10-03 09:20:28 -07:00
test_spend_counter_reseed.py test(proxy): move proxy_server, _experimental and db tests into tests/unit/proxy (#44012) 2026-10-01 18:14:24 +00:00
test_spend_log_batching.py test(proxy): move proxy_server, _experimental and db tests into tests/unit/proxy (#44012) 2026-10-01 18:14:24 +00:00
test_spend_log_tool_index.py fix(responses): log and bill every round of non-stream MCP auto-execute (#43667) 2026-10-16 17:37:33 +00:00
test_token_auth.py fix(proxy): sign RDS IAM tokens for the database's own region (#44782) 2026-10-09 15:41:07 -07:00
test_tool_registry_writer.py fix(proxy): treat Postgres restart and shutdown errors as DB unavailable, not poison spend-log rows (#50132) 2026-11-04 17:39:30 -08:00
test_tool_table_bulk_upsert.py fix(proxy): buffer tool discoveries in Redis and write LiteLLM_ToolTable in one statement per drain, on its own lock (#48089) 2026-10-24 12:34:13 -07:00
test_update_daily_tag_spend.py refactor(proxy): expose public names for private proxy helpers (#45170) 2026-10-07 18:59:27 -07:00