@memberjunction/graphql-dataprovider 5.30.0 → 5.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -667,11 +667,40 @@ For comprehensive information about IS-A relationships in MemberJunction:
667
667
 
668
668
  ## Caching & Real-Time Sync
669
669
 
670
- This package provides browser-side storage providers (`BrowserIndexedDBStorageProvider`, `BrowserLocalStorageProvider`) for `LocalCacheManager`, and subscribes to `CACHE_INVALIDATION` GraphQL events to keep browser data fresh when other users or servers modify entities.
670
+ This package provides browser-side storage providers for `LocalCacheManager` and subscribes to `CACHE_INVALIDATION` GraphQL events to keep browser data fresh when other users or servers modify entities.
671
671
 
672
- `setupGraphQLClient` orchestrates a deterministic warm-load path: after `provider.Config(...)` loads the cached `AllMetadata` blob from IndexedDB (gzip-compressed), it calls `provider.preValidateAndRefresh()` to confirm the cache is current via a single batched timestamp round-trip. If current, fast-start engages and engines trust their local IndexedDB caches without per-view smart-cache-check round-trips during `StartupManager.Startup()`. If stale, metadata is refreshed in place and fast-start is disabled so engines fall through to smart-cache-check.
672
+ ### Storage providers
673
673
 
674
- For the full architecture including differential updates, the fast-start window, Redis cross-server sync, session-based deduplication, and deployment topologies — see the [**Caching & Pub/Sub Guide**](/guides/CACHING_AND_PUBSUB_GUIDE.md).
674
+ | Provider | Backing store | Key features |
675
+ |---|---|---|
676
+ | `BrowserIndexedDBStorageProvider` | IndexedDB | **Native object storage via structured clone** (no JSON parse/stringify on the hot path), **single-transaction batched reads via `GetItems`**, per-category object stores, version-bumped wipe on minor releases |
677
+ | `BrowserLocalStorageProvider` | `localStorage` | Generic-typed `SetItem<T>` / `GetItem<T>` / `GetItems<T>` with internal JSON serialization, key-prefix-based category isolation |
678
+
679
+ Both implement the generic-typed `ILocalStorageProvider` interface defined in `@memberjunction/core` — see that package's README for interface details.
680
+
681
+ ### IndexedDB schema versioning (auto-derived from package version)
682
+
683
+ `BrowserIndexedDBStorageProvider` ties its IDB `DB_VERSION` to this package's `package.json` version (`major * 1000 + minor`):
684
+
685
+ - **5.30.x** → DB version `5030`
686
+ - **5.31.x** → DB version `5031`
687
+ - **6.0.x** → DB version `6000`
688
+
689
+ Patch releases keep the same DB version, so frequent patch deploys don't force users into cold-cache loads. Each minor release triggers a one-time `onupgradeneeded` that wipes all object stores; caches repopulate on first use.
690
+
691
+ The version is generated at build time by `scripts/generate-version.mjs` (runs as a `prebuild`/`pretest` step) into `src/version.generated.ts`. To force an extra wipe within the same minor (rare — emergency hotfix scenario), bump the `MANUAL_CACHE_REVISION` constant at the top of `storage-providers.ts`.
692
+
693
+ ### Batched IDB reads (single-transaction)
694
+
695
+ `BrowserIndexedDBStorageProvider.GetItems<T>(keys, category?)` reads N keys inside a single read transaction. Per-call IDB transaction overhead is real (~3–10ms each in most browsers) and *serialized* on the same object store, so `Promise.all([...N GetItem calls])` actually pays N × overhead even though it looks parallel.
696
+
697
+ For the warm-load smart-cache-check flow this matters a lot — the client reads cached fingerprint metadata for every view in the coalesced engine bundle, then reads the actual cached row data for entries the server marks as 'current'. Both passes used to do per-key reads; both now use `GetItems` to amortize the overhead into one transaction. For 85 keys this is the difference between ~425ms of pure IDB bookkeeping and ~10ms.
698
+
699
+ ### Warm-load orchestration
700
+
701
+ `setupGraphQLClient` orchestrates a deterministic warm-load path: after `provider.Config(...)` loads the cached `AllMetadata` blob from IndexedDB (gzip-compressed, three keys read in a single batched call), it calls `provider.preValidateAndRefresh()` to confirm the cache is current via a single batched timestamp round-trip. If current, engines trust their local caches and route per-view requests through `RunViewsWithCacheCheck` — a fingerprint-only GraphQL call that returns either a "current" marker (use local cache) or fresh data for stale entries.
702
+
703
+ For the full architecture — differential updates, Redis cross-server sync, session-based deduplication, and deployment topologies — see the [**Caching & Pub/Sub Guide**](/guides/CACHING_AND_PUBSUB_GUIDE.md).
675
704
 
676
705
  ## Dependencies
677
706