fix: preserve flag evaluations tracked during analytics flush
Flag evaluations recorded while an analytics batch is being submitted can disappear: flush() serializes the counters, submits the request, and then clears the shared dictionary, including evaluations added after serialization.
Protect counter updates and batch detachment with a lock. Reset the pending dictionary and flush timestamp atomically, then serialize and submit the detached batch outside the lock. Evaluations arriving during submission stay available for the next flush, following the existing EventProcessor locking pattern.
A deterministic regression test blocks request submission in one thread while another records both an existing flag and a new flag. It verifies that tracking completes during submission and that both evaluations reach the next batch.
Testing and validation
- Regression on unmodified main: 1 failed, 6 passed.
- Analytics tests after the fix: 7 passed.
- Full suite after initializing test-data submodules: 379 passed.
- Black, isort and git diff whitespace checks pass for the changed files.
This change and its regression test were generated with assistance from OpenAI Codex.
Summary by cubic
Fixes a race condition in the analytics flush that lost flag evaluations recorded while a batch was being submitted. flush() now detaches the pending counters under a lock before serializing and posting, so evaluations arriving during submission stay available for the next flush instead of being cleared with the submitted batch.
- Protects counter updates and batch detachment with a lock, following the existing
EventProcessorlocking pattern. - Adds a deterministic regression test that blocks request submission while recording both an existing and a new flag.