fix: switch to in-memory storage for events when necessary#2494
fix: switch to in-memory storage for events when necessary#2494saikumarrs wants to merge 6 commits into
Conversation
📝 WalkthroughWalkthrough📝 WalkthroughXhrQueue now falls back to in-memory storage when localStorage is unavailable; queue item type gains an optional Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant App
participant XhrQueue
participant StorageSelector
participant LocalStorage as "LOCAL_STORAGE"
participant MemoryStorage as "MEMORY_STORAGE"
App->>XhrQueue: initialize()
XhrQueue->>StorageSelector: isLocalStorageAvailable?
alt localStorage available
StorageSelector-->>LocalStorage: select
XhrQueue-->>App: use LOCAL_STORAGE
else fallback
StorageSelector-->>MemoryStorage: select
XhrQueue-->>App: use MEMORY_STORAGE
end
Note right of XhrQueue: queue items include optional\n`reclaimed?: boolean` in stored shape
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Pre-merge checks✅ Passed checks (3 passed)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
packages/analytics-js-plugins/src/xhrQueue/index.ts (1)
128-129: Good fallback; add a one-time log for observability when memory storage is used.This helps support/debugging in environments without localStorage (SW, Safari ITP, third‑party iframes). Suggest logging once at init.
Apply this diff:
storeManager, - // If local storage is available, use it, else use memory storage - state.capabilities.storage.isLocalStorageAvailable.value ? LOCAL_STORAGE : MEMORY_STORAGE, + // If local storage is available, use it, else use memory storage + (() => { + const storageType = state.capabilities.storage.isLocalStorageAvailable.value + ? LOCAL_STORAGE + : MEMORY_STORAGE; + if (storageType === MEMORY_STORAGE) { + logger?.info?.( + 'XhrQueue: Using in-memory storage for queue (localStorage unavailable)', + ); + } + return storageType; + })(), logger,packages/analytics-js-plugins/__tests__/xhrQueue/index.test.ts (2)
216-216: Avoid assertingreclaimed: undefinedin strict deep equals.This is brittle and ties tests to an internal optional field being materialized as
undefined. Prefer partial/object match.Example change (pattern):
- expect(queue.getStorageEntry('queue')).toStrictEqual([ - { - item: { /* ... */ }, - attemptNumber: 1, - lastAttemptedAt: expect.any(Number), - firstAttemptedAt: expect.any(Number), - reclaimed: undefined, - id: 'sample_uuid', - time: 1 + 1000 * 2 ** 1, - type: 'Single', - retryReason: 'server-429', - }, - ]); + expect(queue.getStorageEntry('queue')).toMatchObject([ + { + item: { /* ... */ }, + attemptNumber: 1, + lastAttemptedAt: expect.any(Number), + firstAttemptedAt: expect.any(Number), + id: 'sample_uuid', + time: 1 + 1000 * 2 ** 1, + type: 'Single', + retryReason: 'server-429', + }, + ]);Repeat similarly for the other two assertions.
Also applies to: 395-395, 503-503
55-66: Add a unit test for the storage fallback path.Set
state.capabilities.storage.isLocalStorageAvailable.value = falseand assert we log the in‑memory fallback during init.You can add a test like:
it('falls back to memory storage when localStorage is unavailable', () => { batch(() => { state.capabilities.storage.isLocalStorageAvailable.value = false; }); (XhrQueue()?.dataplaneEventsQueue as ExtensionPoint).init?.( state, defaultHttpClient, defaultStoreManager, undefined, defaultLogger, ); expect(defaultLogger.info).toHaveBeenCalledWith( 'XhrQueue: Using in-memory storage for queue (localStorage unavailable)', ); });If
defaultLogger.infoisn’t available in the mock, switch towarnin both code and test.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/analytics-js-plugins/__tests__/xhrQueue/index.test.ts(3 hunks)packages/analytics-js-plugins/src/xhrQueue/index.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/002-javascript-typescript.mdc)
Code must work in browsers AND service workers (no Node.js APIs)
Files:
packages/analytics-js-plugins/__tests__/xhrQueue/index.test.tspackages/analytics-js-plugins/src/xhrQueue/index.ts
packages/*/__tests__/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place unit tests under packages/[package-name]/tests/
Files:
packages/analytics-js-plugins/__tests__/xhrQueue/index.test.ts
packages/*/__tests__/**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Jest for tests and MSW for HTTP mocking
Files:
packages/analytics-js-plugins/__tests__/xhrQueue/index.test.ts
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Adhere to the repository’s ESLint configuration for JavaScript/TypeScript code
Files:
packages/analytics-js-plugins/__tests__/xhrQueue/index.test.tspackages/analytics-js-plugins/src/xhrQueue/index.ts
packages/*/src/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place all package source code under packages/[package-name]/src/
Files:
packages/analytics-js-plugins/src/xhrQueue/index.ts
packages/!(analytics-js-common)/**/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Prefer shared TypeScript types from analytics-js-common across packages
Files:
packages/analytics-js-plugins/src/xhrQueue/index.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: saikumarrs
PR: rudderlabs/rudder-sdk-js#1754
File: packages/analytics-js-service-worker/README.md:0-0
Timestamp: 2024-10-08T15:52:59.819Z
Learning: saikumarrs prefers simplified language in documentation, avoiding redundant phrases.
Learnt from: saikumarrs
PR: rudderlabs/rudder-sdk-js#1754
File: packages/analytics-js-service-worker/README.md:0-0
Timestamp: 2024-06-14T09:50:33.511Z
Learning: saikumarrs prefers simplified language in documentation, avoiding redundant phrases.
📚 Learning: 2024-11-08T13:17:51.356Z
Learnt from: saikumarrs
PR: rudderlabs/rudder-sdk-js#1823
File: packages/analytics-js-common/src/utilities/retryQueue/utilities.ts:0-0
Timestamp: 2024-11-08T13:17:51.356Z
Learning: The issue regarding missing test coverage for the `findOtherQueues` function in `packages/analytics-js-common/src/utilities/retryQueue/utilities.ts` is no longer applicable.
Applied to files:
packages/analytics-js-plugins/__tests__/xhrQueue/index.test.tspackages/analytics-js-plugins/src/xhrQueue/index.ts
📚 Learning: 2024-11-06T16:32:46.257Z
Learnt from: saikumarrs
PR: rudderlabs/rudder-sdk-js#1823
File: packages/analytics-js-plugins/src/xhrQueue/index.ts:34-34
Timestamp: 2024-11-06T16:32:46.257Z
Learning: The deprecated plugins have been removed from the `PluginName` type, so the explicit `PluginName` type annotation is no longer necessary in `packages/analytics-js-plugins/src/xhrQueue/index.ts`.
Applied to files:
packages/analytics-js-plugins/__tests__/xhrQueue/index.test.tspackages/analytics-js-plugins/src/xhrQueue/index.ts
📚 Learning: 2024-10-08T15:52:59.819Z
Learnt from: saikumarrs
PR: rudderlabs/rudder-sdk-js#1708
File: packages/analytics-js-plugins/__tests__/deviceModeTransformation/index.test.ts:10-11
Timestamp: 2024-10-08T15:52:59.819Z
Learning: The misuse of `IHttpClient` in type assertions within the file `packages/analytics-js-plugins/__tests__/deviceModeTransformation/index.test.ts` has been corrected by the user.
Applied to files:
packages/analytics-js-plugins/__tests__/xhrQueue/index.test.ts
🧬 Code graph analysis (1)
packages/analytics-js-plugins/src/xhrQueue/index.ts (1)
packages/analytics-js-plugins/src/shared-chunks/common.ts (2)
LOCAL_STORAGE(3-3)MEMORY_STORAGE(4-4)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Bundle size checks
- GitHub Check: Code quality checks
- GitHub Check: Unit Tests and Lint
🔇 Additional comments (1)
packages/analytics-js-plugins/src/xhrQueue/index.ts (1)
34-35: Import looks correct.Brings in MEMORY_STORAGE for the fallback; aligns with the new selection logic.
size-limit report 📦
|
6aeaca7
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
.github/workflows/deploy-npm.yml (1)
164-164: Verbose publish is fine; double-check logs for secrets.
--verboseis helpful for debugging. Please verify nx/npm verbose output won’t echo tokens, npmrc, or other secrets. Optionally gate verbosity via an input (e.g., only for beta) to reduce noise..github/workflows/deploy-beta.yml (2)
85-86: Non-mergeable PR guard disabled.Deploys may proceed even when PRs aren’t mergeable (conflicts). If this is temporary, consider adding a feature flag/input to re-enable the check without code edits.
105-106: ‘mergeable_state !== clean’ guard disabled.This permits deploys with failing checks or missing approvals. If intended, consider logging the computed reason (blocked/dirty/unstable/unknown) at info level for auditability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
.github/workflows/deploy-beta.yml(5 hunks).github/workflows/deploy-npm.yml(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: saikumarrs
PR: rudderlabs/rudder-sdk-js#1754
File: packages/analytics-js-service-worker/README.md:0-0
Timestamp: 2024-10-08T15:52:59.819Z
Learning: saikumarrs prefers simplified language in documentation, avoiding redundant phrases.
Learnt from: saikumarrs
PR: rudderlabs/rudder-sdk-js#1754
File: packages/analytics-js-service-worker/README.md:0-0
Timestamp: 2024-06-14T09:50:33.511Z
Learning: saikumarrs prefers simplified language in documentation, avoiding redundant phrases.
📚 Learning: 2025-06-26T12:33:40.146Z
Learnt from: saikumarrs
PR: rudderlabs/rudder-sdk-js#2308
File: .github/workflows/deploy-staging.yml:26-27
Timestamp: 2025-06-26T12:33:40.146Z
Learning: The `deploy-staging.yml` workflow only triggers on `pull_request` events, so the `trigger_source` variable correctly assumes PR context is always available and doesn't need guards for other event types.
Applied to files:
.github/workflows/deploy-beta.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Deploy to NPM / Deploy to NPM
- GitHub Check: Get affected projects
- GitHub Check: Unit Tests and Lint
🔇 Additional comments (1)
.github/workflows/deploy-beta.yml (1)
72-73: Draft PR guard disabled.Commenting out the failure/return allows beta deploys from draft PRs. Confirm this relaxation is intentional for this workflow.
|
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
-
.github/workflows/deploy-beta.yml(1 hunks) -
.github/workflows/deploy-npm.yml(3 hunks) -
.github/workflows/publish-new-release.yml(1 hunks) -
.github/workflows/rollback.yml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- .github/workflows/deploy-npm.yml
- .github/workflows/deploy-beta.yml
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: saikumarrs
PR: rudderlabs/rudder-sdk-js#1754
File: packages/analytics-js-service-worker/README.md:0-0
Timestamp: 2024-10-08T15:52:59.819Z
Learning: saikumarrs prefers simplified language in documentation, avoiding redundant phrases.
Learnt from: saikumarrs
PR: rudderlabs/rudder-sdk-js#1754
File: packages/analytics-js-service-worker/README.md:0-0
Timestamp: 2024-06-14T09:50:33.511Z
Learning: saikumarrs prefers simplified language in documentation, avoiding redundant phrases.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Bundle size checks
- GitHub Check: Code quality checks
- GitHub Check: Unit Tests and Lint
🔇 Additional comments (1)
.github/workflows/publish-new-release.yml (1)
271-273: NPM token plumbed — deploy-npm.yml consumes itdeploy-npm.yml sets NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} and runs npm set //registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }} before publishing/deprecating (see .github/workflows/deploy-npm.yml).
|
This is not needed anymore as it is being released as a hotfix. |



PR Description
Switched to in-memory storage for events when local storage is unavailable. This is needed in restrictive environments like Safari v26 and above.
Linear task (optional)
https://linear.app/rudderstack/issue/SDK-3972/switch-to-in-memory-storage-for-storing-events-when-persistent-storage
Cross Browser Tests
Please confirm you have tested for the following browsers:
Sanity Suite
Security
Summary by CodeRabbit
New Features
Bug Fixes
Chores