@luvio/environments 0.73.1 → 0.73.6

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 (49) hide show
  1. package/dist/es/es2018/DurableTTLStore.d.ts +1 -1
  2. package/dist/es/es2018/environments.js +73 -365
  3. package/dist/es/es2018/makeDurable/error.d.ts +1 -1
  4. package/dist/es/es2018/makeDurable/flush.d.ts +3 -3
  5. package/dist/es/es2018/makeDurable/revive.d.ts +3 -3
  6. package/dist/es/es2018/makeDurable/utils.d.ts +1 -1
  7. package/dist/es/es2018/makeDurable.d.ts +5 -4
  8. package/dist/es/es2018/utils/selectors.d.ts +1 -1
  9. package/dist/umd/es2018/DurableTTLStore.d.ts +1 -1
  10. package/dist/umd/es2018/environments.js +72 -364
  11. package/dist/umd/es2018/makeDurable/error.d.ts +1 -1
  12. package/dist/umd/es2018/makeDurable/flush.d.ts +3 -3
  13. package/dist/umd/es2018/makeDurable/revive.d.ts +3 -3
  14. package/dist/umd/es2018/makeDurable/utils.d.ts +1 -1
  15. package/dist/umd/es2018/makeDurable.d.ts +5 -4
  16. package/dist/umd/es2018/utils/selectors.d.ts +1 -1
  17. package/dist/umd/es5/DurableTTLStore.d.ts +1 -1
  18. package/dist/umd/es5/environments.js +72 -373
  19. package/dist/umd/es5/makeDurable/error.d.ts +1 -1
  20. package/dist/umd/es5/makeDurable/flush.d.ts +3 -3
  21. package/dist/umd/es5/makeDurable/revive.d.ts +3 -3
  22. package/dist/umd/es5/makeDurable/utils.d.ts +1 -1
  23. package/dist/umd/es5/makeDurable.d.ts +5 -4
  24. package/dist/umd/es5/utils/selectors.d.ts +1 -1
  25. package/package.json +12 -4
  26. package/dist/es/es2018/makeDurable/cachepolicies/cache-and-network.d.ts +0 -3
  27. package/dist/es/es2018/makeDurable/cachepolicies/cache-then-network.d.ts +0 -3
  28. package/dist/es/es2018/makeDurable/cachepolicies/index.d.ts +0 -6
  29. package/dist/es/es2018/makeDurable/cachepolicies/no-cache.d.ts +0 -3
  30. package/dist/es/es2018/makeDurable/cachepolicies/only-if-cached.d.ts +0 -3
  31. package/dist/es/es2018/makeDurable/cachepolicies/stale-while-revalidate.d.ts +0 -3
  32. package/dist/es/es2018/makeDurable/cachepolicies/utils.d.ts +0 -9
  33. package/dist/es/es2018/makeDurable/cachepolicies/valid-at.d.ts +0 -3
  34. package/dist/umd/es2018/makeDurable/cachepolicies/cache-and-network.d.ts +0 -3
  35. package/dist/umd/es2018/makeDurable/cachepolicies/cache-then-network.d.ts +0 -3
  36. package/dist/umd/es2018/makeDurable/cachepolicies/index.d.ts +0 -6
  37. package/dist/umd/es2018/makeDurable/cachepolicies/no-cache.d.ts +0 -3
  38. package/dist/umd/es2018/makeDurable/cachepolicies/only-if-cached.d.ts +0 -3
  39. package/dist/umd/es2018/makeDurable/cachepolicies/stale-while-revalidate.d.ts +0 -3
  40. package/dist/umd/es2018/makeDurable/cachepolicies/utils.d.ts +0 -9
  41. package/dist/umd/es2018/makeDurable/cachepolicies/valid-at.d.ts +0 -3
  42. package/dist/umd/es5/makeDurable/cachepolicies/cache-and-network.d.ts +0 -3
  43. package/dist/umd/es5/makeDurable/cachepolicies/cache-then-network.d.ts +0 -3
  44. package/dist/umd/es5/makeDurable/cachepolicies/index.d.ts +0 -6
  45. package/dist/umd/es5/makeDurable/cachepolicies/no-cache.d.ts +0 -3
  46. package/dist/umd/es5/makeDurable/cachepolicies/only-if-cached.d.ts +0 -3
  47. package/dist/umd/es5/makeDurable/cachepolicies/stale-while-revalidate.d.ts +0 -3
  48. package/dist/umd/es5/makeDurable/cachepolicies/utils.d.ts +0 -9
  49. package/dist/umd/es5/makeDurable/cachepolicies/valid-at.d.ts +0 -3
@@ -1,4 +1,4 @@
1
- import { DurableStore } from './DurableStore';
1
+ import type { DurableStore } from './DurableStore';
2
2
  export declare const TTL_DURABLE_SEGMENT = "TTL_DURABLE_SEGMENT";
3
3
  export interface DefaultDurableTTLOverride extends DurableTTLOverride {
4
4
  namespace: 'TTL_DEFAULT_KEY';
@@ -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();
@@ -915,73 +654,20 @@ function makeDurable(environment, { durableStore, instrumentation }) {
915
654
  validateNotDisposed();
916
655
  return durableTTLStore.getDurableTTLOverrides();
917
656
  };
918
- // reviveSnapshot wrapper to let cache policies revive data from L2 and
919
- // access the revived data via their own storeLookups
920
- const reviveSnapshotWithCachePolicy = (unavailableSnapshot, storeLookup) => reviveSnapshot(environment, durableStore, unavailableSnapshot, durableStoreErrorHandler, () => storeLookup(unavailableSnapshot.select, unavailableSnapshot.refresh));
921
- const defaultCachePolicy = buildStaleWhileRevalidateImplementation({
922
- validateNotDisposed,
923
- reviveSnapshotWithCachePolicy,
924
- }, Number.MAX_SAFE_INTEGER);
925
- function resolveCachePolicy(cachePolicy) {
926
- if (cachePolicy === undefined) {
927
- return defaultCachePolicy;
928
- }
929
- switch (cachePolicy.type) {
930
- case 'stale-while-revalidate':
931
- return buildStaleWhileRevalidateImplementation({
932
- validateNotDisposed,
933
- reviveSnapshotWithCachePolicy,
934
- }, cachePolicy.staleDurationSeconds);
935
- case 'cache-and-network':
936
- return buildCacheAndNetworkImplementation({
937
- validateNotDisposed,
938
- reviveSnapshotWithCachePolicy,
939
- }, cachePolicy.staleDurationSeconds);
940
- case 'cache-then-network':
941
- return buildCacheThenNetworkImplementation({
942
- validateNotDisposed,
943
- reviveSnapshotWithCachePolicy,
944
- });
945
- case 'no-cache':
946
- return buildNoCacheImplementation({
947
- validateNotDisposed,
948
- reviveSnapshotWithCachePolicy,
949
- });
950
- case 'only-if-cached':
951
- return buildOnlyIfCachedImplementation({
952
- validateNotDisposed,
953
- reviveSnapshotWithCachePolicy,
954
- });
955
- case 'valid-at': {
956
- const basePolicy = resolveCachePolicy(cachePolicy.basePolicy);
957
- return buildValidAtImplementation({
958
- validateNotDisposed,
959
- reviveSnapshotWithCachePolicy,
960
- }, basePolicy, cachePolicy.timestamp);
961
- }
962
- default: {
963
- if (process.env.NODE_ENV !== 'production') {
964
- throw new Error(`unrecognized cache policy: ${JSON.stringify(cachePolicy)}`);
965
- }
966
- return defaultCachePolicy;
967
- }
968
- }
969
- }
970
657
  const applyCachePolicy = function (adapterRequestContext, buildSnapshotContext, buildCachedSnapshot, buildNetworkSnapshot) {
971
658
  validateNotDisposed();
972
- const { cachePolicy } = adapterRequestContext;
973
- const cachePolicyImpl = resolveCachePolicy(cachePolicy);
974
- const resolvePendingSnapshot = (snapshot) => environment.resolvePendingSnapshot(snapshot);
975
- 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
+ };
976
669
  const applyCachePolicy = () => {
977
- return cachePolicyImpl({
978
- buildCachedSnapshot,
979
- buildNetworkSnapshot,
980
- buildSnapshotContext,
981
- resolvePendingSnapshot,
982
- storeLookup,
983
- coercedAdapterRequestContext: coerceAdapterRequestContext(adapterRequestContext),
984
- });
670
+ return environment.applyCachePolicy(adapterRequestContext, buildSnapshotContext, wrappedCacheLookup, buildNetworkSnapshot);
985
671
  };
986
672
  return isRevivingTTLOverrides !== undefined
987
673
  ? isRevivingTTLOverrides.then(applyCachePolicy)
@@ -1008,15 +694,36 @@ function makeDurable(environment, { durableStore, instrumentation }) {
1008
694
  ingestStagingStore.records = existingRecords;
1009
695
  }
1010
696
  const snapshotFromMemoryIngest = ingestAndBroadcastFunc();
1011
- if (snapshotFromMemoryIngest === undefined) {
1012
- return undefined;
1013
- }
1014
- 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(() => {
1015
713
  return snapshotFromMemoryIngest;
1016
- }
1017
- // if snapshot from staging store lookup is unfulfilled then do an L2 lookup
1018
- return reviveSnapshot(environment, durableStore, snapshotFromMemoryIngest, durableStoreErrorHandler, () => environment.storeLookup(snapshotFromMemoryIngest.select, environment.createSnapshot, snapshotFromMemoryIngest.refresh));
714
+ });
715
+ };
716
+ const getNotifyChangeStoreEntries = function (keys) {
717
+ validateNotDisposed();
718
+ return durableStore.getEntries(keys, DefaultDurableSegment).then((durableRecords) => {
719
+ const entries = {};
720
+ publishDurableStoreEntries(durableRecords, (key, record) => {
721
+ entries[key] = record;
722
+ }, () => { });
723
+ return entries;
724
+ });
1019
725
  };
726
+ environment.defaultCachePolicy = buildStaleWhileRevalidateImplementation(Number.MAX_SAFE_INTEGER);
1020
727
  return create(environment, {
1021
728
  publishStoreMetadata: { value: publishStoreMetadata },
1022
729
  storeIngest: { value: storeIngest },
@@ -1035,11 +742,12 @@ function makeDurable(environment, { durableStore, instrumentation }) {
1035
742
  dispose: { value: dispose },
1036
743
  publishChangesToDurableStore: { value: publishChangesToDurableStore },
1037
744
  getDurableTTLOverrides: { value: getDurableTTLOverrides },
1038
- defaultCachePolicy: { value: defaultCachePolicy },
1039
745
  applyCachePolicy: { value: applyCachePolicy },
1040
746
  getIngestStagingStoreRecords: { value: getIngestStagingStoreRecords },
1041
747
  getIngestStagingStoreMetadata: { value: getIngestStagingStoreMetadata },
1042
748
  handleSuccessResponse: { value: handleSuccessResponse },
749
+ handleErrorResponse: { value: handleErrorResponse },
750
+ getNotifyChangeStoreEntries: { value: getNotifyChangeStoreEntries },
1043
751
  });
1044
752
  }
1045
753
 
@@ -1,4 +1,4 @@
1
- import { Luvio } from '@luvio/engine';
1
+ import type { Luvio } from '@luvio/engine';
2
2
  export declare const DURABLE_STORE_ERROR = "durable-store-error";
3
3
  export declare type InstrumentationFunction = Luvio['instrument'];
4
4
  export declare type DurableStoreRejectionHandler = (e: any) => void;
@@ -1,4 +1,4 @@
1
- import { Store } from '@luvio/engine';
2
- import { DurableStore } from '../DurableStore';
3
- import { DurableStoreRejectionHandler } from './error';
1
+ import type { Store } from '@luvio/engine';
2
+ import type { DurableStore } from '../DurableStore';
3
+ import type { DurableStoreRejectionHandler } from './error';
4
4
  export declare function flushStoreValuesToDurableStore(store: Store, durableStore: DurableStore, durableStoreErrorHandler: DurableStoreRejectionHandler): Promise<void>;
@@ -1,6 +1,6 @@
1
- import { Environment, Snapshot, UnAvailableSnapshot, StoreMetadata } from '@luvio/engine';
2
- import { DurableStore, DurableStoreEntries } from '../DurableStore';
3
- import { DurableStoreRejectionHandler } from './error';
1
+ import type { Environment, Snapshot, UnAvailableSnapshot, StoreMetadata } from '@luvio/engine';
2
+ import type { DurableStore, DurableStoreEntries } from '../DurableStore';
3
+ import type { DurableStoreRejectionHandler } from './error';
4
4
  declare type ObjectAsSet = {
5
5
  [key: string]: true;
6
6
  };
@@ -1,2 +1,2 @@
1
- import { StoreRecordError } from '@luvio/engine';
1
+ import type { StoreRecordError } from '@luvio/engine';
2
2
  export declare function isStoreEntryError(storeRecord: unknown): storeRecord is StoreRecordError;
@@ -1,7 +1,8 @@
1
- import { CacheKeySet, Environment, RecordSource, Snapshot, Store } from '@luvio/engine';
2
- import { DurableStore } from './DurableStore';
3
- import { InstrumentationFunction } from './makeDurable/error';
4
- import { TTLOverridesMap } from './DurableTTLStore';
1
+ import type { CacheKeySet, Environment, RecordSource, Snapshot } from '@luvio/engine';
2
+ import { Store } from '@luvio/engine';
3
+ import type { DurableStore } from './DurableStore';
4
+ import type { InstrumentationFunction } from './makeDurable/error';
5
+ import type { TTLOverridesMap } from './DurableTTLStore';
5
6
  export interface DurableEnvironment extends Environment {
6
7
  /**
7
8
  * Disposes the environment and detaches the durable store listener
@@ -1,2 +1,2 @@
1
- import { Selector } from '@luvio/engine';
1
+ import type { Selector } from '@luvio/engine';
2
2
  export declare function readPaginationKeysFromSelector(select?: Selector<unknown>): string[];
@@ -1,4 +1,4 @@
1
- import { DurableStore } from './DurableStore';
1
+ import type { DurableStore } from './DurableStore';
2
2
  export declare const TTL_DURABLE_SEGMENT = "TTL_DURABLE_SEGMENT";
3
3
  export interface DefaultDurableTTLOverride extends DurableTTLOverride {
4
4
  namespace: 'TTL_DEFAULT_KEY';