@luvio/environments 0.70.0 → 0.71.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/dist/es/es2018/environments.js +165 -145
- package/dist/es/es2018/makeDurable/cachepolicies/utils.d.ts +3 -2
- package/dist/umd/es2018/environments.js +165 -145
- package/dist/umd/es2018/makeDurable/cachepolicies/utils.d.ts +3 -2
- package/dist/umd/es5/environments.js +165 -144
- package/dist/umd/es5/makeDurable/cachepolicies/utils.d.ts +3 -2
- package/package.json +2 -2
|
@@ -18,7 +18,11 @@ const { keys, create, assign, freeze } = Object;
|
|
|
18
18
|
const { isArray } = Array;
|
|
19
19
|
|
|
20
20
|
function appendTTLStrategy(storeLookup, ttlStrategy) {
|
|
21
|
-
|
|
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;
|
|
22
26
|
}
|
|
23
27
|
function buildNetworkSnapshot(args) {
|
|
24
28
|
const { buildNetworkSnapshot, buildSnapshotContext, coercedAdapterRequestContext } = args;
|
|
@@ -41,102 +45,112 @@ function buildTTLStrategy(staleDurationMilliseconds = 0) {
|
|
|
41
45
|
}
|
|
42
46
|
return StoreResolveResultState.Found;
|
|
43
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;
|
|
44
63
|
}
|
|
45
64
|
|
|
46
|
-
function buildCacheAndNetworkImplementation(funcs, staleDurationSeconds) {
|
|
65
|
+
function buildCacheAndNetworkImplementation(funcs, staleDurationSeconds = 0) {
|
|
47
66
|
return function (args) {
|
|
48
67
|
funcs.validateNotDisposed();
|
|
49
|
-
const {
|
|
50
|
-
const staleDurationMilliseconds = staleDurationSeconds
|
|
68
|
+
const { buildCachedSnapshot, buildNetworkSnapshot: buildNetworkSnapshot$1, buildSnapshotContext, storeLookup, coercedAdapterRequestContext, } = args;
|
|
69
|
+
const staleDurationMilliseconds = staleDurationSeconds * 1000;
|
|
51
70
|
const cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy(staleDurationMilliseconds));
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return args
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (revivedSnapshot.state === 'Stale') {
|
|
94
|
-
// kick off network request, do not await it
|
|
95
|
-
buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
|
|
96
|
-
// return the L2 cached snapshot to caller
|
|
97
|
-
return revivedSnapshot;
|
|
98
|
-
}
|
|
99
|
-
// data not found in L2 cache, go to the network
|
|
100
|
-
return buildNetworkSnapshot(args);
|
|
101
|
-
});
|
|
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
|
+
}
|
|
102
112
|
}
|
|
103
|
-
|
|
104
|
-
|
|
113
|
+
return buildNetworkSnapshot(args);
|
|
114
|
+
});
|
|
105
115
|
};
|
|
106
116
|
}
|
|
107
117
|
|
|
108
118
|
function buildCacheThenNetworkImplementation(funcs) {
|
|
109
119
|
return function (args) {
|
|
110
120
|
funcs.validateNotDisposed();
|
|
111
|
-
const {
|
|
121
|
+
const { buildCachedSnapshot, buildSnapshotContext, storeLookup } = args;
|
|
112
122
|
const cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy());
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (snapshot.state === 'Pending') {
|
|
120
|
-
return args.resolvePendingSnapshot(snapshot);
|
|
121
|
-
}
|
|
122
|
-
// data not found in L1 cache, try L2 cache
|
|
123
|
-
return funcs
|
|
124
|
-
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
125
|
-
.then((revivedSnapshot) => {
|
|
126
|
-
// data found in L2 cache
|
|
127
|
-
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
128
|
-
revivedSnapshot.state === 'Error') {
|
|
129
|
-
return revivedSnapshot;
|
|
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;
|
|
130
129
|
}
|
|
131
|
-
if (
|
|
132
|
-
return args.resolvePendingSnapshot(
|
|
130
|
+
if (snapshot.state === 'Pending') {
|
|
131
|
+
return args.resolvePendingSnapshot(snapshot);
|
|
133
132
|
}
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
+
});
|
|
140
154
|
};
|
|
141
155
|
}
|
|
142
156
|
|
|
@@ -180,84 +194,90 @@ function buildNotCachedErrorSnapshot() {
|
|
|
180
194
|
error,
|
|
181
195
|
state: 'Error',
|
|
182
196
|
data: undefined,
|
|
183
|
-
// TODO[@W-10164067]: copy refresh data from the snapshot returned by
|
|
197
|
+
// TODO[@W-10164067]: copy refresh data from the snapshot returned by buildCachedSnapshot (if any)
|
|
184
198
|
// refresh: ...
|
|
185
199
|
};
|
|
186
200
|
}
|
|
187
201
|
function buildOnlyIfCachedImplementation(funcs) {
|
|
188
202
|
return function (args) {
|
|
189
203
|
funcs.validateNotDisposed();
|
|
190
|
-
const {
|
|
204
|
+
const { buildCachedSnapshot, buildSnapshotContext, storeLookup } = args;
|
|
191
205
|
const cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy());
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
// network request outstanding, data is not cached
|
|
199
|
-
if (snapshot.state === 'Pending') {
|
|
200
|
-
return buildNotCachedErrorSnapshot();
|
|
201
|
-
}
|
|
202
|
-
// data not found in L1 cache, try L2 cache
|
|
203
|
-
return funcs
|
|
204
|
-
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
205
|
-
.then((revivedSnapshot) => {
|
|
206
|
-
// data found in L2 cache
|
|
207
|
-
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
208
|
-
revivedSnapshot.state === 'Error') {
|
|
209
|
-
return revivedSnapshot;
|
|
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;
|
|
210
212
|
}
|
|
211
|
-
// data is not cached
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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
|
+
});
|
|
216
234
|
};
|
|
217
235
|
}
|
|
218
236
|
|
|
219
237
|
function buildStaleWhileRevalidateImplementation(funcs, staleDurationSeconds) {
|
|
220
238
|
return function (args) {
|
|
221
239
|
funcs.validateNotDisposed();
|
|
222
|
-
const {
|
|
240
|
+
const { buildCachedSnapshot, buildSnapshotContext, storeLookup } = args;
|
|
223
241
|
const cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy(staleDurationSeconds * 1000));
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if (snapshot.state === 'Pending') {
|
|
231
|
-
return args.resolvePendingSnapshot(snapshot);
|
|
232
|
-
}
|
|
233
|
-
// stale data found in L1 cache
|
|
234
|
-
if (snapshot.state === 'Stale') {
|
|
235
|
-
buildNetworkSnapshot(args);
|
|
236
|
-
return snapshot;
|
|
237
|
-
}
|
|
238
|
-
// data not found in L1 cache, try L2 cache
|
|
239
|
-
return funcs
|
|
240
|
-
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
241
|
-
.then((revivedSnapshot) => {
|
|
242
|
-
// data found in L2 cache
|
|
243
|
-
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
244
|
-
revivedSnapshot.state === 'Error') {
|
|
245
|
-
return revivedSnapshot;
|
|
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;
|
|
246
248
|
}
|
|
247
|
-
if (
|
|
248
|
-
return args.resolvePendingSnapshot(
|
|
249
|
+
if (snapshot.state === 'Pending') {
|
|
250
|
+
return args.resolvePendingSnapshot(snapshot);
|
|
249
251
|
}
|
|
250
|
-
// stale data found in
|
|
251
|
-
if (
|
|
252
|
+
// stale data found in L1 cache
|
|
253
|
+
if (snapshot.state === 'Stale') {
|
|
252
254
|
buildNetworkSnapshot(args);
|
|
253
|
-
return
|
|
255
|
+
return snapshot;
|
|
254
256
|
}
|
|
255
|
-
// data not found in
|
|
256
|
-
return
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
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
|
+
});
|
|
261
281
|
};
|
|
262
282
|
}
|
|
263
283
|
|
|
@@ -268,7 +288,7 @@ function buildValidAtImplementation(funcs, basePolicyImplementation, timestamp)
|
|
|
268
288
|
// TTLStrategy to use the the valid-at cache policy's timestamp. The flow goes:
|
|
269
289
|
//
|
|
270
290
|
// Environment.applyCachePolicy => validAtImplementation (this function) =>
|
|
271
|
-
// basePolicyImplementation => adapter's
|
|
291
|
+
// basePolicyImplementation => adapter's buildCachedSnapshot =>
|
|
272
292
|
// basePolicyImplementation's storeLookup => validAtStoreLookup (below) =>
|
|
273
293
|
// Environment.applyCachePolicy's storeLookup => Store/Reader code =>
|
|
274
294
|
// valid-at TTLStrategy (below) =>
|
|
@@ -808,7 +828,7 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
808
828
|
if (ingestStagingStore !== null) {
|
|
809
829
|
return ingestStagingStore.lookup(sel, createSnapshot, refresh, ttlStrategy);
|
|
810
830
|
}
|
|
811
|
-
// otherwise this is from
|
|
831
|
+
// otherwise this is from buildCachedSnapshot and we should use the luvio
|
|
812
832
|
// L1 store
|
|
813
833
|
return environment.storeLookup(sel, createSnapshot, refresh, ttlStrategy);
|
|
814
834
|
};
|
|
@@ -969,7 +989,7 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
969
989
|
}
|
|
970
990
|
}
|
|
971
991
|
}
|
|
972
|
-
const applyCachePolicy = function (adapterRequestContext, buildSnapshotContext,
|
|
992
|
+
const applyCachePolicy = function (adapterRequestContext, buildSnapshotContext, buildCachedSnapshot, buildNetworkSnapshot) {
|
|
973
993
|
validateNotDisposed();
|
|
974
994
|
const { cachePolicy } = adapterRequestContext;
|
|
975
995
|
const cachePolicyImpl = resolveCachePolicy(cachePolicy);
|
|
@@ -977,7 +997,7 @@ function makeDurable(environment, { durableStore, instrumentation }) {
|
|
|
977
997
|
const storeLookup = (sel, refresh, ttlStrategy) => environment.storeLookup(sel, environment.createSnapshot, refresh, ttlStrategy);
|
|
978
998
|
const applyCachePolicy = () => {
|
|
979
999
|
return cachePolicyImpl({
|
|
980
|
-
|
|
1000
|
+
buildCachedSnapshot,
|
|
981
1001
|
buildNetworkSnapshot,
|
|
982
1002
|
buildSnapshotContext,
|
|
983
1003
|
resolvePendingSnapshot,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BuildCachedSnapshot, CachePolicyImplementationArgs, Snapshot, StoreLookup, TTLStrategy, UnAvailableSnapshot } from '@luvio/engine';
|
|
2
2
|
export declare type DurableCachePolicyFunctions = {
|
|
3
3
|
validateNotDisposed: () => void;
|
|
4
4
|
reviveSnapshotWithCachePolicy: <D, V>(unavailableSnapshot: UnAvailableSnapshot<D, V>, storeLookup: StoreLookup<D, V>) => Promise<Snapshot<D, V>>;
|
|
5
5
|
};
|
|
6
|
-
export declare function appendTTLStrategy<C, D>(storeLookup: CachePolicyImplementationArgs<C, D>['storeLookup'], ttlStrategy: TTLStrategy): Parameters<
|
|
6
|
+
export declare function appendTTLStrategy<C, D>(storeLookup: CachePolicyImplementationArgs<C, D>['storeLookup'], ttlStrategy: TTLStrategy): Parameters<BuildCachedSnapshot<C, D>>[1];
|
|
7
7
|
export declare function buildNetworkSnapshot<C, D>(args: CachePolicyImplementationArgs<C, D>): Promise<Snapshot<D, unknown>>;
|
|
8
8
|
export declare function buildTTLStrategy(staleDurationMilliseconds?: number): TTLStrategy;
|
|
9
|
+
export declare function buildAvailableSnapshotFromCachedSnapshotResponse<C, D>(cachedSnapshot: ReturnType<BuildCachedSnapshot<C, D>>, availableSnapshotFunc: (snapshot: Snapshot<D> | undefined) => Snapshot<D> | Promise<Snapshot<D>>): Snapshot<D> | Promise<Snapshot<D>>;
|
|
@@ -22,7 +22,11 @@
|
|
|
22
22
|
const { isArray } = Array;
|
|
23
23
|
|
|
24
24
|
function appendTTLStrategy(storeLookup, ttlStrategy) {
|
|
25
|
-
|
|
25
|
+
const returnStoreLookup = (sel, refresh) => storeLookup(sel, refresh, ttlStrategy);
|
|
26
|
+
// append ttlStrategy to storeLookup function (in cases where custom adapter
|
|
27
|
+
// wants to perform it's own lookup)
|
|
28
|
+
returnStoreLookup.ttlStrategy = ttlStrategy;
|
|
29
|
+
return returnStoreLookup;
|
|
26
30
|
}
|
|
27
31
|
function buildNetworkSnapshot(args) {
|
|
28
32
|
const { buildNetworkSnapshot, buildSnapshotContext, coercedAdapterRequestContext } = args;
|
|
@@ -45,102 +49,112 @@
|
|
|
45
49
|
}
|
|
46
50
|
return engine.StoreResolveResultState.Found;
|
|
47
51
|
};
|
|
52
|
+
}
|
|
53
|
+
// TODO - update userland-facing APIs to return `AvailableSnapshot` instead of `Snapshot`
|
|
54
|
+
// and then the signatures here can be updated as well
|
|
55
|
+
function buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, availableSnapshotFunc) {
|
|
56
|
+
if (isPromise(cachedSnapshot)) {
|
|
57
|
+
return cachedSnapshot.then(availableSnapshotFunc);
|
|
58
|
+
}
|
|
59
|
+
return availableSnapshotFunc(cachedSnapshot);
|
|
60
|
+
}
|
|
61
|
+
function isPromise(value) {
|
|
62
|
+
if (value === undefined) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
// check for Thenable due to test frameworks using custom Promise impls
|
|
66
|
+
return value.then !== undefined;
|
|
48
67
|
}
|
|
49
68
|
|
|
50
|
-
function buildCacheAndNetworkImplementation(funcs, staleDurationSeconds) {
|
|
69
|
+
function buildCacheAndNetworkImplementation(funcs, staleDurationSeconds = 0) {
|
|
51
70
|
return function (args) {
|
|
52
71
|
funcs.validateNotDisposed();
|
|
53
|
-
const {
|
|
54
|
-
const staleDurationMilliseconds = staleDurationSeconds
|
|
72
|
+
const { buildCachedSnapshot, buildNetworkSnapshot: buildNetworkSnapshot$1, buildSnapshotContext, storeLookup, coercedAdapterRequestContext, } = args;
|
|
73
|
+
const staleDurationMilliseconds = staleDurationSeconds * 1000;
|
|
55
74
|
const cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy(staleDurationMilliseconds));
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return args
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (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
|
-
// data not found in L2 cache, go to the network
|
|
104
|
-
return buildNetworkSnapshot(args);
|
|
105
|
-
});
|
|
75
|
+
const cachedSnapshot = buildCachedSnapshot(buildSnapshotContext, cachePolicyStoreLookup);
|
|
76
|
+
return buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, (snapshot) => {
|
|
77
|
+
if (snapshot !== undefined) {
|
|
78
|
+
// data found in L1 cache
|
|
79
|
+
if (snapshot.state === 'Fulfilled' ||
|
|
80
|
+
snapshot.state === 'Error' ||
|
|
81
|
+
snapshot.state === 'Stale') {
|
|
82
|
+
// kick off network request, do not await it
|
|
83
|
+
buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
|
|
84
|
+
// return the cached snapshot to caller
|
|
85
|
+
return snapshot;
|
|
86
|
+
}
|
|
87
|
+
// network request outstanding
|
|
88
|
+
if (snapshot.state === 'Pending') {
|
|
89
|
+
// kick off another network request, do not await it
|
|
90
|
+
buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
|
|
91
|
+
return args.resolvePendingSnapshot(snapshot);
|
|
92
|
+
}
|
|
93
|
+
// if unfulfilled we have enough info to do an L2 lookup
|
|
94
|
+
if (snapshot.state === 'Unfulfilled') {
|
|
95
|
+
return funcs
|
|
96
|
+
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
97
|
+
.then((revivedSnapshot) => {
|
|
98
|
+
// data found in L2 cache
|
|
99
|
+
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
100
|
+
revivedSnapshot.state === 'Error' ||
|
|
101
|
+
revivedSnapshot.state === 'Stale') {
|
|
102
|
+
// kick off network request, do not await it
|
|
103
|
+
buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
|
|
104
|
+
// return the L2 cached snapshot to caller
|
|
105
|
+
return revivedSnapshot;
|
|
106
|
+
}
|
|
107
|
+
if (revivedSnapshot.state === 'Pending') {
|
|
108
|
+
// kick off network request, do not await it
|
|
109
|
+
buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
|
|
110
|
+
return args.resolvePendingSnapshot(revivedSnapshot);
|
|
111
|
+
}
|
|
112
|
+
// data not found in L2 cache, go to the network
|
|
113
|
+
return buildNetworkSnapshot(args);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
106
116
|
}
|
|
107
|
-
|
|
108
|
-
|
|
117
|
+
return buildNetworkSnapshot(args);
|
|
118
|
+
});
|
|
109
119
|
};
|
|
110
120
|
}
|
|
111
121
|
|
|
112
122
|
function buildCacheThenNetworkImplementation(funcs) {
|
|
113
123
|
return function (args) {
|
|
114
124
|
funcs.validateNotDisposed();
|
|
115
|
-
const {
|
|
125
|
+
const { buildCachedSnapshot, buildSnapshotContext, storeLookup } = args;
|
|
116
126
|
const cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy());
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (snapshot.state === 'Pending') {
|
|
124
|
-
return args.resolvePendingSnapshot(snapshot);
|
|
125
|
-
}
|
|
126
|
-
// data not found in L1 cache, try L2 cache
|
|
127
|
-
return funcs
|
|
128
|
-
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
129
|
-
.then((revivedSnapshot) => {
|
|
130
|
-
// data found in L2 cache
|
|
131
|
-
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
132
|
-
revivedSnapshot.state === 'Error') {
|
|
133
|
-
return revivedSnapshot;
|
|
127
|
+
const cachedSnapshot = buildCachedSnapshot(buildSnapshotContext, cachePolicyStoreLookup);
|
|
128
|
+
return buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, (snapshot) => {
|
|
129
|
+
if (snapshot !== undefined) {
|
|
130
|
+
// data found in L1 cache
|
|
131
|
+
if (snapshot.state === 'Fulfilled' || snapshot.state === 'Error') {
|
|
132
|
+
return snapshot;
|
|
134
133
|
}
|
|
135
|
-
if (
|
|
136
|
-
return args.resolvePendingSnapshot(
|
|
134
|
+
if (snapshot.state === 'Pending') {
|
|
135
|
+
return args.resolvePendingSnapshot(snapshot);
|
|
137
136
|
}
|
|
138
|
-
//
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
137
|
+
// if unfulfilled we have enough info to do an L2 lookup
|
|
138
|
+
if (snapshot.state === 'Unfulfilled') {
|
|
139
|
+
return funcs
|
|
140
|
+
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
141
|
+
.then((revivedSnapshot) => {
|
|
142
|
+
// data found in L2 cache
|
|
143
|
+
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
144
|
+
revivedSnapshot.state === 'Error') {
|
|
145
|
+
return revivedSnapshot;
|
|
146
|
+
}
|
|
147
|
+
if (revivedSnapshot.state === 'Pending') {
|
|
148
|
+
return args.resolvePendingSnapshot(revivedSnapshot);
|
|
149
|
+
}
|
|
150
|
+
// data not found in L2 cache, go to the network
|
|
151
|
+
return buildNetworkSnapshot(args);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// L1 lookup could not find enough information to even construct a snapshot, go to the network
|
|
156
|
+
return buildNetworkSnapshot(args);
|
|
157
|
+
});
|
|
144
158
|
};
|
|
145
159
|
}
|
|
146
160
|
|
|
@@ -184,84 +198,90 @@
|
|
|
184
198
|
error,
|
|
185
199
|
state: 'Error',
|
|
186
200
|
data: undefined,
|
|
187
|
-
// TODO[@W-10164067]: copy refresh data from the snapshot returned by
|
|
201
|
+
// TODO[@W-10164067]: copy refresh data from the snapshot returned by buildCachedSnapshot (if any)
|
|
188
202
|
// refresh: ...
|
|
189
203
|
};
|
|
190
204
|
}
|
|
191
205
|
function buildOnlyIfCachedImplementation(funcs) {
|
|
192
206
|
return function (args) {
|
|
193
207
|
funcs.validateNotDisposed();
|
|
194
|
-
const {
|
|
208
|
+
const { buildCachedSnapshot, buildSnapshotContext, storeLookup } = args;
|
|
195
209
|
const cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy());
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
// network request outstanding, data is not cached
|
|
203
|
-
if (snapshot.state === 'Pending') {
|
|
204
|
-
return buildNotCachedErrorSnapshot();
|
|
205
|
-
}
|
|
206
|
-
// data not found in L1 cache, try L2 cache
|
|
207
|
-
return funcs
|
|
208
|
-
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
209
|
-
.then((revivedSnapshot) => {
|
|
210
|
-
// data found in L2 cache
|
|
211
|
-
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
212
|
-
revivedSnapshot.state === 'Error') {
|
|
213
|
-
return revivedSnapshot;
|
|
210
|
+
const cachedSnapshot = buildCachedSnapshot(buildSnapshotContext, cachePolicyStoreLookup);
|
|
211
|
+
return buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, (snapshot) => {
|
|
212
|
+
if (snapshot !== undefined) {
|
|
213
|
+
// data found in L1 cache
|
|
214
|
+
if (snapshot.state === 'Fulfilled' || snapshot.state === 'Error') {
|
|
215
|
+
return snapshot;
|
|
214
216
|
}
|
|
215
|
-
// data is not cached
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
// network request outstanding, data is not cached
|
|
218
|
+
if (snapshot.state === 'Pending') {
|
|
219
|
+
return buildNotCachedErrorSnapshot();
|
|
220
|
+
}
|
|
221
|
+
// if unfulfilled we have enough info to do an L2 lookup
|
|
222
|
+
if (snapshot.state === 'Unfulfilled') {
|
|
223
|
+
return funcs
|
|
224
|
+
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
225
|
+
.then((revivedSnapshot) => {
|
|
226
|
+
// data found in L2 cache
|
|
227
|
+
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
228
|
+
revivedSnapshot.state === 'Error') {
|
|
229
|
+
return revivedSnapshot;
|
|
230
|
+
}
|
|
231
|
+
// data is not cached
|
|
232
|
+
return buildNotCachedErrorSnapshot();
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return buildNotCachedErrorSnapshot();
|
|
237
|
+
});
|
|
220
238
|
};
|
|
221
239
|
}
|
|
222
240
|
|
|
223
241
|
function buildStaleWhileRevalidateImplementation(funcs, staleDurationSeconds) {
|
|
224
242
|
return function (args) {
|
|
225
243
|
funcs.validateNotDisposed();
|
|
226
|
-
const {
|
|
244
|
+
const { buildCachedSnapshot, buildSnapshotContext, storeLookup } = args;
|
|
227
245
|
const cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy(staleDurationSeconds * 1000));
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
if (snapshot.state === 'Pending') {
|
|
235
|
-
return args.resolvePendingSnapshot(snapshot);
|
|
236
|
-
}
|
|
237
|
-
// stale data found in L1 cache
|
|
238
|
-
if (snapshot.state === 'Stale') {
|
|
239
|
-
buildNetworkSnapshot(args);
|
|
240
|
-
return snapshot;
|
|
241
|
-
}
|
|
242
|
-
// data not found in L1 cache, try L2 cache
|
|
243
|
-
return funcs
|
|
244
|
-
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
245
|
-
.then((revivedSnapshot) => {
|
|
246
|
-
// data found in L2 cache
|
|
247
|
-
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
248
|
-
revivedSnapshot.state === 'Error') {
|
|
249
|
-
return revivedSnapshot;
|
|
246
|
+
const cachedSnapshot = buildCachedSnapshot(buildSnapshotContext, cachePolicyStoreLookup);
|
|
247
|
+
return buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, (snapshot) => {
|
|
248
|
+
if (snapshot !== undefined) {
|
|
249
|
+
// data found in L1 cache
|
|
250
|
+
if (snapshot.state === 'Fulfilled' || snapshot.state === 'Error') {
|
|
251
|
+
return snapshot;
|
|
250
252
|
}
|
|
251
|
-
if (
|
|
252
|
-
return args.resolvePendingSnapshot(
|
|
253
|
+
if (snapshot.state === 'Pending') {
|
|
254
|
+
return args.resolvePendingSnapshot(snapshot);
|
|
253
255
|
}
|
|
254
|
-
// stale data found in
|
|
255
|
-
if (
|
|
256
|
+
// stale data found in L1 cache
|
|
257
|
+
if (snapshot.state === 'Stale') {
|
|
256
258
|
buildNetworkSnapshot(args);
|
|
257
|
-
return
|
|
259
|
+
return snapshot;
|
|
258
260
|
}
|
|
259
|
-
// data not found in
|
|
260
|
-
return
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
261
|
+
// data not found in L1 cache, try L2 cache
|
|
262
|
+
return funcs
|
|
263
|
+
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
264
|
+
.then((revivedSnapshot) => {
|
|
265
|
+
// data found in L2 cache
|
|
266
|
+
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
267
|
+
revivedSnapshot.state === 'Error') {
|
|
268
|
+
return revivedSnapshot;
|
|
269
|
+
}
|
|
270
|
+
if (revivedSnapshot.state === 'Pending') {
|
|
271
|
+
return args.resolvePendingSnapshot(revivedSnapshot);
|
|
272
|
+
}
|
|
273
|
+
// stale data found in L2 cache
|
|
274
|
+
if (revivedSnapshot.state === 'Stale') {
|
|
275
|
+
buildNetworkSnapshot(args);
|
|
276
|
+
return revivedSnapshot;
|
|
277
|
+
}
|
|
278
|
+
// data not found in L2 cache, go to the network
|
|
279
|
+
return buildNetworkSnapshot(args);
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
// L1 lookup could not find enough information to even construct a snapshot, go to the network
|
|
283
|
+
return buildNetworkSnapshot(args);
|
|
284
|
+
});
|
|
265
285
|
};
|
|
266
286
|
}
|
|
267
287
|
|
|
@@ -272,7 +292,7 @@
|
|
|
272
292
|
// TTLStrategy to use the the valid-at cache policy's timestamp. The flow goes:
|
|
273
293
|
//
|
|
274
294
|
// Environment.applyCachePolicy => validAtImplementation (this function) =>
|
|
275
|
-
// basePolicyImplementation => adapter's
|
|
295
|
+
// basePolicyImplementation => adapter's buildCachedSnapshot =>
|
|
276
296
|
// basePolicyImplementation's storeLookup => validAtStoreLookup (below) =>
|
|
277
297
|
// Environment.applyCachePolicy's storeLookup => Store/Reader code =>
|
|
278
298
|
// valid-at TTLStrategy (below) =>
|
|
@@ -812,7 +832,7 @@
|
|
|
812
832
|
if (ingestStagingStore !== null) {
|
|
813
833
|
return ingestStagingStore.lookup(sel, createSnapshot, refresh, ttlStrategy);
|
|
814
834
|
}
|
|
815
|
-
// otherwise this is from
|
|
835
|
+
// otherwise this is from buildCachedSnapshot and we should use the luvio
|
|
816
836
|
// L1 store
|
|
817
837
|
return environment.storeLookup(sel, createSnapshot, refresh, ttlStrategy);
|
|
818
838
|
};
|
|
@@ -973,7 +993,7 @@
|
|
|
973
993
|
}
|
|
974
994
|
}
|
|
975
995
|
}
|
|
976
|
-
const applyCachePolicy = function (adapterRequestContext, buildSnapshotContext,
|
|
996
|
+
const applyCachePolicy = function (adapterRequestContext, buildSnapshotContext, buildCachedSnapshot, buildNetworkSnapshot) {
|
|
977
997
|
validateNotDisposed();
|
|
978
998
|
const { cachePolicy } = adapterRequestContext;
|
|
979
999
|
const cachePolicyImpl = resolveCachePolicy(cachePolicy);
|
|
@@ -981,7 +1001,7 @@
|
|
|
981
1001
|
const storeLookup = (sel, refresh, ttlStrategy) => environment.storeLookup(sel, environment.createSnapshot, refresh, ttlStrategy);
|
|
982
1002
|
const applyCachePolicy = () => {
|
|
983
1003
|
return cachePolicyImpl({
|
|
984
|
-
|
|
1004
|
+
buildCachedSnapshot,
|
|
985
1005
|
buildNetworkSnapshot,
|
|
986
1006
|
buildSnapshotContext,
|
|
987
1007
|
resolvePendingSnapshot,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BuildCachedSnapshot, CachePolicyImplementationArgs, Snapshot, StoreLookup, TTLStrategy, UnAvailableSnapshot } from '@luvio/engine';
|
|
2
2
|
export declare type DurableCachePolicyFunctions = {
|
|
3
3
|
validateNotDisposed: () => void;
|
|
4
4
|
reviveSnapshotWithCachePolicy: <D, V>(unavailableSnapshot: UnAvailableSnapshot<D, V>, storeLookup: StoreLookup<D, V>) => Promise<Snapshot<D, V>>;
|
|
5
5
|
};
|
|
6
|
-
export declare function appendTTLStrategy<C, D>(storeLookup: CachePolicyImplementationArgs<C, D>['storeLookup'], ttlStrategy: TTLStrategy): Parameters<
|
|
6
|
+
export declare function appendTTLStrategy<C, D>(storeLookup: CachePolicyImplementationArgs<C, D>['storeLookup'], ttlStrategy: TTLStrategy): Parameters<BuildCachedSnapshot<C, D>>[1];
|
|
7
7
|
export declare function buildNetworkSnapshot<C, D>(args: CachePolicyImplementationArgs<C, D>): Promise<Snapshot<D, unknown>>;
|
|
8
8
|
export declare function buildTTLStrategy(staleDurationMilliseconds?: number): TTLStrategy;
|
|
9
|
+
export declare function buildAvailableSnapshotFromCachedSnapshotResponse<C, D>(cachedSnapshot: ReturnType<BuildCachedSnapshot<C, D>>, availableSnapshotFunc: (snapshot: Snapshot<D> | undefined) => Snapshot<D> | Promise<Snapshot<D>>): Snapshot<D> | Promise<Snapshot<D>>;
|
|
@@ -58,9 +58,13 @@
|
|
|
58
58
|
var isArray = Array.isArray;
|
|
59
59
|
|
|
60
60
|
function appendTTLStrategy(storeLookup, ttlStrategy) {
|
|
61
|
-
|
|
61
|
+
var returnStoreLookup = function (sel, refresh) {
|
|
62
62
|
return storeLookup(sel, refresh, ttlStrategy);
|
|
63
63
|
};
|
|
64
|
+
// append ttlStrategy to storeLookup function (in cases where custom adapter
|
|
65
|
+
// wants to perform it's own lookup)
|
|
66
|
+
returnStoreLookup.ttlStrategy = ttlStrategy;
|
|
67
|
+
return returnStoreLookup;
|
|
64
68
|
}
|
|
65
69
|
function buildNetworkSnapshot(args) {
|
|
66
70
|
var buildNetworkSnapshot = args.buildNetworkSnapshot, buildSnapshotContext = args.buildSnapshotContext, coercedAdapterRequestContext = args.coercedAdapterRequestContext;
|
|
@@ -86,102 +90,113 @@
|
|
|
86
90
|
}
|
|
87
91
|
return engine.StoreResolveResultState.Found;
|
|
88
92
|
};
|
|
93
|
+
}
|
|
94
|
+
// TODO - update userland-facing APIs to return `AvailableSnapshot` instead of `Snapshot`
|
|
95
|
+
// and then the signatures here can be updated as well
|
|
96
|
+
function buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, availableSnapshotFunc) {
|
|
97
|
+
if (isPromise(cachedSnapshot)) {
|
|
98
|
+
return cachedSnapshot.then(availableSnapshotFunc);
|
|
99
|
+
}
|
|
100
|
+
return availableSnapshotFunc(cachedSnapshot);
|
|
101
|
+
}
|
|
102
|
+
function isPromise(value) {
|
|
103
|
+
if (value === undefined) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
// check for Thenable due to test frameworks using custom Promise impls
|
|
107
|
+
return value.then !== undefined;
|
|
89
108
|
}
|
|
90
109
|
|
|
91
110
|
function buildCacheAndNetworkImplementation(funcs, staleDurationSeconds) {
|
|
111
|
+
if (staleDurationSeconds === void 0) { staleDurationSeconds = 0; }
|
|
92
112
|
return function (args) {
|
|
93
113
|
funcs.validateNotDisposed();
|
|
94
|
-
var
|
|
95
|
-
var staleDurationMilliseconds = staleDurationSeconds
|
|
114
|
+
var buildCachedSnapshot = args.buildCachedSnapshot, buildNetworkSnapshot$1 = args.buildNetworkSnapshot, buildSnapshotContext = args.buildSnapshotContext, storeLookup = args.storeLookup, coercedAdapterRequestContext = args.coercedAdapterRequestContext;
|
|
115
|
+
var staleDurationMilliseconds = staleDurationSeconds * 1000;
|
|
96
116
|
var cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy(staleDurationMilliseconds));
|
|
97
|
-
var
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
return args
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (revivedSnapshot.state === 'Stale') {
|
|
139
|
-
// kick off network request, do not await it
|
|
140
|
-
buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
|
|
141
|
-
// return the L2 cached snapshot to caller
|
|
142
|
-
return revivedSnapshot;
|
|
143
|
-
}
|
|
144
|
-
// data not found in L2 cache, go to the network
|
|
145
|
-
return buildNetworkSnapshot(args);
|
|
146
|
-
});
|
|
117
|
+
var cachedSnapshot = buildCachedSnapshot(buildSnapshotContext, cachePolicyStoreLookup);
|
|
118
|
+
return buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, function (snapshot) {
|
|
119
|
+
if (snapshot !== undefined) {
|
|
120
|
+
// data found in L1 cache
|
|
121
|
+
if (snapshot.state === 'Fulfilled' ||
|
|
122
|
+
snapshot.state === 'Error' ||
|
|
123
|
+
snapshot.state === 'Stale') {
|
|
124
|
+
// kick off network request, do not await it
|
|
125
|
+
buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
|
|
126
|
+
// return the cached snapshot to caller
|
|
127
|
+
return snapshot;
|
|
128
|
+
}
|
|
129
|
+
// network request outstanding
|
|
130
|
+
if (snapshot.state === 'Pending') {
|
|
131
|
+
// kick off another network request, do not await it
|
|
132
|
+
buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
|
|
133
|
+
return args.resolvePendingSnapshot(snapshot);
|
|
134
|
+
}
|
|
135
|
+
// if unfulfilled we have enough info to do an L2 lookup
|
|
136
|
+
if (snapshot.state === 'Unfulfilled') {
|
|
137
|
+
return funcs
|
|
138
|
+
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
139
|
+
.then(function (revivedSnapshot) {
|
|
140
|
+
// data found in L2 cache
|
|
141
|
+
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
142
|
+
revivedSnapshot.state === 'Error' ||
|
|
143
|
+
revivedSnapshot.state === 'Stale') {
|
|
144
|
+
// kick off network request, do not await it
|
|
145
|
+
buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
|
|
146
|
+
// return the L2 cached snapshot to caller
|
|
147
|
+
return revivedSnapshot;
|
|
148
|
+
}
|
|
149
|
+
if (revivedSnapshot.state === 'Pending') {
|
|
150
|
+
// kick off network request, do not await it
|
|
151
|
+
buildNetworkSnapshot$1(buildSnapshotContext, coercedAdapterRequestContext);
|
|
152
|
+
return args.resolvePendingSnapshot(revivedSnapshot);
|
|
153
|
+
}
|
|
154
|
+
// data not found in L2 cache, go to the network
|
|
155
|
+
return buildNetworkSnapshot(args);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
147
158
|
}
|
|
148
|
-
|
|
149
|
-
|
|
159
|
+
return buildNetworkSnapshot(args);
|
|
160
|
+
});
|
|
150
161
|
};
|
|
151
162
|
}
|
|
152
163
|
|
|
153
164
|
function buildCacheThenNetworkImplementation(funcs) {
|
|
154
165
|
return function (args) {
|
|
155
166
|
funcs.validateNotDisposed();
|
|
156
|
-
var
|
|
167
|
+
var buildCachedSnapshot = args.buildCachedSnapshot, buildSnapshotContext = args.buildSnapshotContext, storeLookup = args.storeLookup;
|
|
157
168
|
var cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy());
|
|
158
|
-
var
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (snapshot.state === 'Pending') {
|
|
165
|
-
return args.resolvePendingSnapshot(snapshot);
|
|
166
|
-
}
|
|
167
|
-
// data not found in L1 cache, try L2 cache
|
|
168
|
-
return funcs
|
|
169
|
-
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
170
|
-
.then(function (revivedSnapshot) {
|
|
171
|
-
// data found in L2 cache
|
|
172
|
-
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
173
|
-
revivedSnapshot.state === 'Error') {
|
|
174
|
-
return revivedSnapshot;
|
|
169
|
+
var cachedSnapshot = buildCachedSnapshot(buildSnapshotContext, cachePolicyStoreLookup);
|
|
170
|
+
return buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, function (snapshot) {
|
|
171
|
+
if (snapshot !== undefined) {
|
|
172
|
+
// data found in L1 cache
|
|
173
|
+
if (snapshot.state === 'Fulfilled' || snapshot.state === 'Error') {
|
|
174
|
+
return snapshot;
|
|
175
175
|
}
|
|
176
|
-
if (
|
|
177
|
-
return args.resolvePendingSnapshot(
|
|
176
|
+
if (snapshot.state === 'Pending') {
|
|
177
|
+
return args.resolvePendingSnapshot(snapshot);
|
|
178
178
|
}
|
|
179
|
-
//
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
179
|
+
// if unfulfilled we have enough info to do an L2 lookup
|
|
180
|
+
if (snapshot.state === 'Unfulfilled') {
|
|
181
|
+
return funcs
|
|
182
|
+
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
183
|
+
.then(function (revivedSnapshot) {
|
|
184
|
+
// data found in L2 cache
|
|
185
|
+
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
186
|
+
revivedSnapshot.state === 'Error') {
|
|
187
|
+
return revivedSnapshot;
|
|
188
|
+
}
|
|
189
|
+
if (revivedSnapshot.state === 'Pending') {
|
|
190
|
+
return args.resolvePendingSnapshot(revivedSnapshot);
|
|
191
|
+
}
|
|
192
|
+
// data not found in L2 cache, go to the network
|
|
193
|
+
return buildNetworkSnapshot(args);
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// L1 lookup could not find enough information to even construct a snapshot, go to the network
|
|
198
|
+
return buildNetworkSnapshot(args);
|
|
199
|
+
});
|
|
185
200
|
};
|
|
186
201
|
}
|
|
187
202
|
|
|
@@ -225,84 +240,90 @@
|
|
|
225
240
|
error: error,
|
|
226
241
|
state: 'Error',
|
|
227
242
|
data: undefined,
|
|
228
|
-
// TODO[@W-10164067]: copy refresh data from the snapshot returned by
|
|
243
|
+
// TODO[@W-10164067]: copy refresh data from the snapshot returned by buildCachedSnapshot (if any)
|
|
229
244
|
// refresh: ...
|
|
230
245
|
};
|
|
231
246
|
}
|
|
232
247
|
function buildOnlyIfCachedImplementation(funcs) {
|
|
233
248
|
return function (args) {
|
|
234
249
|
funcs.validateNotDisposed();
|
|
235
|
-
var
|
|
250
|
+
var buildCachedSnapshot = args.buildCachedSnapshot, buildSnapshotContext = args.buildSnapshotContext, storeLookup = args.storeLookup;
|
|
236
251
|
var cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy());
|
|
237
|
-
var
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
// network request outstanding, data is not cached
|
|
244
|
-
if (snapshot.state === 'Pending') {
|
|
245
|
-
return buildNotCachedErrorSnapshot();
|
|
246
|
-
}
|
|
247
|
-
// data not found in L1 cache, try L2 cache
|
|
248
|
-
return funcs
|
|
249
|
-
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
250
|
-
.then(function (revivedSnapshot) {
|
|
251
|
-
// data found in L2 cache
|
|
252
|
-
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
253
|
-
revivedSnapshot.state === 'Error') {
|
|
254
|
-
return revivedSnapshot;
|
|
252
|
+
var cachedSnapshot = buildCachedSnapshot(buildSnapshotContext, cachePolicyStoreLookup);
|
|
253
|
+
return buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, function (snapshot) {
|
|
254
|
+
if (snapshot !== undefined) {
|
|
255
|
+
// data found in L1 cache
|
|
256
|
+
if (snapshot.state === 'Fulfilled' || snapshot.state === 'Error') {
|
|
257
|
+
return snapshot;
|
|
255
258
|
}
|
|
256
|
-
// data is not cached
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
259
|
+
// network request outstanding, data is not cached
|
|
260
|
+
if (snapshot.state === 'Pending') {
|
|
261
|
+
return buildNotCachedErrorSnapshot();
|
|
262
|
+
}
|
|
263
|
+
// if unfulfilled we have enough info to do an L2 lookup
|
|
264
|
+
if (snapshot.state === 'Unfulfilled') {
|
|
265
|
+
return funcs
|
|
266
|
+
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
267
|
+
.then(function (revivedSnapshot) {
|
|
268
|
+
// data found in L2 cache
|
|
269
|
+
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
270
|
+
revivedSnapshot.state === 'Error') {
|
|
271
|
+
return revivedSnapshot;
|
|
272
|
+
}
|
|
273
|
+
// data is not cached
|
|
274
|
+
return buildNotCachedErrorSnapshot();
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return buildNotCachedErrorSnapshot();
|
|
279
|
+
});
|
|
261
280
|
};
|
|
262
281
|
}
|
|
263
282
|
|
|
264
283
|
function buildStaleWhileRevalidateImplementation(funcs, staleDurationSeconds) {
|
|
265
284
|
return function (args) {
|
|
266
285
|
funcs.validateNotDisposed();
|
|
267
|
-
var
|
|
286
|
+
var buildCachedSnapshot = args.buildCachedSnapshot, buildSnapshotContext = args.buildSnapshotContext, storeLookup = args.storeLookup;
|
|
268
287
|
var cachePolicyStoreLookup = appendTTLStrategy(storeLookup, buildTTLStrategy(staleDurationSeconds * 1000));
|
|
269
|
-
var
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
if (snapshot.state === 'Pending') {
|
|
276
|
-
return args.resolvePendingSnapshot(snapshot);
|
|
277
|
-
}
|
|
278
|
-
// stale data found in L1 cache
|
|
279
|
-
if (snapshot.state === 'Stale') {
|
|
280
|
-
buildNetworkSnapshot(args);
|
|
281
|
-
return snapshot;
|
|
282
|
-
}
|
|
283
|
-
// data not found in L1 cache, try L2 cache
|
|
284
|
-
return funcs
|
|
285
|
-
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
286
|
-
.then(function (revivedSnapshot) {
|
|
287
|
-
// data found in L2 cache
|
|
288
|
-
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
289
|
-
revivedSnapshot.state === 'Error') {
|
|
290
|
-
return revivedSnapshot;
|
|
288
|
+
var cachedSnapshot = buildCachedSnapshot(buildSnapshotContext, cachePolicyStoreLookup);
|
|
289
|
+
return buildAvailableSnapshotFromCachedSnapshotResponse(cachedSnapshot, function (snapshot) {
|
|
290
|
+
if (snapshot !== undefined) {
|
|
291
|
+
// data found in L1 cache
|
|
292
|
+
if (snapshot.state === 'Fulfilled' || snapshot.state === 'Error') {
|
|
293
|
+
return snapshot;
|
|
291
294
|
}
|
|
292
|
-
if (
|
|
293
|
-
return args.resolvePendingSnapshot(
|
|
295
|
+
if (snapshot.state === 'Pending') {
|
|
296
|
+
return args.resolvePendingSnapshot(snapshot);
|
|
294
297
|
}
|
|
295
|
-
// stale data found in
|
|
296
|
-
if (
|
|
298
|
+
// stale data found in L1 cache
|
|
299
|
+
if (snapshot.state === 'Stale') {
|
|
297
300
|
buildNetworkSnapshot(args);
|
|
298
|
-
return
|
|
301
|
+
return snapshot;
|
|
299
302
|
}
|
|
300
|
-
// data not found in
|
|
301
|
-
return
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
303
|
+
// data not found in L1 cache, try L2 cache
|
|
304
|
+
return funcs
|
|
305
|
+
.reviveSnapshotWithCachePolicy(snapshot, cachePolicyStoreLookup)
|
|
306
|
+
.then(function (revivedSnapshot) {
|
|
307
|
+
// data found in L2 cache
|
|
308
|
+
if (revivedSnapshot.state === 'Fulfilled' ||
|
|
309
|
+
revivedSnapshot.state === 'Error') {
|
|
310
|
+
return revivedSnapshot;
|
|
311
|
+
}
|
|
312
|
+
if (revivedSnapshot.state === 'Pending') {
|
|
313
|
+
return args.resolvePendingSnapshot(revivedSnapshot);
|
|
314
|
+
}
|
|
315
|
+
// stale data found in L2 cache
|
|
316
|
+
if (revivedSnapshot.state === 'Stale') {
|
|
317
|
+
buildNetworkSnapshot(args);
|
|
318
|
+
return revivedSnapshot;
|
|
319
|
+
}
|
|
320
|
+
// data not found in L2 cache, go to the network
|
|
321
|
+
return buildNetworkSnapshot(args);
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
// L1 lookup could not find enough information to even construct a snapshot, go to the network
|
|
325
|
+
return buildNetworkSnapshot(args);
|
|
326
|
+
});
|
|
306
327
|
};
|
|
307
328
|
}
|
|
308
329
|
|
|
@@ -313,7 +334,7 @@
|
|
|
313
334
|
// TTLStrategy to use the the valid-at cache policy's timestamp. The flow goes:
|
|
314
335
|
//
|
|
315
336
|
// Environment.applyCachePolicy => validAtImplementation (this function) =>
|
|
316
|
-
// basePolicyImplementation => adapter's
|
|
337
|
+
// basePolicyImplementation => adapter's buildCachedSnapshot =>
|
|
317
338
|
// basePolicyImplementation's storeLookup => validAtStoreLookup (below) =>
|
|
318
339
|
// Environment.applyCachePolicy's storeLookup => Store/Reader code =>
|
|
319
340
|
// valid-at TTLStrategy (below) =>
|
|
@@ -854,7 +875,7 @@
|
|
|
854
875
|
if (ingestStagingStore !== null) {
|
|
855
876
|
return ingestStagingStore.lookup(sel, createSnapshot, refresh, ttlStrategy);
|
|
856
877
|
}
|
|
857
|
-
// otherwise this is from
|
|
878
|
+
// otherwise this is from buildCachedSnapshot and we should use the luvio
|
|
858
879
|
// L1 store
|
|
859
880
|
return environment.storeLookup(sel, createSnapshot, refresh, ttlStrategy);
|
|
860
881
|
};
|
|
@@ -1018,7 +1039,7 @@
|
|
|
1018
1039
|
}
|
|
1019
1040
|
}
|
|
1020
1041
|
}
|
|
1021
|
-
var applyCachePolicy = function (adapterRequestContext, buildSnapshotContext,
|
|
1042
|
+
var applyCachePolicy = function (adapterRequestContext, buildSnapshotContext, buildCachedSnapshot, buildNetworkSnapshot) {
|
|
1022
1043
|
validateNotDisposed();
|
|
1023
1044
|
var cachePolicy = adapterRequestContext.cachePolicy;
|
|
1024
1045
|
var cachePolicyImpl = resolveCachePolicy(cachePolicy);
|
|
@@ -1028,7 +1049,7 @@
|
|
|
1028
1049
|
var storeLookup = function (sel, refresh, ttlStrategy) { return environment.storeLookup(sel, environment.createSnapshot, refresh, ttlStrategy); };
|
|
1029
1050
|
var applyCachePolicy = function () {
|
|
1030
1051
|
return cachePolicyImpl({
|
|
1031
|
-
|
|
1052
|
+
buildCachedSnapshot: buildCachedSnapshot,
|
|
1032
1053
|
buildNetworkSnapshot: buildNetworkSnapshot,
|
|
1033
1054
|
buildSnapshotContext: buildSnapshotContext,
|
|
1034
1055
|
resolvePendingSnapshot: resolvePendingSnapshot,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BuildCachedSnapshot, CachePolicyImplementationArgs, Snapshot, StoreLookup, TTLStrategy, UnAvailableSnapshot } from '@luvio/engine';
|
|
2
2
|
export declare type DurableCachePolicyFunctions = {
|
|
3
3
|
validateNotDisposed: () => void;
|
|
4
4
|
reviveSnapshotWithCachePolicy: <D, V>(unavailableSnapshot: UnAvailableSnapshot<D, V>, storeLookup: StoreLookup<D, V>) => Promise<Snapshot<D, V>>;
|
|
5
5
|
};
|
|
6
|
-
export declare function appendTTLStrategy<C, D>(storeLookup: CachePolicyImplementationArgs<C, D>['storeLookup'], ttlStrategy: TTLStrategy): Parameters<
|
|
6
|
+
export declare function appendTTLStrategy<C, D>(storeLookup: CachePolicyImplementationArgs<C, D>['storeLookup'], ttlStrategy: TTLStrategy): Parameters<BuildCachedSnapshot<C, D>>[1];
|
|
7
7
|
export declare function buildNetworkSnapshot<C, D>(args: CachePolicyImplementationArgs<C, D>): Promise<Snapshot<D, unknown>>;
|
|
8
8
|
export declare function buildTTLStrategy(staleDurationMilliseconds?: number): TTLStrategy;
|
|
9
|
+
export declare function buildAvailableSnapshotFromCachedSnapshotResponse<C, D>(cachedSnapshot: ReturnType<BuildCachedSnapshot<C, D>>, availableSnapshotFunc: (snapshot: Snapshot<D> | undefined) => Snapshot<D> | Promise<Snapshot<D>>): Snapshot<D> | Promise<Snapshot<D>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luvio/environments",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.71.0",
|
|
4
4
|
"description": "Luvio Environments",
|
|
5
5
|
"main": "dist/umd/es2018/environments.js",
|
|
6
6
|
"module": "dist/es/es2018/environments.js",
|
|
@@ -26,6 +26,6 @@
|
|
|
26
26
|
"dist/"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@luvio/engine": "0.
|
|
29
|
+
"@luvio/engine": "0.71.0"
|
|
30
30
|
}
|
|
31
31
|
}
|