Skip to content

feat(audience-sdk): SDK-257 E2E robustness follow-up#717

Merged
ImmutableJeffrey merged 1 commit intomainfrom
feat/sdk-257-e2e-robustness
Apr 30, 2026
Merged

feat(audience-sdk): SDK-257 E2E robustness follow-up#717
ImmutableJeffrey merged 1 commit intomainfrom
feat/sdk-257-e2e-robustness

Conversation

@ImmutableJeffrey
Copy link
Copy Markdown
Collaborator

@ImmutableJeffrey ImmutableJeffrey commented Apr 29, 2026

Summary

  • Adds TimerDisposal.DisposeAndWait helper; replaces ad-hoc Timer.Dispose(WaitHandle) + using patterns in Session.Start, Session.DrainHeartbeatTimer, and ImmutableAudience.Shutdown. Leaks the wait handle on timeout to avoid a threadpool crash on the underlying race.
  • Adds publishable-key / BaseUrl mismatch detection at Init time; logs a warning on test-key + production-BaseUrl pairings and vice versa.
  • Adds thread-safety stress tests: sustained multi-threaded Track load, mixed Track / Identify / SetConsent concurrency, main-thread allocation budget check.
  • Adds disk-write-blocked resilience regression tests. An [Ignore]'d Track_DiskWritesBlocked_RetainsEventsInMemory_AndSurfacesOnError documents the deferred EventQueue memory-only fallback follow-up.
  • Adds targeted TimerDisposal unit tests.

Linear: SDK-257

@ImmutableJeffrey ImmutableJeffrey force-pushed the feat/sdk-257-e2e-robustness branch from d3771d7 to c682b6b Compare April 29, 2026 11:53
@ImmutableJeffrey ImmutableJeffrey marked this pull request as ready for review April 29, 2026 23:16
@ImmutableJeffrey ImmutableJeffrey requested review from a team as code owners April 29, 2026 23:16
…DK-257)

Tests:
- ThreadSafetyStressTests: 4 / 16 thread sustained Track load (5s, no exceptions, queue
  count matches fired). 16-thread mixed Track / Identify / SetConsent. 10 000-call
  per-call main-thread allocation budget via GC.GetAllocatedBytesForCurrentThread,
  isolated from drain-thread noise.
- OfflineResilienceTests: Track and Shutdown absorb disk-write IOException without
  throwing. Memory-only fallback (retain events without losing in-flight) captured as
  [Ignore]'d test — EventQueue currently drops on IOException; gap documented for
  follow-up.
- PublishableKeyPrefixTests: Init warns on test-prefix + production BaseUrl (and the
  symmetric pairing). Custom dev/staging URLs not flagged. Track + Flush surfaces
  backend 401 as ValidationRejected via OnError, body propagated through.
- TimerDisposalTests: null, already-disposed, idle, long-running callback (regression
  guard for the SDK fix below).

SDK:
- ImmutableAudience.WarnIfKeyEnvironmentMismatch logs at Init when prefix and BaseUrl
  override contradict. Init proceeds either way.
- New TimerDisposal.DisposeAndWait at three call sites (Session.Start,
  Session.DrainHeartbeatTimer, ImmutableAudience.Shutdown). Replaces a pattern that
  raced its own dispose — WaitOne timeout disposed the handle, then Timer's
  signal-when-done fired SetEvent on the closed SafeWaitHandle and crashed the
  threadpool. Helper leaks the wait handle on timeout; GC reclaims after the signal
  lands.

Test infrastructure:
- TestDefaults shared constants (FlushIntervalSeconds, FlushSize) across the new
  fixtures.

Out of scope:
- Kill-Unity restart automation — needs CLI Unity test harness.
- Network toggle — platform-coupled, requires admin privileges.
- EventQueue memory-only fallback for disk-full — separate ticket.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@ImmutableJeffrey ImmutableJeffrey force-pushed the feat/sdk-257-e2e-robustness branch from c682b6b to 14cda32 Compare April 30, 2026 01:05
@ImmutableJeffrey ImmutableJeffrey merged commit 526b993 into main Apr 30, 2026
28 checks passed
@ImmutableJeffrey ImmutableJeffrey deleted the feat/sdk-257-e2e-robustness branch April 30, 2026 01:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

2 participants