Skip to content

fix(bookstack-analytics): fix concurrent-write race condition and show unique users#104

Merged
amrit110 merged 2 commits into
mainfrom
fix/bookstack-analytics-race-condition-unique-users
Jun 17, 2026
Merged

fix(bookstack-analytics): fix concurrent-write race condition and show unique users#104
amrit110 merged 2 commits into
mainfrom
fix/bookstack-analytics-race-condition-unique-users

Conversation

@amrit110

Copy link
Copy Markdown
Member

Summary

  • Race condition fix: The GCS activity log used a raw read-modify-write pattern with no locking — two simultaneous queries from different users could overwrite each other's entry. Fixed with a compare-and-swap loop using GCS object generation preconditions (if_generation_match). On an HTTP 412 conflict, the logger reloads the latest log and retries up to 5 times.
  • Unique Users metric: Replaced the "Unique Sessions" dashboard card (which was nearly equal to total queries since every page load creates a new session ID) with a "Unique Users" metric computed from distinct user_email values. Currently shows 5 unique users vs the misleading 25 sessions.

Root cause investigation

Confirmed via gsutil cat on the live GCS bucket: the raw data IS stored correctly (different users asking the same question produce separate entries with distinct session_id, user_email, and timestamp). The issues were:

  1. Concurrent writes could silently drop entries (race condition in activity_logger.py)
  2. The dashboard's "Unique Sessions" metric was misleading — it counted UUID session IDs (one per page load), not distinct users

Changes

File Change
src/aieng_bot/bookstack/activity_logger.py CAS retry loop, _load_activity_log returns (data, generation), _save_activity_log takes if_generation_match
tests/bookstack/test_activity_logger.py Updated tests + 3 new tests for CAS retry, exhaustion, and PreconditionFailed re-raise
bookstack_agent/ui/lib/bookstack-types.ts Add unique_users: number to BookstackMetrics
bookstack_agent/ui/lib/bookstack-data-fetcher.ts Compute unique_users from distinct non-null user_email values
bookstack_agent/ui/app/analytics/components/query-metrics.tsx Replace "Unique Sessions" card with "Unique Users"

Test plan

  • All 250 existing tests pass (uv run pytest)
  • 3 new tests: CAS conflict retry, retry exhaustion, PreconditionFailed re-raise
  • TypeScript type-checks clean (tsc --noEmit)
  • Linting clean (ruff check)

amrit110 and others added 2 commits June 16, 2026 19:22
…w unique users

Replace the unsafe read-modify-write on the GCS activity log with a
compare-and-swap loop using GCS object generation preconditions
(if_generation_match). On an HTTP 412 conflict the logger reloads the
latest log and retries up to 5 times, so simultaneous queries from
different users no longer silently overwrite each other.

Replace the misleading "Unique Sessions" dashboard metric (which was
essentially equal to total queries since every page load creates a new
session) with "Unique Users" computed from distinct user_email values.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@amrit110 amrit110 merged commit b96a5ae into main Jun 17, 2026
9 checks passed
@amrit110 amrit110 deleted the fix/bookstack-analytics-race-condition-unique-users branch June 17, 2026 02:02
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