litellm/tests/test_litellm/proxy/db
ryan-crabbe-berri be71a8fdbf
fix(alerting): dedupe scheduled Slack spend reports across pods (#36489)
* fix(alerting): dedupe scheduled Slack spend reports across pods

Every pod ran its own weekly/monthly spend report jobs, prometheus
fallback stats cron, and daily report loop, so deployments with
multiple replicas or uvicorn workers received one copy per pod.

Gate each scheduled send behind the shared PodLockManager redis lock.
The lock is never released: its TTL (the full reporting window for the
weekly interval job, whose per-pod anchors drift by boot time and
jitter) doubles as a sent-this-window marker. acquire_lock returning
None (no redis wired) proceeds, preserving single-pod behavior.

Also generalize the pod lock could-not-acquire log line, which claimed
to be about spend tracking for every consumer.

Fixes #14809

* fix(alerting): harden spend report locks after adversarial review

Weekly lock TTL gets an hour haircut: with ttl equal to the interval,
the winner re-fires just before its own key expires, reacquires without
a TTL refresh, and the key then lapses in time for a trailing pod to
re-send. Job/lock ids move to litellm/constants.py per convention, and
spend_report_frequency now rejects non-positive day counts, which
previously coerced to an every-second schedule and would now compute a
negative lock TTL that silently never sends.

Adds the missing test coverage the review flagged: startup_event's
pod_lock_manager wiring (identity-asserted), the prometheus closure's
positive path, and the ungated immediate prometheus send pinned to
exactly one await.

* test(alerting): consolidate spend_report_frequency validator coverage

Drops a duplicate non-positive-days test and parametrizes the survivor
over the suffix half of the validator too

* fix(alerting): route the startup prometheus fallback send through the pod lock

Greptile caught that the boot-time send still ran once per pod when
PROMETHEUS_URL is set, the same duplication class this PR removes

* fix(alerting): make report lock acquisition non-reentrant

Greptile caught that a pod booting within an hour of the fallback stats
cron sent twice: the startup send takes the lock, then the cron fire
hits acquire_lock's reacquire branch, which returns True for the
holder. Window-marker gates now pass allow_reentrant=False so a live
lock blocks everyone including its holder; leader-election consumers
keep the reentrant default

* test(proxy): give spec'd ProxyLogging mocks a db_spend_update_writer

_initialize_slack_alerting_jobs now reads it for the pod lock manager,
and spec=ProxyLogging blocks instance-only attributes
2026-08-11 12:41:11 -07:00
..
db_transaction_queue fix(alerting): dedupe scheduled Slack spend reports across pods (#36489) 2026-08-11 12:41:11 -07:00
mcp_server build(VLLM-Passthrough-with-loadbalancing-support-(enables-using-model-list-for-VLLM-/classify-endpoint)): Closes #11205 2025-05-31 09:00:04 -07:00
conftest.py fix(tests): stop DATABASE_URL env pollution from read-replica tests breaking DB e2e tests (#32653) 2026-07-09 14:37:49 -07:00
test_autorouter_session_rollup.py feat(auto-router): track turns per complexity tier (LIT-5302) (#36209) 2026-08-07 17:03:34 -07:00
test_check_migration.py build: migrate packaging, CI, and Docker from Poetry to uv (#25007) 2026-04-09 11:46:23 -07:00
test_create_views.py [Fix] should_create_missing_views returns False for reltuples=0 (falsy zero bug) 2026-04-18 11:00:09 -07:00
test_daily_spend_bulk_upsert.py perf(spend): write each daily spend batch in one upsert statement (#36448) 2026-08-10 17:06:00 -07:00
test_db_spend_update_writer.py fix(proxy): add config_updated_at audit timestamp for virtual keys (#36488) 2026-08-11 11:02:57 -07:00
test_db_url_settings.py fix(tests): stop DATABASE_URL env pollution from read-replica tests breaking DB e2e tests (#32653) 2026-07-09 14:37:49 -07:00
test_exception_handler.py fix(proxy): only treat a recoverable database outage as grounds to serve without one (#35864) 2026-08-05 14:15:13 -07:00
test_exception_handler_reconnect_retry.py fix(proxy): preserve original transport error if reconnect itself raises 2026-04-28 23:55:46 -07:00
test_gateway_request_tracking.py feat(sgr): make the gateway middleware the source of truth for successful requests (#35717) 2026-08-05 12:40:47 -07:00
test_prisma_client.py feat(db): opt-in REPLICA IDENTITY FULL after prisma migrations (#35267) 2026-07-30 15:45:40 -07:00
test_prisma_planned_engine_restart.py fix(proxy): stop alerting on health probes that lose the planned engine-restart race (#36141) 2026-08-07 09:57:30 -07:00
test_prisma_self_heal.py fix(proxy): only treat a recoverable database outage as grounds to serve without one (#35864) 2026-08-05 14:15:13 -07:00
test_query_engine_reaper.py fix(proxy_cli): reap orphaned prisma query-engine processes when a worker dies (#33424) 2026-07-16 13:16:41 -07:00
test_rds_iam_token_expiry.py fix(tests): stop DATABASE_URL env pollution from read-replica tests breaking DB e2e tests (#32653) 2026-07-09 14:37:49 -07:00
test_replica_identity.py feat(db): opt-in REPLICA IDENTITY FULL after prisma migrations (#35267) 2026-07-30 15:45:40 -07:00
test_routing_prisma_wrapper.py fix(tests): stop DATABASE_URL env pollution from read-replica tests breaking DB e2e tests (#32653) 2026-07-09 14:37:49 -07:00
test_spend_log_batching.py fix(spend): bound each spend-log write statement by payload bytes (#34956) 2026-08-01 13:53:36 -07:00
test_spend_log_tool_index.py fix(proxy): close the adversarial-review findings on the tool spend rollup 2026-07-26 01:55:47 -07:00
test_tool_registry_writer.py fix(proxy): self-heal startup/reload prisma reads on engine disconnect (#28803) 2026-06-10 20:16:58 +02:00