Skip to content

fix(session-ingest): add retry with backoff to session-ingest-client calls#1385

Open
jeanduplessis wants to merge 3 commits intomainfrom
session-ingest-hardening
Open

fix(session-ingest): add retry with backoff to session-ingest-client calls#1385
jeanduplessis wants to merge 3 commits intomainfrom
session-ingest-hardening

Conversation

@jeanduplessis
Copy link
Contributor

Summary

  • Replace direct fetch() calls in session-ingest-client.ts with fetchWithBackoff() (10s budget) for the export, share, and delete endpoints, so transient failures from the session-ingest worker are retried automatically instead of immediately surfacing errors to users.
  • Consolidate the duplicated share-endpoint logic in cli-sessions-v2-router.ts — the inline fetch + response parsing is replaced with a call to the shared shareSessionIngest helper, removing ~25 lines of redundant code and the now-unused SESSION_INGEST_WORKER_URL / generateInternalServiceToken imports.
  • Drain response bodies on retried responses in fetchWithBackoff.ts (response.body?.cancel()) to prevent socket/buffer leaks.

Verification

  • pnpm typecheck — passed
  • pnpm test src/lib/session-ingest-client.test.ts — 25/25 tests passed (including 2 new retry integration tests)
  • pnpm exec oxlint — 0 errors
  • pnpm exec oxfmt --list-different . — no unformatted files
  • Pre-push hook (format + lint + typecheck) — passed

Visual Changes

N/A

Reviewer Notes

  • The retry integration tests use jest.requireActual to swap the mock fetchWithBackoff for the real implementation within a single describe block, while all other tests continue to use the passthrough mock. The "retries exhausted" test has a 15s timeout since it waits for the real 10s backoff budget to expire.
  • fetchWithBackoff already retries on 5xx by default, so no custom retryResponse option is needed.
  • The response.body?.cancel() drain is fire-and-forget with a swallowed error — the body may already be consumed or absent in some environments.

…calls

Replace direct fetch() calls in session-ingest-client with fetchWithBackoff()
to handle transient failures from the session ingest worker. Consolidate
the duplicated share endpoint logic in cli-sessions-v2-router to use the
shared shareSessionIngest helper. Drain response bodies on retry to prevent
socket/buffer leaks.
@kilo-code-bot
Copy link
Contributor

kilo-code-bot bot commented Mar 23, 2026

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

No new issues on current PR diff lines.

Other Observations (not in diff)

Issues found in merged changes outside the current PR diff that cannot receive inline comments:

File Line Issue
packages/db/src/migrations/0057_backfill_billing_misclassified.sql 23 Marks every v2 failed session.error review as billing, but session.error is also used for generic session failures (src/lib/cloud-agent-next/processor/event-processor.ts:375), so this backfill can misclassify historical non-billing reviews.

Fix these issues in Kilo Cloud

Files Reviewed (71 files)
  • .env.test
  • .specs/kiloclaw-billing.md
  • AGENTS.md
  • cloud-agent-next/wrapper/src/connection.ts
  • cloudflare-gastown/src/dos/Town.do.ts
  • cloudflare-gastown/src/dos/town/agents.ts
  • cloudflare-gastown/src/dos/town/reconciler.ts
  • cloudflare-gastown/src/dos/town/review-queue.ts
  • cloudflare-gastown/src/dos/town/scheduling.ts
  • cloudflare-gastown/test/integration/reconciler.test.ts
  • kiloclaw/controller/src/bootstrap.test.ts
  • kiloclaw/controller/src/bootstrap.ts
  • kiloclaw/controller/src/config-writer.test.ts
  • kiloclaw/controller/src/config-writer.ts
  • kiloclaw/packages/secret-catalog/src/__tests__/catalog.test.ts
  • kiloclaw/packages/secret-catalog/src/catalog.ts
  • kiloclaw/packages/secret-catalog/src/index.ts
  • kiloclaw/packages/secret-catalog/src/types.ts
  • kiloclaw/src/durable-objects/kiloclaw-instance.test.ts
  • kiloclaw/src/durable-objects/kiloclaw-instance/index.ts
  • kiloclaw/src/routes/kiloclaw.test.ts
  • kiloclaw/src/utils/analytics.ts
  • packages/db/src/migrations/0057_backfill_billing_misclassified.sql
  • packages/db/src/migrations/meta/0057_snapshot.json
  • packages/db/src/migrations/meta/_journal.json
  • packages/db/src/schema-types.ts
  • packages/worker-utils/src/cloud-agent-next-client.ts
  • plans/kiloclaw-billing-promo-codes.md
  • src/app/(app)/claw/components/ChangelogCard.tsx
  • src/app/(app)/claw/components/ChangelogTab.tsx
  • src/app/(app)/claw/components/CreateInstanceCard.tsx
  • src/app/(app)/claw/components/CreditsNudge.actions.ts
  • src/app/(app)/claw/components/CreditsNudge.tsx
  • src/app/(app)/claw/components/SettingsTab.tsx
  • src/app/(app)/claw/components/billing/SubscriptionCard.tsx
  • src/app/(app)/claw/components/changelog-data.ts
  • src/app/(app)/claw/components/secret-ui-adapter.ts
  • src/app/admin/components/KiloclawInstances/KiloclawInstancesPage.tsx
  • src/app/admin/components/UserAdmin/UserAdminKiloClaw.tsx
  • src/app/api/internal/code-review-status/[reviewId]/route.test.ts
  • src/app/api/internal/code-review-status/[reviewId]/route.ts
  • src/app/api/openrouter/[...path]/route.ts
  • src/app/payments/topup/route.ts
  • src/lib/config.server.ts
  • src/lib/fetchWithBackoff.ts
  • src/lib/forbidden-free-models.ts
  • src/lib/integrations/platforms/github/adapter.ts
  • src/lib/integrations/platforms/gitlab/adapter.ts
  • src/lib/kilo-auto-model.ts
  • src/lib/kiloclaw/billing-lifecycle-cron.ts
  • src/lib/kiloclaw/stripe-handlers.ts
  • src/lib/kiloclaw/stripe-price-ids.server.ts
  • src/lib/llm-proxy-helpers.ts
  • src/lib/models.ts
  • src/lib/processUsage.messages.ts
  • src/lib/providers/gigapotato.ts
  • src/lib/providers/index.ts
  • src/lib/providers/model-settings.ts
  • src/lib/providers/vercel/index.ts
  • src/lib/rewriteModelResponse.ts
  • src/lib/session-ingest-client.test.ts
  • src/lib/session-ingest-client.ts
  • src/lib/stripe.ts
  • src/routers/admin-kiloclaw-instances-router.ts
  • src/routers/admin-kiloclaw-user-router.test.ts
  • src/routers/admin-router.ts
  • src/routers/cli-sessions-v2-router.test.ts
  • src/routers/cli-sessions-v2-router.ts
  • src/routers/kilo-pass-router.ts
  • src/routers/kiloclaw-billing-router.test.ts
  • src/routers/kiloclaw-router.ts

Reviewed by gpt-5.4-20260305 · 635,991 tokens

… of global.fetch

The shareForWebhookTrigger endpoint now delegates to the shared
shareSessionIngest client. The router test was mocking global.fetch
directly, which broke because fetchWithBackoff retries transient 500s
and the mockResolvedValueOnce only covered the first attempt.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant