fix(proxy): do not retry ambiguous spend writer POSTs

This commit is contained in:
Charan Rathore 2026-09-28 10:51:12 +05:30
parent 5480ddf3d7
commit 023d82f23f
2 changed files with 26 additions and 0 deletions

View file

@ -7282,6 +7282,7 @@ class ProxyUpdateSpend:
start_time: Final = time.time()
try:
for i in range(n_retry_times + 1):
external_post_attempted = False
try:
base_url = os.getenv("SPEND_LOGS_URL", None)
if len(logs_to_process) > 0 and base_url is not None and db_writer_client is not None:
@ -7294,6 +7295,7 @@ class ProxyUpdateSpend:
# No external request has been sent. The batch is safe to replay.
await requeue_spend_logs(prisma_client, proxy_logging_obj, logs_to_process)
raise
external_post_attempted = True
response = await db_writer_client.post(
url=base_url + "spend/update",
data=json_data,
@ -7336,6 +7338,10 @@ class ProxyUpdateSpend:
)
break
except Exception as e:
if external_post_attempted:
# Even a transport error can arrive after the remote writer
# committed. Retrying or requeueing could duplicate spend.
raise
if not _is_transient_spend_log_write_error(e):
if PrismaDBExceptionHandler.is_prisma_error(e):
await requeue_spend_logs(prisma_client, proxy_logging_obj, logs_to_process)

View file

@ -991,3 +991,23 @@ async def test_external_spend_log_post_error_is_not_replayed(
)
writer.post.assert_awaited_once()
assert mock_prisma_client.spend_log_transactions == []
@pytest.mark.asyncio
async def test_external_spend_log_transport_error_is_not_retried_or_requeued(
mock_prisma_client: Any, make_spend_log_row: Any, monkeypatch: pytest.MonkeyPatch
) -> None:
import httpx
monkeypatch.setenv("SPEND_LOGS_URL", "http://writer.invalid")
writer = MagicMock()
writer.post = AsyncMock(side_effect=httpx.ReadError("response lost after send"))
proxy_logging = MagicMock()
proxy_logging.failure_handler = AsyncMock()
with pytest.raises(httpx.ReadError):
await ProxyUpdateSpend.update_spend_logs(
n_retry_times=2, prisma_client=mock_prisma_client, db_writer_client=writer,
proxy_logging_obj=proxy_logging, logs_to_process=[make_spend_log_row(request_id="maybe-committed")],
)
writer.post.assert_awaited_once()
assert mock_prisma_client.spend_log_transactions == []