Repository navigation
feat: [SDK-5371] session model and sessions v2 feature flag - #1762
Conversation
Persist a per-session record that captures the sdk_sessions_v2_api_cutover flag at session start, pins the OneSignal and push subscription IDs, and measures foreground time with a monotonic clock. Nothing reads the record while the flag is off. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Multi-model review (Claude Opus 5.5, GPT 5.6 Sol, Grok 4.7) of the session record + sdk_sessions_v2_api_cutover pin.
Act on
- (3/3)
startNewSessionalways setsfocusedAt = nowand never commits the open interval. Tracker callsonFocusfirst, thenstartNewSession:dispatchesstartNewSessionInternalonto main. That later overwrite drops the dispatch/startup slice fromactiveDuration. If the user backgrounds before the async block runs,onUnfocuspersists time on the old record and this then replaces it withactiveDuration == 0. Keep an existing foreground stamp, and commitnow - focusedAtonto the record being replaced. - (3/3) Production
fromInit:YESalways replaces the only persisted slot without loading or finalizing it.testRecordSurvivesARestartconstructs a second service and never goes throughinit, so it does not model a cold start. Later PRs that send this record need a handoff (resume vs close-then-replace) decided here.
Consider
- (2/3)
fillPinnedIdsrefuses a latesubscriptionIdoncesessionIdentityModelIdhas moved, butcreateNewUser/identifyUserreuse the same push model. Init +login()before create-user returns can leave the first session withsubscriptionId == nilforever, while a known ID at start stays pinned through login. - Non-atomic provider reads (model id, onesignal id, push id) can tear across a login.
- If
initializeruns after the firstdidBecomeActive,lastOnFocusWasToBackgroundstaysYES, the first resign is ignored, and the nextonFocusthrows away the first visit. handleAppIdChange:clears other unscoped keys but notOSUD_SESSION_RECORD.
Noted
Flag-freeze test may not flip an APP_STARTUP latch. Failed decode sets loaded and never retries. No integration test that UserManager / Tracker actually write the record.
Dismissed
Flag-off still writing a record (documented). currentRecord fill side effects (intentional).
Sent by Cursor Automation: PR Reviews
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Addressed in b2c0925:
Not changing:
|
abdulraqeeb33
left a comment
There was a problem hiding this comment.
The replies say these are fixed in b2c0925, but that commit is on #1763, not this branch. At this head the subscriptionId fill gap after identifyUser (inline), the focusedAt overwrite in startNewSession (line 141), and the record clear on app id change are still open. Please move b2c0925 here, or merge the two PRs.
- Keep an open foreground interval when a session starts, so the visit that started it counts from focus and a background launch counts nothing. - Read the current user's IDs from one snapshot. - Fill in the subscription ID after a login that identified the same user. - Clear the stored record on an app-id change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Thanks, I'd fixed the commits being on wrong branch |
abdulraqeeb33
left a comment
There was a problem hiding this comment.
All three are fixed in f9e6376 and verified.
- Subscription id now fills in after identifyUser via the onesignal_id match, with a test.
- startNewSession leaves the focus stamp alone.
- handleAppIdChange clears the stored record.
Non-blocking, for the sender PR: resetAndClearStoredRecord drops the in-memory focusedAt, so an app id change while foregrounded skips the current visit until the next focus.
#1763 still carries b2c0925, so it needs a rebase onto this.
nan-li
left a comment
There was a problem hiding this comment.
One item worth addressing, inline on fillPinnedIds. The other two are a consider and a nit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The push subscription is carried across logins, so its ID is always this device's. A login that conflicted before the anonymous user was created left the session with no subscription ID, so it could never be sent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nan-li
left a comment
There was a problem hiding this comment.
Thanks for the work! LGTM
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>


Description
One Line Summary
Persist a per-session record that captures the
sdk_sessions_v2_api_cutoverflag and pinned user/subscription IDs at session start, and measure foreground time with a monotonic clock.Details
Motivation
First iOS PR in the SDK Sessions stack (SDK-5368), matching Android OneSignal/OneSignal-Android-SDK#2774. Later PRs need a persisted per-session record that knows which path the session is on and which user/subscription it belongs to, even after login.
Scope
OneSignal-KMP-SDKsubmodule to3a4ce04forFeatureFlag.SDK_SESSIONS_V2_API_CUTOVER(feat: [SDK-5369] add sdk_sessions_v2_api_cutover feature flag OneSignal-KMP-SDK#27), the same commit Android uses. It is on the KMPnew-session-eventsbranch, notmain.OSSessionServicein OneSignalOSCore with anOSSessionRecord: session UUID, start time, cumulative active duration,usesSessionsApi, pinnedonesignalIdandsubscriptionId, and aserverSessionIdslot. Persisted to UserDefaults underOSUD_SESSION_RECORD.OneSignalUserManagerImpl.startNewSession()starts a new record.OneSignalTrackerreports focus and unfocus.CLOCK_MONOTONIC_RAW. The focus stamp is in memory only, so a reboot or a previous process can never produce a bogus interval.Other
iOS has no local OneSignal IDs;
onesignal_idis nil until the user is created. The record pins the identity model's local ID too, and fills in the OneSignal ID once the backend assigns it to that same user. A missing subscription ID is only filled in while that user is still current, since after a login the push subscription is created for the new user. Logins and user switches leave pinned IDs alone.Testing
Unit testing
New
OSSessionServiceTests: flag capture on/off, flag fixed mid-session, new session ID per session, IDs pinned after login, IDs filled in once the session's user is created (and not for another user's subscription), duration across focus cycles, unfocus without focus, and the record surviving a restart.swiftlintadds no new violations.UnitTestApp_TestPlan_Reducedpasses apart from intermittent failures inUserConcurrencyTests.testSubscriptionExecutorConcurrencyandOneSignalUserTests, which pass on rerun and also fail intermittently on the base branch.Manual testing
Not tested on a device. No user-facing behavior changes with the flag off.
Affected code checklist
Checklist
Overview
Testing
Final pass
🤖 Generated with Claude Code