@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.
- package/dist/es/es2018/environments.js +62 -388
- package/dist/umd/es2018/environments.js +61 -387
- package/dist/umd/es5/environments.js +61 -398
- package/package.json +2 -2
- package/dist/es/es2018/makeDurable/cachepolicies/cache-and-network.d.ts +0 -3
- package/dist/es/es2018/makeDurable/cachepolicies/cache-then-network.d.ts +0 -3
- package/dist/es/es2018/makeDurable/cachepolicies/index.d.ts +0 -6
- package/dist/es/es2018/makeDurable/cachepolicies/no-cache.d.ts +0 -3
- package/dist/es/es2018/makeDurable/cachepolicies/only-if-cached.d.ts +0 -3
- package/dist/es/es2018/makeDurable/cachepolicies/stale-while-revalidate.d.ts +0 -3
- package/dist/es/es2018/makeDurable/cachepolicies/utils.d.ts +0 -9
- package/dist/es/es2018/makeDurable/cachepolicies/valid-at.d.ts +0 -3
- package/dist/umd/es2018/makeDurable/cachepolicies/cache-and-network.d.ts +0 -3
- package/dist/umd/es2018/makeDurable/cachepolicies/cache-then-network.d.ts +0 -3
- package/dist/umd/es2018/makeDurable/cachepolicies/index.d.ts +0 -6
- package/dist/umd/es2018/makeDurable/cachepolicies/no-cache.d.ts +0 -3
- package/dist/umd/es2018/makeDurable/cachepolicies/only-if-cached.d.ts +0 -3
- package/dist/umd/es2018/makeDurable/cachepolicies/stale-while-revalidate.d.ts +0 -3
- package/dist/umd/es2018/makeDurable/cachepolicies/utils.d.ts +0 -9
- package/dist/umd/es2018/makeDurable/cachepolicies/valid-at.d.ts +0 -3
- package/dist/umd/es5/makeDurable/cachepolicies/cache-and-network.d.ts +0 -3
- package/dist/umd/es5/makeDurable/cachepolicies/cache-then-network.d.ts +0 -3
- package/dist/umd/es5/makeDurable/cachepolicies/index.d.ts +0 -6
- package/dist/umd/es5/makeDurable/cachepolicies/no-cache.d.ts +0 -3
- package/dist/umd/es5/makeDurable/cachepolicies/only-if-cached.d.ts +0 -3
- package/dist/umd/es5/makeDurable/cachepolicies/stale-while-revalidate.d.ts +0 -3
- package/dist/umd/es5/makeDurable/cachepolicies/utils.d.ts +0 -9
- package/dist/umd/es5/makeDurable/cachepolicies/valid-at.d.ts +0 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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
|
-
//
|
|
810
|
-
//
|
|
811
|
-
//
|
|
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
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
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
|
|
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
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
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
|
|