Skip to content

fix: drain pre-init buffer after modules subscribe; preserve setter ordering#701

Closed
mahmoud-elmorabea wants to merge 2 commits into
pre-init-event-bufferfrom
address-pr-700-feedback
Closed

fix: drain pre-init buffer after modules subscribe; preserve setter ordering#701
mahmoud-elmorabea wants to merge 2 commits into
pre-init-event-bufferfrom
address-pr-700-feedback

Conversation

@mahmoud-elmorabea

Copy link
Copy Markdown
Contributor

Summary

Addresses both P2 review comments on #700.

  • Deferred drain (P2 ci: setup automated deployment #2) — A new CustomerIO.finishInitialization() publishes the initial UserChangedEvent and drains the pre-init buffer after every module has run its initialize(). Late-subscribing modules (e.g. MessagingInApp) attach before the identity event is published, so a screen-heavy buffer can no longer evict it from the SharedFlow replay window.
  • Setter ordering (P2 ci: automate lint and tests #1)isReady now sources from preInitBuffer.isReady instead of a separate componentsReady flag. The readiness signal flips atomically with the drain completing, so setProfileAttributes / setDeviceAttributes (which don't synchronize via DataPipelineInstance) route through the buffer for the entire pre-init and drain window, preserving FIFO order with earlier buffered calls.
  • Recursion-free replay — Buffered closures now invoke private *Internal methods that contain the bodies without the readiness gate, so replay against the real impl doesn't re-enter enqueue. The companion-level double-init guard moved to a separate initStarted flag latched at the start of initializeComponents().
  • Capacity during drainPreInitEventBuffer.enqueue now enforces capacity + drop accounting in the Draining state as well as Buffering, mirroring the iOS sister fix.

Aligned with customerio-ios-tng (no deliberate divergence): module wiring, identity broadcast, and event-stream drain occur in that order.

Test plan

  • ./gradlew :datapipelines:testDebugUnitTest — full suite green, including:
    • New PreInitEventBufferTest.drainingStateEnforcesCapacity — reentrant enqueues during drain hit the cap.
    • New FinishInitializationOrderTest.givenScreenHeavyPreInitBuffer_* — late-subscribing module receives the initial UserChangedEvent even when 101 pre-init screens are queued; buffered screens publish after subscription.
  • ./gradlew :messaginginapp:testDebugUnitTest — green.
  • ./gradlew :datapipelines:lintDebug — green.
  • ./ktlint --android on changed files — clean.
  • CI lint + tests (this PR).

🤖 Generated with Claude Code

…rdering

Addresses PR #700 review comments.

- `CustomerIO.finishInitialization()` now publishes the initial
  `UserChangedEvent` and drains the pre-init buffer **after** every module
  has run its `initialize()`. This means MessagingInApp (and any other
  late-subscribing module) attaches before the identity event is published,
  so a screen-heavy pre-init buffer can no longer evict it from the
  SharedFlow replay window.
- `isReady` now sources from `preInitBuffer.isReady` instead of the old
  `componentsReady` flag, so the readiness signal flips atomically with the
  drain completing. Public setters that don't synchronize via
  `DataPipelineInstance` (`setProfileAttributes`, `setDeviceAttributes`)
  therefore route through the buffer for the entire pre-init and drain
  window, preserving FIFO order with earlier buffered calls.
- Buffered closures now invoke private `*Internal` methods (identifyInternal,
  trackInternal, screenInternal, …) that contain the bodies without the
  readiness gate, avoiding recursive re-enqueue during replay. The double-
  init guard moved to a separate `initStarted` flag latched at the start of
  `initializeComponents()`.
- `PreInitEventBuffer.enqueue` now enforces capacity + drop accounting in
  the `Draining` state as well as `Buffering`. Mirrors the iOS fix; covered
  by a new `drainingStateEnforcesCapacity` unit test.
- New `FinishInitializationOrderTest` verifies that a late-subscribing
  module's `subscribe(UserChangedEvent)` happens before the initial
  publish, and that buffered screen events drain after subscription.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented May 18, 2026

Copy link
Copy Markdown

Sample app builds 📱

Below you will find the list of the latest versions of the sample apps. It's recommended to always download the latest builds of the sample apps to accurately test the pull request.


@codecov

codecov Bot commented May 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 65.00000% with 21 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.86%. Comparing base (2092f89) to head (7686efc).

Files with missing lines Patch % Lines
...ines/src/main/kotlin/io/customer/sdk/CustomerIO.kt 61.81% 14 Missing and 7 partials ⚠️
Additional details and impacted files
@@                     Coverage Diff                     @@
##             pre-init-event-buffer     #701      +/-   ##
===========================================================
+ Coverage                    67.70%   67.86%   +0.15%     
- Complexity                     876      889      +13     
===========================================================
  Files                          156      156              
  Lines                         4803     4832      +29     
  Branches                       669      670       +1     
===========================================================
+ Hits                          3252     3279      +27     
+ Misses                        1287     1286       -1     
- Partials                       264      267       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

Copy link
Copy Markdown
  • java_layout: address-pr-700-feedback (1779100235)

@github-actions

Copy link
Copy Markdown
  • kotlin_compose: address-pr-700-feedback (1779100228)

@github-actions

github-actions Bot commented May 18, 2026

Copy link
Copy Markdown

📏 SDK Binary Size Comparison Report

Module Last Recorded Size Current Size Change in Size
core 32.34 KB 32.34 KB ✅ No Change
datapipelines 48.81 KB 49.69 KB ⬆️ +0.88KB
messagingpush 28.93 KB 28.93 KB ✅ No Change
messaginginapp 121.84 KB 121.84 KB ✅ No Change
tracking-migration 22.89 KB 22.89 KB ✅ No Change

@github-actions

Copy link
Copy Markdown

Build available to test
Version: address-pr-700-feedback-SNAPSHOT
Repository: https://central.sonatype.com/repository/maven-snapshots/

…mpleApplication

Mirrors the iOS APN-UIKit AppDelegate scenarios. Toggle PRE_INIT_SCENARIO to
S1..S7 to exercise a specific case while running the sample app, then watch
logcat for `PreInitEventBuffer` entries and check server arrival via the
workspace's Activity Log. Default is OFF, leaving normal app behavior
unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
  • java_layout: address-pr-700-feedback (1779101757)

@github-actions

Copy link
Copy Markdown
  • kotlin_compose: address-pr-700-feedback (1779101757)

@mahmoud-elmorabea

Copy link
Copy Markdown
Contributor Author

Rolled into the original PR #700 as commit bdc4e1f4 (pushed directly onto pre-init-event-buffer). Closing this duplicate.

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