@luvio/environments 0.72.0 → 0.73.3

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.
Files changed (28) hide show
  1. package/dist/es/es2018/environments.js +62 -388
  2. package/dist/umd/es2018/environments.js +61 -387
  3. package/dist/umd/es5/environments.js +61 -398
  4. package/package.json +2 -2
  5. package/dist/es/es2018/makeDurable/cachepolicies/cache-and-network.d.ts +0 -3
  6. package/dist/es/es2018/makeDurable/cachepolicies/cache-then-network.d.ts +0 -3
  7. package/dist/es/es2018/makeDurable/cachepolicies/index.d.ts +0 -6
  8. package/dist/es/es2018/makeDurable/cachepolicies/no-cache.d.ts +0 -3
  9. package/dist/es/es2018/makeDurable/cachepolicies/only-if-cached.d.ts +0 -3
  10. package/dist/es/es2018/makeDurable/cachepolicies/stale-while-revalidate.d.ts +0 -3
  11. package/dist/es/es2018/makeDurable/cachepolicies/utils.d.ts +0 -9
  12. package/dist/es/es2018/makeDurable/cachepolicies/valid-at.d.ts +0 -3
  13. package/dist/umd/es2018/makeDurable/cachepolicies/cache-and-network.d.ts +0 -3
  14. package/dist/umd/es2018/makeDurable/cachepolicies/cache-then-network.d.ts +0 -3
  15. package/dist/umd/es2018/makeDurable/cachepolicies/index.d.ts +0 -6
  16. package/dist/umd/es2018/makeDurable/cachepolicies/no-cache.d.ts +0 -3
  17. package/dist/umd/es2018/makeDurable/cachepolicies/only-if-cached.d.ts +0 -3
  18. package/dist/umd/es2018/makeDurable/cachepolicies/stale-while-revalidate.d.ts +0 -3
  19. package/dist/umd/es2018/makeDurable/cachepolicies/utils.d.ts +0 -9
  20. package/dist/umd/es2018/makeDurable/cachepolicies/valid-at.d.ts +0 -3
  21. package/dist/umd/es5/makeDurable/cachepolicies/cache-and-network.d.ts +0 -3
  22. package/dist/umd/es5/makeDurable/cachepolicies/cache-then-network.d.ts +0 -3
  23. package/dist/umd/es5/makeDurable/cachepolicies/index.d.ts +0 -6
  24. package/dist/umd/es5/makeDurable/cachepolicies/no-cache.d.ts +0 -3
  25. package/dist/umd/es5/makeDurable/cachepolicies/only-if-cached.d.ts +0 -3
  26. package/dist/umd/es5/makeDurable/cachepolicies/stale-while-revalidate.d.ts +0 -3
  27. package/dist/umd/es5/makeDurable/cachepolicies/utils.d.ts +0 -9
  28. package/dist/umd/es5/makeDurable/cachepolicies/valid-at.d.ts +0 -3
@@ -1,4 +1,4 @@
1
- import { StoreResolveResultState, HttpStatusCode, Store, coerceAdapterRequestContext } from '@luvio/engine';
1
+ import { buildStaleWhileRevalidateImplementation, Store } from '@luvio/engine';
2
2
 
3
3
  function isDeprecatedDurableStoreEntry(durableRecord) {
4
4
  if (durableRecord.expiration !== undefined) {
@@ -17,292 +17,6 @@ const DefaultDurableSegment = 'DEFAULT';
17
17
  const { keys, create, assign, freeze } = Object;
18
18
  const { isArray } = Array;
19
19
 
20
- function appendTTLStrategy(storeLookup, ttlStrategy) {
21
- const returnStoreLookup = (sel, refresh) => storeLookup(sel, refresh, ttlStrategy);
22
- // append ttlStrategy to storeLookup function (in cases where custom adapter
23
- // wants to perform it's own lookup)
24
- returnStoreLookup.ttlStrategy = ttlStrategy;
25
- return returnStoreLookup;
26
- }
27
- function buildNetworkSnapshot(args) {
28
- const { buildNetworkSnapshot, buildSnapshotContext, coercedAdapterRequestContext } = args;
29
- return buildNetworkSnapshot(buildSnapshotContext, coercedAdapterRequestContext).then((snapshot) => snapshot.state === 'Pending' ? args.resolvePendingSnapshot(snapshot) : snapshot);
30
- }
31
- function buildTTLStrategy(staleDurationMilliseconds = 0) {
32
- return (timestamp, metadata, valueIsError) => {
33
- if (metadata !== undefined) {
34
- const { expirationTimestamp } = metadata;
35
- if (timestamp > expirationTimestamp) {
36
- if (timestamp <= expirationTimestamp + staleDurationMilliseconds &&
37
- valueIsError !== true) {
38
- return StoreResolveResultState.Stale;
39
- }
40
- return StoreResolveResultState.NotPresent;
41
- }
42
- }
43
- if (valueIsError === true) {
44
- return StoreResolveResultState.Error;
45
- }
46
- return StoreResolveResultState.Found;
47
- };
48
- }
49
- // TODO - update userland-facing APIs to return `AvailableSnapshot` instead of `Snapshot`
50
- // and then the signatures here can be updated as well
51
- function buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, availableSnapshotFunc) {
52
- if (isPromise(cachedSnapshot)) {
53
- return cachedSnapshot.then(availableSnapshotFunc);
54
- }
55
- return availableSnapshotFunc(cachedSnapshot);
56
- }
57
- function isPromise(value) {
58
- if (value === undefined) {
59
- return false;
60
- }
61
- // check for Thenable due to test frameworks using custom Promise impls
62
- return value.then !== undefined;
63
- }
64
-
65
- function buildCacheAndNetworkImplementation(funcs, staleDurationSeconds = 0) {
66
- return function (args) {
67
- funcs.validateNotDisposed();
68
- const { buildCachedSnapshot, buildNetworkSnapshot: buildNetworkSnapshot$1, buildSnapshotContext, storeLookup, coercedAdapterRequestContext, } = args;
69
- const staleDurationMilliseconds = staleDurationSeconds * 1000;
70
- const cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy(staleDurationMilliseconds));
71
- const cachedSnapshot = buildCachedSnapshot(buildSnapshotContext, cachePolicyStoreLookup);
72
- return buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, (snapshot) => {
73
- if (snapshot !== undefined) {
74
- // data found in L1 cache
75
- if (snapshot.state === 'Fulfilled' ||
76
- snapshot.state === 'Error' ||
77
- snapshot.state === 'Stale') {
78
- // kick off network request, do not await it
79
- buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
80
- // return the cached snapshot to caller
81
- return snapshot;
82
- }
83
- // network request outstanding
84
- if (snapshot.state === 'Pending') {
85
- // kick off another network request, do not await it
86
- buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
87
- return args.resolvePendingSnapshot(snapshot);
88
- }
89
- // if unfulfilled we have enough info to do an L2 lookup
90
- if (snapshot.state === 'Unfulfilled') {
91
- return funcs
92
- .reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
93
- .then((revivedSnapshot) => {
94
- // data found in L2 cache
95
- if (revivedSnapshot.state === 'Fulfilled' ||
96
- revivedSnapshot.state === 'Error' ||
97
- revivedSnapshot.state === 'Stale') {
98
- // kick off network request, do not await it
99
- buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
100
- // return the L2 cached snapshot to caller
101
- return revivedSnapshot;
102
- }
103
- if (revivedSnapshot.state === 'Pending') {
104
- // kick off network request, do not await it
105
- buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
106
- return args.resolvePendingSnapshot(revivedSnapshot);
107
- }
108
- // data not found in L2 cache, go to the network
109
- return buildNetworkSnapshot(args);
110
- });
111
- }
112
- }
113
- return buildNetworkSnapshot(args);
114
- });
115
- };
116
- }
117
-
118
- function buildCacheThenNetworkImplementation(funcs) {
119
- return function (args) {
120
- funcs.validateNotDisposed();
121
- const { buildCachedSnapshot, buildSnapshotContext, storeLookup } = args;
122
- const cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy());
123
- const cachedSnapshot = buildCachedSnapshot(buildSnapshotContext, cachePolicyStoreLookup);
124
- return buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, (snapshot) => {
125
- if (snapshot !== undefined) {
126
- // data found in L1 cache
127
- if (snapshot.state === 'Fulfilled' || snapshot.state === 'Error') {
128
- return snapshot;
129
- }
130
- if (snapshot.state === 'Pending') {
131
- return args.resolvePendingSnapshot(snapshot);
132
- }
133
- // if unfulfilled we have enough info to do an L2 lookup
134
- if (snapshot.state === 'Unfulfilled') {
135
- return funcs
136
- .reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
137
- .then((revivedSnapshot) => {
138
- // data found in L2 cache
139
- if (revivedSnapshot.state === 'Fulfilled' ||
140
- revivedSnapshot.state === 'Error') {
141
- return revivedSnapshot;
142
- }
143
- if (revivedSnapshot.state === 'Pending') {
144
- return args.resolvePendingSnapshot(revivedSnapshot);
145
- }
146
- // data not found in L2 cache, go to the network
147
- return buildNetworkSnapshot(args);
148
- });
149
- }
150
- }
151
- // L1 lookup could not find enough information to even construct a snapshot, go to the network
152
- return buildNetworkSnapshot(args);
153
- });
154
- };
155
- }
156
-
157
- function buildNoCacheImplementation(funcs) {
158
- return function (args) {
159
- funcs.validateNotDisposed();
160
- return buildNetworkSnapshot(args);
161
- };
162
- }
163
-
164
- function deepFreeze(value) {
165
- // No need to freeze primitives
166
- if (typeof value !== 'object' || value === null) {
167
- return;
168
- }
169
- if (isArray(value)) {
170
- for (let i = 0, len = value.length; i < len; i += 1) {
171
- deepFreeze(value[i]);
172
- }
173
- }
174
- else {
175
- const keys$1 = keys(value);
176
- for (let i = 0, len = keys$1.length; i < len; i += 1) {
177
- deepFreeze(value[keys$1[i]]);
178
- }
179
- }
180
- freeze(value);
181
- }
182
-
183
- // TODO[@W-10165595]: consolidate this code with the corresponding logic in the default environment's only-if-cached.ts
184
- function buildNotCachedErrorSnapshot() {
185
- const error = {
186
- body: undefined,
187
- headers: {},
188
- ok: false,
189
- status: HttpStatusCode.GatewayTimeout,
190
- statusText: 'Gateway Timeout',
191
- };
192
- deepFreeze(error);
193
- return {
194
- error,
195
- state: 'Error',
196
- data: undefined,
197
- // TODO[@W-10164067]: copy refresh data from the snapshot returned by buildCachedSnapshot (if any)
198
- // refresh: ...
199
- };
200
- }
201
- function buildOnlyIfCachedImplementation(funcs) {
202
- return function (args) {
203
- funcs.validateNotDisposed();
204
- const { buildCachedSnapshot, buildSnapshotContext, storeLookup } = args;
205
- const cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy());
206
- const cachedSnapshot = buildCachedSnapshot(buildSnapshotContext, cachePolicyStoreLookup);
207
- return buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, (snapshot) => {
208
- if (snapshot !== undefined) {
209
- // data found in L1 cache
210
- if (snapshot.state === 'Fulfilled' || snapshot.state === 'Error') {
211
- return snapshot;
212
- }
213
- // network request outstanding, data is not cached
214
- if (snapshot.state === 'Pending') {
215
- return buildNotCachedErrorSnapshot();
216
- }
217
- // if unfulfilled we have enough info to do an L2 lookup
218
- if (snapshot.state === 'Unfulfilled') {
219
- return funcs
220
- .reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
221
- .then((revivedSnapshot) => {
222
- // data found in L2 cache
223
- if (revivedSnapshot.state === 'Fulfilled' ||
224
- revivedSnapshot.state === 'Error') {
225
- return revivedSnapshot;
226
- }
227
- // data is not cached
228
- return buildNotCachedErrorSnapshot();
229
- });
230
- }
231
- }
232
- return buildNotCachedErrorSnapshot();
233
- });
234
- };
235
- }
236
-
237
- function buildStaleWhileRevalidateImplementation(funcs, staleDurationSeconds) {
238
- return function (args) {
239
- funcs.validateNotDisposed();
240
- const { buildCachedSnapshot, buildSnapshotContext, storeLookup } = args;
241
- const cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy(staleDurationSeconds * 1000));
242
- const cachedSnapshot = buildCachedSnapshot(buildSnapshotContext, cachePolicyStoreLookup);
243
- return buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, (snapshot) => {
244
- if (snapshot !== undefined) {
245
- // data found in L1 cache
246
- if (snapshot.state === 'Fulfilled' || snapshot.state === 'Error') {
247
- return snapshot;
248
- }
249
- if (snapshot.state === 'Pending') {
250
- return args.resolvePendingSnapshot(snapshot);
251
- }
252
- // stale data found in L1 cache
253
- if (snapshot.state === 'Stale') {
254
- buildNetworkSnapshot(args);
255
- return snapshot;
256
- }
257
- // data not found in L1 cache, try L2 cache
258
- return funcs
259
- .reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
260
- .then((revivedSnapshot) => {
261
- // data found in L2 cache
262
- if (revivedSnapshot.state === 'Fulfilled' ||
263
- revivedSnapshot.state === 'Error') {
264
- return revivedSnapshot;
265
- }
266
- if (revivedSnapshot.state === 'Pending') {
267
- return args.resolvePendingSnapshot(revivedSnapshot);
268
- }
269
- // stale data found in L2 cache
270
- if (revivedSnapshot.state === 'Stale') {
271
- buildNetworkSnapshot(args);
272
- return revivedSnapshot;
273
- }
274
- // data not found in L2 cache, go to the network
275
- return buildNetworkSnapshot(args);
276
- });
277
- }
278
- // L1 lookup could not find enough information to even construct a snapshot, go to the network
279
- return buildNetworkSnapshot(args);
280
- });
281
- };
282
- }
283
-
284
- function buildValidAtImplementation(funcs, basePolicyImplementation, timestamp) {
285
- return function validAtImplementation(args) {
286
- funcs.validateNotDisposed();
287
- // This somewhat convoluted code is used to force the basePolicyImplementation's
288
- // TTLStrategy to use the the valid-at cache policy's timestamp. The flow goes:
289
- //
290
- // Environment.applyCachePolicy => validAtImplementation (this function) =>
291
- // basePolicyImplementation => adapter's buildCachedSnapshot =>
292
- // basePolicyImplementation's storeLookup => validAtStoreLookup (below) =>
293
- // Environment.applyCachePolicy's storeLookup => Store/Reader code =>
294
- // valid-at TTLStrategy (below) =>
295
- // basePolicyImplementation's TTLStrategy (with valid-at timestamp)
296
- const validAtStoreLookup = (sel, refresh, ttlStrategy) => args.storeLookup(sel, refresh, (_readerTimestamp, metadata, valueIsError) => ttlStrategy(timestamp, metadata, valueIsError));
297
- // let basePolicy make all the decisions, but have it use our storeLookup
298
- // so we can override the timestamp passed to the basePolicy's TTLStrategy
299
- return basePolicyImplementation({
300
- ...args,
301
- storeLookup: validAtStoreLookup,
302
- });
303
- };
304
- }
305
-
306
20
  //Durable store error instrumentation key
307
21
  const DURABLE_STORE_ERROR = 'durable-store-error';
308
22
  /**
@@ -327,6 +41,25 @@ function handleDurableStoreRejection(instrument) {
327
41
  };
328
42
  }
329
43
 
44
+ function deepFreeze(value) {
45
+ // No need to freeze primitives
46
+ if (typeof value !== 'object' || value === null) {
47
+ return;
48
+ }
49
+ if (isArray(value)) {
50
+ for (let i = 0, len = value.length; i < len; i += 1) {
51
+ deepFreeze(value[i]);
52
+ }
53
+ }
54
+ else {
55
+ const keys$1 = keys(value);
56
+ for (let i = 0, len = keys$1.length; i < len; i += 1) {
57
+ deepFreeze(value[keys$1[i]]);
58
+ }
59
+ }
60
+ freeze(value);
61
+ }
62
+
330
63
  const SELECTOR_PAGINATION_TOKEN = 'tokenDataKey';
331
64
  function isFragmentUnionSelection(sel) {
332
65
  return sel.union === true;
@@ -696,6 +429,15 @@ function reviveOrCreateContext(adapterId, durableStore, durableStoreErrorHandler
696
429
  return contextReturn();
697
430
  });
698
431
  }
432
+ function isUnfulfilledSnapshot(cachedSnapshotResult) {
433
+ if (cachedSnapshotResult === undefined) {
434
+ return false;
435
+ }
436
+ if ('then' in cachedSnapshotResult) {
437
+ return false;
438
+ }
439
+ return cachedSnapshotResult.state === 'Unfulfilled';
440
+ }
699
441
  /**
700
442
  * Configures the environment to persist data into a durable store and attempt to resolve
701
443
  * data from the persistent store before hitting the network.
@@ -806,12 +548,9 @@ function makeDurable(environment, { durableStore, instrumentation }) {
806
548
  };
807
549
  const storeBroadcast = function (_rebuildSnapshot, _snapshotDataAvailable) {
808
550
  validateNotDisposed();
809
- // for our environment we basically want a broadcast to be a "durable store broadcast",
810
- // so we flush staging store to L2, which will cause the onChanged handler to fire
811
- // which will revive records to the main L1 store and call the base storeBroadcast
812
- // don't await the DS write - DS implementation will take care of R/W
813
- // synchronization
814
- publishChangesToDurableStore();
551
+ // no-op here and wait for the L2 flush to happen in handleSuccessResponse,
552
+ // that flush will cause the onChanged handler to fire which will revive
553
+ // records to the main L1 store and call the base storeBroadcast
815
554
  };
816
555
  const publishChangesToDurableStore = function () {
817
556
  validateNotDisposed();
@@ -853,28 +592,6 @@ function makeDurable(environment, { durableStore, instrumentation }) {
853
592
  }
854
593
  return environment.wrapNormalizedGraphNode(normalized, ingestStagingStore);
855
594
  };
856
- const resolveSnapshot = function (snapshot, refresh) {
857
- validateNotDisposed();
858
- // if the snapshot is already pending then no need to kick off another
859
- // revive, just wait for the pending refresh to broadcast
860
- if (snapshot.state === 'Pending') {
861
- return environment.resolvePendingSnapshot(snapshot);
862
- }
863
- const { resolve, config } = refresh;
864
- const refreshFunc = () => resolve(config);
865
- // if the snapshot is unfulfilled we can do an L2 lookup
866
- if (snapshot.state === 'Unfulfilled') {
867
- return reviveSnapshot(environment, durableStore, snapshot, durableStoreErrorHandler, () => environment.storeLookup(snapshot.select, environment.createSnapshot, snapshot.refresh)).then((durableSnapshot) => {
868
- if (environment.snapshotAvailable(durableSnapshot)) {
869
- // L2 cache hit
870
- return durableSnapshot;
871
- }
872
- // else have to hit network
873
- return refreshFunc();
874
- });
875
- }
876
- return refreshFunc();
877
- };
878
595
  const rebuildSnapshot = function (snapshot, records, storeMetadataMap, redirects, onAsyncRebuild) {
879
596
  validateNotDisposed();
880
597
  // try rebuilding from memory
@@ -937,73 +654,20 @@ function makeDurable(environment, { durableStore, instrumentation }) {
937
654
  validateNotDisposed();
938
655
  return durableTTLStore.getDurableTTLOverrides();
939
656
  };
940
- // reviveSnapshot wrapper to let cache policies revive data from L2 and
941
- // access the revived data via their own storeLookups
942
- const reviveSnapshotWithCachePolicy = (unavailableSnapshot, storeLookup) => reviveSnapshot(environment, durableStore, unavailableSnapshot, durableStoreErrorHandler, () => storeLookup(unavailableSnapshot.select, unavailableSnapshot.refresh));
943
- const defaultCachePolicy = buildStaleWhileRevalidateImplementation({
944
- validateNotDisposed,
945
- reviveSnapshotWithCachePolicy,
946
- }, Number.MAX_SAFE_INTEGER);
947
- function resolveCachePolicy(cachePolicy) {
948
- if (cachePolicy === undefined) {
949
- return defaultCachePolicy;
950
- }
951
- switch (cachePolicy.type) {
952
- case 'stale-while-revalidate':
953
- return buildStaleWhileRevalidateImplementation({
954
- validateNotDisposed,
955
- reviveSnapshotWithCachePolicy,
956
- }, cachePolicy.staleDurationSeconds);
957
- case 'cache-and-network':
958
- return buildCacheAndNetworkImplementation({
959
- validateNotDisposed,
960
- reviveSnapshotWithCachePolicy,
961
- }, cachePolicy.staleDurationSeconds);
962
- case 'cache-then-network':
963
- return buildCacheThenNetworkImplementation({
964
- validateNotDisposed,
965
- reviveSnapshotWithCachePolicy,
966
- });
967
- case 'no-cache':
968
- return buildNoCacheImplementation({
969
- validateNotDisposed,
970
- reviveSnapshotWithCachePolicy,
971
- });
972
- case 'only-if-cached':
973
- return buildOnlyIfCachedImplementation({
974
- validateNotDisposed,
975
- reviveSnapshotWithCachePolicy,
976
- });
977
- case 'valid-at': {
978
- const basePolicy = resolveCachePolicy(cachePolicy.basePolicy);
979
- return buildValidAtImplementation({
980
- validateNotDisposed,
981
- reviveSnapshotWithCachePolicy,
982
- }, basePolicy, cachePolicy.timestamp);
983
- }
984
- default: {
985
- if (process.env.NODE_ENV !== 'production') {
986
- throw new Error(`unrecognized cache policy: ${JSON.stringify(cachePolicy)}`);
987
- }
988
- return defaultCachePolicy;
989
- }
990
- }
991
- }
992
657
  const applyCachePolicy = function (adapterRequestContext, buildSnapshotContext, buildCachedSnapshot, buildNetworkSnapshot) {
993
658
  validateNotDisposed();
994
- const { cachePolicy } = adapterRequestContext;
995
- const cachePolicyImpl = resolveCachePolicy(cachePolicy);
996
- const resolvePendingSnapshot = (snapshot) => environment.resolvePendingSnapshot(snapshot);
997
- const storeLookup = (sel, refresh, ttlStrategy) => environment.storeLookup(sel, environment.createSnapshot, refresh, ttlStrategy);
659
+ const wrappedCacheLookup = (buildSnapshotContext, storeLookup) => {
660
+ const snapshot = buildCachedSnapshot(buildSnapshotContext, storeLookup);
661
+ // if the adapter attempted to do an L1 lookup and it was unfulfilled
662
+ // then we can attempt an L2 lookup
663
+ if (isUnfulfilledSnapshot(snapshot)) {
664
+ return reviveSnapshot(environment, durableStore, snapshot, durableStoreErrorHandler, () => storeLookup(snapshot.select, snapshot.refresh));
665
+ }
666
+ // otherwise just return what buildCachedSnapshot gave us
667
+ return snapshot;
668
+ };
998
669
  const applyCachePolicy = () => {
999
- return cachePolicyImpl({
1000
- buildCachedSnapshot,
1001
- buildNetworkSnapshot,
1002
- buildSnapshotContext,
1003
- resolvePendingSnapshot,
1004
- storeLookup,
1005
- coercedAdapterRequestContext: coerceAdapterRequestContext(adapterRequestContext),
1006
- });
670
+ return environment.applyCachePolicy(adapterRequestContext, buildSnapshotContext, wrappedCacheLookup, buildNetworkSnapshot);
1007
671
  };
1008
672
  return isRevivingTTLOverrides !== undefined
1009
673
  ? isRevivingTTLOverrides.then(applyCachePolicy)
@@ -1030,15 +694,26 @@ function makeDurable(environment, { durableStore, instrumentation }) {
1030
694
  ingestStagingStore.records = existingRecords;
1031
695
  }
1032
696
  const snapshotFromMemoryIngest = ingestAndBroadcastFunc();
1033
- if (snapshotFromMemoryIngest === undefined) {
1034
- return undefined;
1035
- }
1036
- if (snapshotFromMemoryIngest.state !== 'Unfulfilled') {
697
+ // now that ingestion is done flush staging store values to L2
698
+ return publishChangesToDurableStore().then(() => {
699
+ if (snapshotFromMemoryIngest === undefined) {
700
+ return undefined;
701
+ }
702
+ if (snapshotFromMemoryIngest.state !== 'Unfulfilled') {
703
+ return snapshotFromMemoryIngest;
704
+ }
705
+ // if snapshot from staging store lookup is unfulfilled then do an L2 lookup
706
+ return reviveSnapshot(environment, durableStore, snapshotFromMemoryIngest, durableStoreErrorHandler, () => environment.storeLookup(snapshotFromMemoryIngest.select, environment.createSnapshot, snapshotFromMemoryIngest.refresh));
707
+ });
708
+ };
709
+ const handleErrorResponse = function (ingestAndBroadcastFunc) {
710
+ validateNotDisposed();
711
+ const snapshotFromMemoryIngest = ingestAndBroadcastFunc();
712
+ return publishChangesToDurableStore().then(() => {
1037
713
  return snapshotFromMemoryIngest;
1038
- }
1039
- // if snapshot from staging store lookup is unfulfilled then do an L2 lookup
1040
- return reviveSnapshot(environment, durableStore, snapshotFromMemoryIngest, durableStoreErrorHandler, () => environment.storeLookup(snapshotFromMemoryIngest.select, environment.createSnapshot, snapshotFromMemoryIngest.refresh));
714
+ });
1041
715
  };
716
+ environment.defaultCachePolicy = buildStaleWhileRevalidateImplementation(Number.MAX_SAFE_INTEGER);
1042
717
  return create(environment, {
1043
718
  publishStoreMetadata: { value: publishStoreMetadata },
1044
719
  storeIngest: { value: storeIngest },
@@ -1048,7 +723,6 @@ function makeDurable(environment, { durableStore, instrumentation }) {
1048
723
  storeEvict: { value: storeEvict },
1049
724
  wrapNormalizedGraphNode: { value: wrapNormalizedGraphNode },
1050
725
  getNode: { value: getNode },
1051
- resolveSnapshot: { value: resolveSnapshot },
1052
726
  rebuildSnapshot: { value: rebuildSnapshot },
1053
727
  withContext: { value: withContext },
1054
728
  storeSetTTLOverride: { value: storeSetTTLOverride },
@@ -1058,11 +732,11 @@ function makeDurable(environment, { durableStore, instrumentation }) {
1058
732
  dispose: { value: dispose },
1059
733
  publishChangesToDurableStore: { value: publishChangesToDurableStore },
1060
734
  getDurableTTLOverrides: { value: getDurableTTLOverrides },
1061
- defaultCachePolicy: { value: defaultCachePolicy },
1062
735
  applyCachePolicy: { value: applyCachePolicy },
1063
736
  getIngestStagingStoreRecords: { value: getIngestStagingStoreRecords },
1064
737
  getIngestStagingStoreMetadata: { value: getIngestStagingStoreMetadata },
1065
738
  handleSuccessResponse: { value: handleSuccessResponse },
739
+ handleErrorResponse: { value: handleErrorResponse },
1066
740
  });
1067
741
  }
1068
742