Skip to content

fix: preserve flag evaluations tracked during analytics flush - #284

Open
pcbeingused333 wants to merge 1 commit into
Flagsmith:mainfrom
pcbeingused333:fix/c3477-analytics-flush
Open

pcbeingused333 wants to merge 1 commit into
Flagsmith:mainfrom
pcbeingused333:fix/c3477-analytics-flush

Conversation

@pcbeingused333

@pcbeingused333 pcbeingused333 commented Nov 15, 2026 •

Copy link
Copy Markdown

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 EventProcessor locking pattern.
  • Adds a deterministic regression test that blocks request submission while recording both an existing and a new flag.

Written for commit b438740. Summary will update on new commits.

View guided diff

@pcbeingused333
pcbeingused333 requested a review from a team as a code owner November 15, 2026 19:21
@pcbeingused333
pcbeingused333 requested review from emyller and removed request for a team November 15, 2026 19:21
@coderabbitai

coderabbitai Bot commented Nov 15, 2026 •

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

AnalyticsProcessor now locks updates to buffered analytics data. flush captures and clears the pending batch before posting it, and updates the flush timestamp during that operation. track_feature checks the timer while holding the lock and calls flush after releasing it. A concurrent test blocks a POST and verifies that evaluations recorded during the submission remain available for a later flush.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: Minimal · up to b4387

This change keeps flag evaluations recorded during an analytics submission from being lost. No merge-blocking risk was found, and a regression test covers the behavior.

- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 9e00888a-3ad3-439c-9840-bb231f17424e
Commits

Reviewing files that changed from the base of the PR and between b480743 and b438740.

Files selected for processing: 2

  • flagsmith/analytics.py
  • tests/test_analytics.py

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="flagsmith/analytics.py">

<violation number="1" location="flagsmith/analytics.py:70">
P2: A synchronous `session.post` failure now drops this detached batch because the counters are cleared before submission. Re-queue `analytics_data` under `_lock` when submission raises, then propagate the exception.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

Comment thread flagsmith/analytics.py
if not self.analytics_data:
return
analytics_data = self.analytics_data
self.analytics_data = {}

@cubic-dev-ai cubic-dev-ai Bot Nov 15, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: A synchronous session.post failure now drops this detached batch because the counters are cleared before submission. Re-queue analytics_data under _lock when submission raises, then propagate the exception.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At flagsmith/analytics.py, line 70:

<comment>A synchronous `session.post` failure now drops this detached batch because the counters are cleared before submission. Re-queue `analytics_data` under `_lock` when submission raises, then propagate the exception.</comment>

<file context>
@@ -56,30 +56,39 @@ def __init__(
+            if not self.analytics_data:
+                return
+            analytics_data = self.analytics_data
+            self.analytics_data = {}
+            self._last_flushed = datetime.now()
+
</file context>
Fix with cubic

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