@nerdwallet/apollo-cache-policies
Advanced tools
Comparing version 2.10.0 to 2.11.0
@@ -0,1 +1,5 @@ | ||
2.11.0 (Dan Reynolds) | ||
Improve collection update performance. | ||
2.10.0 (Dan Reynolds) | ||
@@ -2,0 +6,0 @@ |
@@ -22,2 +22,3 @@ import { InMemoryCache, Cache, NormalizedCacheObject, Reference, StoreObject } from "@apollo/client/core"; | ||
protected isInitialized: boolean; | ||
protected pendingCollectionUpdates: Record<string, Record<string, Reference>>; | ||
constructor(config?: InvalidationPolicyCacheConfig); | ||
@@ -28,2 +29,3 @@ private reinitialize; | ||
protected broadcastWatches(): void; | ||
private get _hasPendingCollectionUpdates(); | ||
isOperatingOnRootData(): boolean; | ||
@@ -37,2 +39,4 @@ modify<Entity extends Record<string, any> = Record<string, any>>(options: Cache.ModifyOptions<Entity>): boolean; | ||
evict(options: Cache.EvictOptions): boolean; | ||
private _updatePendingCollection; | ||
private _updatePendingCollections; | ||
protected updateCollectionField(typename: string, dataId: string): void; | ||
@@ -39,0 +43,0 @@ private _expire; |
@@ -37,2 +37,3 @@ "use strict"; | ||
super(inMemoryCacheConfig); | ||
this.pendingCollectionUpdates = {}; | ||
this.enableCollections = enableCollections; | ||
@@ -109,2 +110,5 @@ this.invalidationPolicies = invalidationPolicies; | ||
} | ||
get _hasPendingCollectionUpdates() { | ||
return Object.keys(this.pendingCollectionUpdates).length > 0; | ||
} | ||
// Determines whether the cache's data reference is set to the root store. If not, then there is an ongoing optimistic transaction | ||
@@ -219,2 +223,30 @@ // being applied to a new layer. | ||
} | ||
_updatePendingCollection(collectionEntityId) { | ||
const updatedReferences = this.pendingCollectionUpdates[collectionEntityId]; | ||
if (!updatedReferences) { | ||
return; | ||
} | ||
this.modify({ | ||
broadcast: false, | ||
id: collectionEntityId, | ||
fields: { | ||
data: (existing, { canRead }) => { | ||
return [ | ||
...existing, | ||
...Object.values(updatedReferences), | ||
].filter(canRead); | ||
} | ||
} | ||
}); | ||
delete this.pendingCollectionUpdates[collectionEntityId]; | ||
} | ||
_updatePendingCollections() { | ||
if (!this._hasPendingCollectionUpdates) { | ||
return; | ||
} | ||
Object.keys(this.pendingCollectionUpdates).forEach((collectionEntityId) => { | ||
this._updatePendingCollection(collectionEntityId); | ||
}); | ||
this.broadcastWatches(); | ||
} | ||
updateCollectionField(typename, dataId) { | ||
@@ -247,14 +279,13 @@ // Since colletion support is still experimental, only record entities in collections if enabled | ||
if (!this.entityTypeMap.readEntityById(dataId)) { | ||
this.modify({ | ||
broadcast: false, | ||
id: collectionEntityId, | ||
fields: { | ||
data: (existing, { canRead }) => { | ||
return [ | ||
...existing.filter((ref) => canRead(ref)), | ||
(0, core_1.makeReference)(dataId), | ||
]; | ||
} | ||
} | ||
}); | ||
if (!this._hasPendingCollectionUpdates) { | ||
// Collection updates are scheduled on a separate tick so that they can be aggregated across the current tick and minimize the number | ||
// of collection modifications. | ||
process.nextTick(() => this._updatePendingCollections()); | ||
} | ||
if (!this.pendingCollectionUpdates[collectionEntityId]) { | ||
this.pendingCollectionUpdates[collectionEntityId] = {}; | ||
} | ||
if (!this.pendingCollectionUpdates[collectionEntityId][dataId]) { | ||
this.pendingCollectionUpdates[collectionEntityId][dataId] = (0, core_1.makeReference)(dataId); | ||
} | ||
} | ||
@@ -377,2 +408,5 @@ } | ||
extract(optimistic = false, withInvalidation = true) { | ||
if (this._hasPendingCollectionUpdates) { | ||
this._updatePendingCollections(); | ||
} | ||
const extractedCache = super.extract(optimistic); | ||
@@ -403,4 +437,8 @@ if (withInvalidation) { | ||
const { __typename, filter } = options; | ||
const collectionEntityName = (0, utils_1.collectionEntityIdForType)(__typename); | ||
const entityReferences = this.readField('data', (0, core_1.makeReference)(collectionEntityName)); | ||
const collectionEntityId = (0, utils_1.collectionEntityIdForType)(__typename); | ||
// If a stale collection is accessed while it has a pending update, then eagerly update it before the read. | ||
if (this.pendingCollectionUpdates[collectionEntityId]) { | ||
this._updatePendingCollection(collectionEntityId); | ||
} | ||
const entityReferences = this.readField('data', (0, core_1.makeReference)(collectionEntityId)); | ||
if (!entityReferences) { | ||
@@ -407,0 +445,0 @@ return []; |
{ | ||
"name": "@nerdwallet/apollo-cache-policies", | ||
"version": "2.10.0", | ||
"version": "2.11.0", | ||
"description": "An extension to the InMemoryCache from Apollo that adds additional cache policies.", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -54,8 +54,8 @@ ![Build](https://github.com/NerdWalletOSS/apollo-cache-policies/workflows/Build/badge.svg) | ||
import { InvalidationPolicyCache, RenewalPolicy } from '@nerdwallet/apollo-cache-policies'; | ||
const cache = new InvalidationPolicyCache({ | ||
typePolicies: {...}, | ||
invalidationPolicies: { | ||
timeToLive: 3600 * 1000; // 1hr TTL on all types in the cache | ||
renewalPolicy: RenewalPolicy.WriteOnly; | ||
timeToLive: 3600 * 1000, // 1hr TTL on all types in the cache | ||
renewalPolicy: RenewalPolicy.WriteOnly, | ||
types: { | ||
@@ -66,3 +66,3 @@ Employee: { | ||
EmployeeMessage: { | ||
renewalPolicy: RenewalPolicy.AccessAndWrite // The TTL for employee messages is renewed when the a message is read or written in the cache | ||
renewalPolicy: RenewalPolicy.AccessAndWrite // The TTL for employee messages is renewed when the message is read or written in the cache | ||
} | ||
@@ -69,0 +69,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
337239
2519