Skip to content

fix: drop oversize AI events locally on the immediate path and align retry defaults - #286

Open
eli-r-ph wants to merge 2 commits into
v1from
v1-immediate-ai-size-and-retries
Open

eli-r-ph wants to merge 2 commits into
v1from
v1-immediate-ai-size-and-retries

Conversation

@eli-r-ph

Copy link
Copy Markdown
Contributor

💡 Motivation and Context

Two v1 behavior fixes so the Rust SDK matches the other server SDKs.

The immediate AI variants now apply the 8 MiB per-event limit locally. The background AI lane already drops an event whose serialized properties exceed AI_MAX_EVENT_BYTES (strictly greater). capture_ai_immediate and capture_ai_batch_immediate sent such an event and relied on the backend to refuse it. Now prepare_immediate measures each event against a per-lane max_event_bytes. An event over the limit is not sent. It gets a local EventResult { result: Drop, details: "ai_event_too_big" }, which counts in submitted() and not_persisted() exactly like the backend's verdict would. If every event in a call is over the limit, no request is made. The analytics lane has no ceiling and its behavior is unchanged.

Retry defaults.

  • max_capture_attempts now defaults to 4 (was 3).
  • retry_initial_backoff_ms now defaults to 100 (was 200).
  • Remote /flags retries no longer read the capture retry options. They use a fixed backoff of 300 ms, doubling up to 30 s, which matches posthog-python and posthog-go. feature_flags_request_max_retries still controls how many /flags retries happen.
  • The exponential math is shared by one helper, exponential_backoff.

The migration guide's Retry section and a capture-retry-defaults changeset describe the new defaults. The guide and changeset text for the AI immediate drop lives in #280, which already rewrites those sentences. I pushed a follow-up commit there so the two PRs agree.

💚 How did you test it?

New and changed tests:

  • prepare_immediate_drops_events_over_the_lane_ceiling_locally covers an event exactly at the ceiling (sent), one byte over (local drop), and every event over the ceiling (no request). It runs on both lanes.
  • capture_ai_batch_immediate_drops_an_oversize_event_locally replaces the old "server returns too-big verdict" test, async and blocking. The mock only answers a request that carries the normal event and not the oversize one. The test asserts submitted() == 2, not_persisted() == 1, the local ai_event_too_big drop, and the normal event's Ok.
  • feature_flags_backoff_doubles_from_300ms_up_to_30s covers the /flags schedule and its cap.
  • The two existing /flags decision tests now assert the exact 300 ms wait while the capture backoff options are set to 1/5 ms, which proves /flags ignores them.
  • backoff_exponential_growth_with_default_options now uses the builder defaults, so it pins 4 attempts and 100/200/400 ms.

Mutation checks. Each mutant fails at least one test, and each was reverted afterwards:

  • AI lane max_event_bytes set to None: the async and the blocking integration tests fail.
  • > changed to >=: the unit test fails.
  • Defaults reverted to 3 attempts or to 200 ms: the default-options test fails.
  • /flags pointed back at the capture backoff: both /flags decision tests fail.

Ran locally and passing:

  • cargo fmt -- --check
  • cargo clippy -- -D warnings
  • cargo test --workspace
  • cargo test --no-default-features
  • cargo test --no-default-features --features error-tracking
  • both test_tls_no_provider variants
  • cargo test --features e2e-test,tls --no-default-features
  • scripts/check-public-api.sh (no public API change)
  • cargo package --locked

Trial merges into #279, #280 (including its new commit) and #285 are all clean. The combined #285 + #280 + this branch passes clippy and cargo test --workspace.

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed.
  • No breaking change or entry added to the changelog.

If releasing new changes

  • Ran sampo add to generate a changeset file

🤖 Agent context

Written with Claude Opus 5.5 in Cursor, directed and reviewed by @eli-r-ph.

capture_ai_immediate and capture_ai_batch_immediate now apply the 8 MiB per-event limit before sending, like the background AI lane. An event over the limit is not sent and gets a local drop verdict with the detail ai_event_too_big in the returned CaptureSummary.
… its own backoff

max_capture_attempts now defaults to 4 and retry_initial_backoff_ms to 100. Remote /flags retries use a fixed backoff of 300 ms, doubling up to 30 s, instead of the capture retry options.
@eli-r-ph eli-r-ph self-assigned this Oct 10, 2026
@eli-r-ph
eli-r-ph marked this pull request as ready for review October 10, 2026 21:51
@eli-r-ph
eli-r-ph requested a review from a team as a code owner October 10, 2026 21:51

This branch has not been deployed

No deployments
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