Skip to content

feat(e2e-cli): add flush-retry loop to simulate real flush policy#1173

Merged
abueide merged 9 commits intotapi/types-and-errorsfrom
tapi/cli-flush-retry-loop
Mar 19, 2026
Merged

feat(e2e-cli): add flush-retry loop to simulate real flush policy#1173
abueide merged 9 commits intotapi/types-and-errorsfrom
tapi/cli-flush-retry-loop

Conversation

@abueide
Copy link
Contributor

@abueide abueide commented Mar 18, 2026

Summary

  • Replaces the single flush() + 500ms wait with a proper flush-retry loop that simulates the flush policy cadence a real app uses
  • The CLI now drives repeated flush cycles via the SDK's built-in TimerFlushPolicy (100ms interval), then polls pendingEvents() until the queue drains or timeout
  • Reports accurate success (false when events remain in queue or were permanently dropped) and sentBatches (derived from delivered event count)
  • Reads drop-count from logger.error() messages emitted by SegmentDestination when events are permanently dropped or retry-limit-exceeded
  • Enables the retry test suite in e2e-config.json

Depends on #1156 (tapi/types-and-errors) for httpConfig on Config.

Context

The SDK uses a deferred retry model: failed events stay in a persistent queue and are retried on the next flush policy trigger (timer every 30s, count threshold at 20). The CLI had no flush policies running — it called flush() once and exited. Events that received retryable errors (5xx, 429) were left in the queue with no retry, causing ~20 retry e2e tests to fail.

What this fixes

  • Retry tests that need basic retry → success pattern (500 → retry → 200)
  • success field reporting (was hardcoded to true)
  • sentBatches tracking (was hardcoded to 0)
  • Error classification (permanent drops on 4xx vs retry on 5xx) via tapi types
  • maxRetries wiring to httpConfig.rateLimitConfig and httpConfig.backoffConfig

Test plan

  • esbuild build succeeds
  • CLI smoke test with empty input returns {"success":true,"sentBatches":0}
  • All 66 existing unit test suites pass (362 tests)
  • Run e2e tests against mock server to verify retry loop behavior

🤖 Generated with Claude Code

@abueide abueide changed the base branch from master to tapi/types-and-errors March 19, 2026 16:34
abueide and others added 9 commits March 19, 2026 11:55
The CLI previously called flush() once and exited, so events that
received retryable errors (5xx, 429) stayed in the queue with no
retry. This implements the retry loop that flush policies drive in a
real app: flush → check pending → wait for backoff → repeat.

- Flush-retry loop respects maxRetries from test config
- Forward-compatible with tapi RetryManager (reads backoff state when
  available, falls back to fixed delay on master)
- Tracks permanently dropped events via logger interception
- Reports success=false when events remain or are dropped
- Computes sentBatches from delivered event count
- Enables retry test suite in e2e-config.json

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of manually calling flush() in a loop and reading private
RetryManager state, let the SDK's built-in flush policies drive
retries. TimerFlushPolicy fires every flushInterval (100ms default
for e2e), and the RetryManager gates actual uploads during backoff.

The CLI just triggers the initial flush, then polls pendingEvents()
until the queue drains or 30s timeout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Pass maxRetries from test config into httpConfig overrides so the SDK
  enforces retry limits during e2e tests
- Set output.error when permanentDropCount > 0 so failure reporting tests
  get a truthy error field
- Add BROWSER_BATCHING=true to e2e-config.json to skip tests that assume
  ephemeral per-request batching (RN uses persistent queue re-chunking)
- Add jsx: react to tsconfig.json for .tsx transitive imports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract buildConfig, dispatchEvent, waitForQueueDrain, and
interceptDropCount from main(). Drop redundant per-event validation
warnings and error handling. 367 -> 256 lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Return boolean from waitForQueueDrain to indicate drain vs timeout
- Add JSDoc for interceptDropCount noting coupling to SegmentDestination log format
- Add console.warn in dispatchEvent when events are skipped for missing fields
- Add comment on sentBatches approximation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace fragile log-interception pattern in e2e-cli with a proper
counter on SegmentDestination. The CLI now calls client.droppedEvents()
instead of monkey-patching logger.error and regex-matching drop messages.

- Add droppedEventCount property to SegmentDestination
- Add droppedEvents() accessor on SegmentClient (mirrors pendingEvents)
- Remove interceptDropCount helper from e2e-cli

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@abueide abueide force-pushed the tapi/types-and-errors branch from ff837e7 to a3ac0e5 Compare March 19, 2026 16:57
@abueide abueide force-pushed the tapi/cli-flush-retry-loop branch from 623ad53 to ec82caa Compare March 19, 2026 16:57
@abueide abueide merged commit ec82caa into tapi/types-and-errors Mar 19, 2026
4 checks passed
@abueide abueide deleted the tapi/cli-flush-retry-loop branch March 19, 2026 17:33
@abueide abueide restored the tapi/cli-flush-retry-loop branch March 19, 2026 17:58
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