@luvio/environments 0.48.3 → 0.49.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.
@@ -1,8 +1,24 @@
1
1
  /**
2
2
  * Contains store entry data along with any metadata for that entry that needs
3
3
  * to be persisted to durable storage
4
+ *
5
+ * IMPORTANT: if you update this interface, you must also create a
6
+ * deprecated interface, and check for durable store entries of this
7
+ * type in isDeprecatedDurableStoreEntry so that revive discards
8
+ * invalid entries.
4
9
  */
5
10
  export interface DurableStoreEntry<T = unknown> {
11
+ data: T;
12
+ metadata?: {
13
+ ingestionTimestamp: number;
14
+ expirationTimestamp: number;
15
+ staleTimestamp?: number;
16
+ namespace: string;
17
+ representationName: string;
18
+ };
19
+ }
20
+ export declare function isDeprecatedDurableStoreEntry(durableRecord: unknown): boolean;
21
+ export interface DeprecatedDurableStoreEntry1<T = unknown> {
6
22
  data: T;
7
23
  expiration?: {
8
24
  fresh: number;
@@ -1,3 +1,10 @@
1
+ function isDeprecatedDurableStoreEntry(durableRecord) {
2
+ if (durableRecord.expiration !== undefined) {
3
+ return true;
4
+ }
5
+ // Add more deprecated shape checks here
6
+ return false;
7
+ }
1
8
  var DurableStoreOperationType;
2
9
  (function (DurableStoreOperationType) {
3
10
  DurableStoreOperationType["SetEntries"] = "setEntries";
@@ -62,7 +69,7 @@ function buildPendingWriter() {
62
69
  flushPendingWritesToDurableStore: function (environment, durableStore, durableStoreErrorHandler) {
63
70
  const durableRecords = create({});
64
71
  const records = environment.getStoreRecords();
65
- const expirations = environment.getStoreRecordExpirations();
72
+ const storeMetadataMap = environment.getStoreMetadataMap();
66
73
  const keys$1 = keys(pendingDurableWrites);
67
74
  for (let i = 0, len = keys$1.length; i < len; i += 1) {
68
75
  const key = keys$1[i];
@@ -71,12 +78,12 @@ function buildPendingWriter() {
71
78
  if (record === undefined) {
72
79
  continue;
73
80
  }
74
- const ttl = expirations[key];
81
+ const recordMetadata = storeMetadataMap[key];
75
82
  durableRecords[key] = {
76
83
  // make copy of record b/c evict is coming
77
84
  // NOTE: only spread copy if an array or object
78
85
  data: copy(record),
79
- expiration: ttl,
86
+ metadata: recordMetadata,
80
87
  };
81
88
  // remove record from L1 cache while we are on the synchronous path
82
89
  // because we do not want some other code attempting to use the
@@ -250,8 +257,8 @@ function buildDurableStoreAwareRefresh(refresh, snapshot, environment, pendingWr
250
257
  function isStoreEntryError(storeRecord) {
251
258
  return storeRecord.__type === 'error';
252
259
  }
253
- function isStoreEntryExpiredAndError(storeRecord, fresh, now) {
254
- return isStoreEntryError(storeRecord) && fresh < now;
260
+ function isStoreEntryExpiredAndError(storeRecord, expirationTimestamp, now) {
261
+ return isStoreEntryError(storeRecord) && expirationTimestamp < now;
255
262
  }
256
263
  function reviveDurableEntriesToStore(durableRecords, environment, pendingWriter) {
257
264
  const revivedKeys = create(null);
@@ -268,37 +275,42 @@ function reviveDurableEntriesToStore(durableRecords, environment, pendingWriter)
268
275
  for (let i = 0, len = durableKeys.length; i < len; i += 1) {
269
276
  const key = durableKeys[i];
270
277
  const durableRecord = durableRecords[key];
271
- const { expiration, data } = durableRecord;
278
+ if (isDeprecatedDurableStoreEntry(durableRecord)) {
279
+ // had the old shape, skip reviving this entry.
280
+ hadUnexpectedShape = true;
281
+ continue;
282
+ }
283
+ const { metadata, data } = durableRecord;
272
284
  if (data === undefined) {
273
285
  // if unexpected data skip reviving
274
286
  hadUnexpectedShape = true;
275
287
  continue;
276
288
  }
277
- if (expiration !== undefined) {
278
- const { fresh, stale } = expiration;
279
- if (fresh === undefined || stale === undefined) {
289
+ if (metadata !== undefined) {
290
+ const { expirationTimestamp, staleTimestamp } = metadata;
291
+ if (expirationTimestamp === undefined || staleTimestamp === undefined) {
280
292
  // if unexpected expiration data skip reviving
281
293
  hadUnexpectedShape = true;
282
294
  continue;
283
295
  }
284
296
  // if past stale TTL then don't revive
285
- if (stale < now) {
297
+ if (staleTimestamp < now) {
286
298
  continue;
287
299
  }
288
300
  // We don't want to revive a cached value if it's an error and it's
289
- // fresh TTL is expired, otherwise we would never hit the network
301
+ // expirationTimestamp TTL is expired, otherwise we would never hit the network
290
302
  // during resolveSnapshot or rebuildSnapshot in the makeOffline
291
303
  // environment because the way the Reader works.
292
304
  // If a StoreEntry is an error, the Reader will return UnfulfilledSnapshot
293
305
  // if stale TTL is expired. But it will return ErrorSnapshot (instead of
294
- // StaleSnapshot) if fresh TTL is expired (but stale TTL isn't).
306
+ // StaleSnapshot) if expirationTimestamp TTL is expired (but stale TTL isn't).
295
307
  // In makeOffline environment the stale TTL is maxed out so Reader
296
308
  // will always return ErrorSnapshot.
297
- if (isStoreEntryExpiredAndError(data, fresh, now)) {
309
+ if (isStoreEntryExpiredAndError(data, expirationTimestamp, now)) {
298
310
  continue;
299
311
  }
300
- // call base storeSetExpiration so we don't add the key to pendingWriters
301
- environment.storeSetExpiration(key, fresh, stale);
312
+ // call base publishStoreMetadata so we don't add the key to pendingWriters
313
+ environment.publishStoreMetadata(key, metadata);
302
314
  }
303
315
  if (isStoreEntryError(data)) {
304
316
  // freeze errors on way into L1
@@ -375,7 +387,7 @@ function reviveSnapshot(environment, durableStore, pendingWriter, unavailableSna
375
387
  // now that we have revived the missingLinks
376
388
  const snapshot = baseSnapshot === undefined
377
389
  ? environment.storeLookup(unavailableSnapshot.select, environment.createSnapshot, unavailableSnapshot.refresh)
378
- : environment.rebuildSnapshot(baseSnapshot, environment.getStoreRecords(), environment.getStoreRecordExpirations(), environment.getStoreRedirectKeys(), () => { });
390
+ : environment.rebuildSnapshot(baseSnapshot, environment.getStoreRecords(), environment.getStoreMetadataMap(), environment.getStoreRedirectKeys(), () => { });
379
391
  // if snapshot is pending then some other in-flight refresh will broadcast
380
392
  // later
381
393
  if (snapshot.state === 'Pending') {
@@ -518,6 +530,12 @@ function makeDurable(environment, { durableStore, instrumentation, pendingWriter
518
530
  pendingWriter.addPendingWrite(recordId);
519
531
  environment.storeSetExpiration(recordId, expiration, staleExpiration);
520
532
  };
533
+ const publishStoreMetadata = function (recordId, storeMetadata) {
534
+ validateNotDisposed();
535
+ // mark this as pending write since we need to re-write with updated metadata values
536
+ pendingWriter.addPendingWrite(recordId);
537
+ environment.publishStoreMetadata(recordId, storeMetadata);
538
+ };
521
539
  const storeBroadcast = function (_rebuildSnapshot, _snapshotDataAvailable) {
522
540
  // don't await the DS write - DS implementation will take care of R/W
523
541
  // synchronization
@@ -552,10 +570,10 @@ function makeDurable(environment, { durableStore, instrumentation, pendingWriter
552
570
  }
553
571
  return reviveSnapshot(environment, durableStore, pendingWriter, snapshot, refresh, durableStoreErrorHandler);
554
572
  };
555
- const rebuildSnapshot = function (snapshot, records, recordExpirations, redirects, onAsyncRebuild) {
573
+ const rebuildSnapshot = function (snapshot, records, storeMetadataMap, redirects, onAsyncRebuild) {
556
574
  validateNotDisposed();
557
575
  // try rebuilding from memory
558
- const rebuilt = environment.rebuildSnapshot(snapshot, records, recordExpirations, redirects, onAsyncRebuild);
576
+ const rebuilt = environment.rebuildSnapshot(snapshot, records, storeMetadataMap, redirects, onAsyncRebuild);
559
577
  // only try reviving from durable store if snapshot is unfulfilled
560
578
  if (rebuilt.state !== 'Unfulfilled') {
561
579
  return rebuilt;
@@ -616,6 +634,7 @@ function makeDurable(environment, { durableStore, instrumentation, pendingWriter
616
634
  };
617
635
  return create(environment, {
618
636
  storeSetExpiration: { value: storeSetExpiration },
637
+ publishStoreMetadata: { value: publishStoreMetadata },
619
638
  storeBroadcast: { value: storeBroadcast },
620
639
  storeReset: { value: storeReset },
621
640
  resolveSnapshot: { value: resolveSnapshot },
@@ -662,6 +681,12 @@ function makeOffline(environment) {
662
681
  const setExpiration = function (recordId, expiration, _staleExpiration) {
663
682
  environment.storeSetExpiration(recordId, expiration, Number.MAX_SAFE_INTEGER);
664
683
  };
684
+ const publishStoreMetadata = function (recordId, storeMetadata) {
685
+ environment.publishStoreMetadata(recordId, {
686
+ ...storeMetadata,
687
+ staleTimestamp: Number.MAX_SAFE_INTEGER,
688
+ });
689
+ };
665
690
  return create(environment, {
666
691
  storeLookup: { value: storeLookup },
667
692
  snapshotAvailable: {
@@ -670,6 +695,9 @@ function makeOffline(environment) {
670
695
  storeSetExpiration: {
671
696
  value: setExpiration,
672
697
  },
698
+ publishStoreMetadata: {
699
+ value: publishStoreMetadata,
700
+ },
673
701
  });
674
702
  }
675
703
 
@@ -1,8 +1,24 @@
1
1
  /**
2
2
  * Contains store entry data along with any metadata for that entry that needs
3
3
  * to be persisted to durable storage
4
+ *
5
+ * IMPORTANT: if you update this interface, you must also create a
6
+ * deprecated interface, and check for durable store entries of this
7
+ * type in isDeprecatedDurableStoreEntry so that revive discards
8
+ * invalid entries.
4
9
  */
5
10
  export interface DurableStoreEntry<T = unknown> {
11
+ data: T;
12
+ metadata?: {
13
+ ingestionTimestamp: number;
14
+ expirationTimestamp: number;
15
+ staleTimestamp?: number;
16
+ namespace: string;
17
+ representationName: string;
18
+ };
19
+ }
20
+ export declare function isDeprecatedDurableStoreEntry(durableRecord: unknown): boolean;
21
+ export interface DeprecatedDurableStoreEntry1<T = unknown> {
6
22
  data: T;
7
23
  expiration?: {
8
24
  fresh: number;
@@ -4,6 +4,13 @@
4
4
  (global = global || self, factory(global.luvioEnvironments = {}));
5
5
  }(this, (function (exports) { 'use strict';
6
6
 
7
+ function isDeprecatedDurableStoreEntry(durableRecord) {
8
+ if (durableRecord.expiration !== undefined) {
9
+ return true;
10
+ }
11
+ // Add more deprecated shape checks here
12
+ return false;
13
+ }
7
14
  (function (DurableStoreOperationType) {
8
15
  DurableStoreOperationType["SetEntries"] = "setEntries";
9
16
  DurableStoreOperationType["EvictEntries"] = "evictEntries";
@@ -67,7 +74,7 @@
67
74
  flushPendingWritesToDurableStore: function (environment, durableStore, durableStoreErrorHandler) {
68
75
  const durableRecords = create({});
69
76
  const records = environment.getStoreRecords();
70
- const expirations = environment.getStoreRecordExpirations();
77
+ const storeMetadataMap = environment.getStoreMetadataMap();
71
78
  const keys$1 = keys(pendingDurableWrites);
72
79
  for (let i = 0, len = keys$1.length; i < len; i += 1) {
73
80
  const key = keys$1[i];
@@ -76,12 +83,12 @@
76
83
  if (record === undefined) {
77
84
  continue;
78
85
  }
79
- const ttl = expirations[key];
86
+ const recordMetadata = storeMetadataMap[key];
80
87
  durableRecords[key] = {
81
88
  // make copy of record b/c evict is coming
82
89
  // NOTE: only spread copy if an array or object
83
90
  data: copy(record),
84
- expiration: ttl,
91
+ metadata: recordMetadata,
85
92
  };
86
93
  // remove record from L1 cache while we are on the synchronous path
87
94
  // because we do not want some other code attempting to use the
@@ -255,8 +262,8 @@
255
262
  function isStoreEntryError(storeRecord) {
256
263
  return storeRecord.__type === 'error';
257
264
  }
258
- function isStoreEntryExpiredAndError(storeRecord, fresh, now) {
259
- return isStoreEntryError(storeRecord) && fresh < now;
265
+ function isStoreEntryExpiredAndError(storeRecord, expirationTimestamp, now) {
266
+ return isStoreEntryError(storeRecord) && expirationTimestamp < now;
260
267
  }
261
268
  function reviveDurableEntriesToStore(durableRecords, environment, pendingWriter) {
262
269
  const revivedKeys = create(null);
@@ -273,37 +280,42 @@
273
280
  for (let i = 0, len = durableKeys.length; i < len; i += 1) {
274
281
  const key = durableKeys[i];
275
282
  const durableRecord = durableRecords[key];
276
- const { expiration, data } = durableRecord;
283
+ if (isDeprecatedDurableStoreEntry(durableRecord)) {
284
+ // had the old shape, skip reviving this entry.
285
+ hadUnexpectedShape = true;
286
+ continue;
287
+ }
288
+ const { metadata, data } = durableRecord;
277
289
  if (data === undefined) {
278
290
  // if unexpected data skip reviving
279
291
  hadUnexpectedShape = true;
280
292
  continue;
281
293
  }
282
- if (expiration !== undefined) {
283
- const { fresh, stale } = expiration;
284
- if (fresh === undefined || stale === undefined) {
294
+ if (metadata !== undefined) {
295
+ const { expirationTimestamp, staleTimestamp } = metadata;
296
+ if (expirationTimestamp === undefined || staleTimestamp === undefined) {
285
297
  // if unexpected expiration data skip reviving
286
298
  hadUnexpectedShape = true;
287
299
  continue;
288
300
  }
289
301
  // if past stale TTL then don't revive
290
- if (stale < now) {
302
+ if (staleTimestamp < now) {
291
303
  continue;
292
304
  }
293
305
  // We don't want to revive a cached value if it's an error and it's
294
- // fresh TTL is expired, otherwise we would never hit the network
306
+ // expirationTimestamp TTL is expired, otherwise we would never hit the network
295
307
  // during resolveSnapshot or rebuildSnapshot in the makeOffline
296
308
  // environment because the way the Reader works.
297
309
  // If a StoreEntry is an error, the Reader will return UnfulfilledSnapshot
298
310
  // if stale TTL is expired. But it will return ErrorSnapshot (instead of
299
- // StaleSnapshot) if fresh TTL is expired (but stale TTL isn't).
311
+ // StaleSnapshot) if expirationTimestamp TTL is expired (but stale TTL isn't).
300
312
  // In makeOffline environment the stale TTL is maxed out so Reader
301
313
  // will always return ErrorSnapshot.
302
- if (isStoreEntryExpiredAndError(data, fresh, now)) {
314
+ if (isStoreEntryExpiredAndError(data, expirationTimestamp, now)) {
303
315
  continue;
304
316
  }
305
- // call base storeSetExpiration so we don't add the key to pendingWriters
306
- environment.storeSetExpiration(key, fresh, stale);
317
+ // call base publishStoreMetadata so we don't add the key to pendingWriters
318
+ environment.publishStoreMetadata(key, metadata);
307
319
  }
308
320
  if (isStoreEntryError(data)) {
309
321
  // freeze errors on way into L1
@@ -380,7 +392,7 @@
380
392
  // now that we have revived the missingLinks
381
393
  const snapshot = baseSnapshot === undefined
382
394
  ? environment.storeLookup(unavailableSnapshot.select, environment.createSnapshot, unavailableSnapshot.refresh)
383
- : environment.rebuildSnapshot(baseSnapshot, environment.getStoreRecords(), environment.getStoreRecordExpirations(), environment.getStoreRedirectKeys(), () => { });
395
+ : environment.rebuildSnapshot(baseSnapshot, environment.getStoreRecords(), environment.getStoreMetadataMap(), environment.getStoreRedirectKeys(), () => { });
384
396
  // if snapshot is pending then some other in-flight refresh will broadcast
385
397
  // later
386
398
  if (snapshot.state === 'Pending') {
@@ -523,6 +535,12 @@
523
535
  pendingWriter.addPendingWrite(recordId);
524
536
  environment.storeSetExpiration(recordId, expiration, staleExpiration);
525
537
  };
538
+ const publishStoreMetadata = function (recordId, storeMetadata) {
539
+ validateNotDisposed();
540
+ // mark this as pending write since we need to re-write with updated metadata values
541
+ pendingWriter.addPendingWrite(recordId);
542
+ environment.publishStoreMetadata(recordId, storeMetadata);
543
+ };
526
544
  const storeBroadcast = function (_rebuildSnapshot, _snapshotDataAvailable) {
527
545
  // don't await the DS write - DS implementation will take care of R/W
528
546
  // synchronization
@@ -557,10 +575,10 @@
557
575
  }
558
576
  return reviveSnapshot(environment, durableStore, pendingWriter, snapshot, refresh, durableStoreErrorHandler);
559
577
  };
560
- const rebuildSnapshot = function (snapshot, records, recordExpirations, redirects, onAsyncRebuild) {
578
+ const rebuildSnapshot = function (snapshot, records, storeMetadataMap, redirects, onAsyncRebuild) {
561
579
  validateNotDisposed();
562
580
  // try rebuilding from memory
563
- const rebuilt = environment.rebuildSnapshot(snapshot, records, recordExpirations, redirects, onAsyncRebuild);
581
+ const rebuilt = environment.rebuildSnapshot(snapshot, records, storeMetadataMap, redirects, onAsyncRebuild);
564
582
  // only try reviving from durable store if snapshot is unfulfilled
565
583
  if (rebuilt.state !== 'Unfulfilled') {
566
584
  return rebuilt;
@@ -621,6 +639,7 @@
621
639
  };
622
640
  return create(environment, {
623
641
  storeSetExpiration: { value: storeSetExpiration },
642
+ publishStoreMetadata: { value: publishStoreMetadata },
624
643
  storeBroadcast: { value: storeBroadcast },
625
644
  storeReset: { value: storeReset },
626
645
  resolveSnapshot: { value: resolveSnapshot },
@@ -667,6 +686,12 @@
667
686
  const setExpiration = function (recordId, expiration, _staleExpiration) {
668
687
  environment.storeSetExpiration(recordId, expiration, Number.MAX_SAFE_INTEGER);
669
688
  };
689
+ const publishStoreMetadata = function (recordId, storeMetadata) {
690
+ environment.publishStoreMetadata(recordId, {
691
+ ...storeMetadata,
692
+ staleTimestamp: Number.MAX_SAFE_INTEGER,
693
+ });
694
+ };
670
695
  return create(environment, {
671
696
  storeLookup: { value: storeLookup },
672
697
  snapshotAvailable: {
@@ -675,6 +700,9 @@
675
700
  storeSetExpiration: {
676
701
  value: setExpiration,
677
702
  },
703
+ publishStoreMetadata: {
704
+ value: publishStoreMetadata,
705
+ },
678
706
  });
679
707
  }
680
708
 
@@ -1,8 +1,24 @@
1
1
  /**
2
2
  * Contains store entry data along with any metadata for that entry that needs
3
3
  * to be persisted to durable storage
4
+ *
5
+ * IMPORTANT: if you update this interface, you must also create a
6
+ * deprecated interface, and check for durable store entries of this
7
+ * type in isDeprecatedDurableStoreEntry so that revive discards
8
+ * invalid entries.
4
9
  */
5
10
  export interface DurableStoreEntry<T = unknown> {
11
+ data: T;
12
+ metadata?: {
13
+ ingestionTimestamp: number;
14
+ expirationTimestamp: number;
15
+ staleTimestamp?: number;
16
+ namespace: string;
17
+ representationName: string;
18
+ };
19
+ }
20
+ export declare function isDeprecatedDurableStoreEntry(durableRecord: unknown): boolean;
21
+ export interface DeprecatedDurableStoreEntry1<T = unknown> {
6
22
  data: T;
7
23
  expiration?: {
8
24
  fresh: number;
@@ -4,6 +4,13 @@
4
4
  (global = global || self, factory(global.luvioEnvironments = {}));
5
5
  }(this, (function (exports) { 'use strict';
6
6
 
7
+ function isDeprecatedDurableStoreEntry(durableRecord) {
8
+ if (durableRecord.expiration !== undefined) {
9
+ return true;
10
+ }
11
+ // Add more deprecated shape checks here
12
+ return false;
13
+ }
7
14
  (function (DurableStoreOperationType) {
8
15
  DurableStoreOperationType["SetEntries"] = "setEntries";
9
16
  DurableStoreOperationType["EvictEntries"] = "evictEntries";
@@ -102,7 +109,7 @@
102
109
  flushPendingWritesToDurableStore: function (environment, durableStore, durableStoreErrorHandler) {
103
110
  var durableRecords = create({});
104
111
  var records = environment.getStoreRecords();
105
- var expirations = environment.getStoreRecordExpirations();
112
+ var storeMetadataMap = environment.getStoreMetadataMap();
106
113
  var keys$1 = keys(pendingDurableWrites);
107
114
  for (var i = 0, len = keys$1.length; i < len; i += 1) {
108
115
  var key = keys$1[i];
@@ -111,12 +118,12 @@
111
118
  if (record === undefined) {
112
119
  continue;
113
120
  }
114
- var ttl = expirations[key];
121
+ var recordMetadata = storeMetadataMap[key];
115
122
  durableRecords[key] = {
116
123
  // make copy of record b/c evict is coming
117
124
  // NOTE: only spread copy if an array or object
118
125
  data: copy(record),
119
- expiration: ttl,
126
+ metadata: recordMetadata,
120
127
  };
121
128
  // remove record from L1 cache while we are on the synchronous path
122
129
  // because we do not want some other code attempting to use the
@@ -281,8 +288,8 @@
281
288
  function isStoreEntryError(storeRecord) {
282
289
  return storeRecord.__type === 'error';
283
290
  }
284
- function isStoreEntryExpiredAndError(storeRecord, fresh, now) {
285
- return isStoreEntryError(storeRecord) && fresh < now;
291
+ function isStoreEntryExpiredAndError(storeRecord, expirationTimestamp, now) {
292
+ return isStoreEntryError(storeRecord) && expirationTimestamp < now;
286
293
  }
287
294
  function reviveDurableEntriesToStore(durableRecords, environment, pendingWriter) {
288
295
  var revivedKeys = create(null);
@@ -299,37 +306,42 @@
299
306
  for (var i = 0, len = durableKeys.length; i < len; i += 1) {
300
307
  var key = durableKeys[i];
301
308
  var durableRecord = durableRecords[key];
302
- var expiration = durableRecord.expiration, data = durableRecord.data;
309
+ if (isDeprecatedDurableStoreEntry(durableRecord)) {
310
+ // had the old shape, skip reviving this entry.
311
+ hadUnexpectedShape = true;
312
+ continue;
313
+ }
314
+ var metadata = durableRecord.metadata, data = durableRecord.data;
303
315
  if (data === undefined) {
304
316
  // if unexpected data skip reviving
305
317
  hadUnexpectedShape = true;
306
318
  continue;
307
319
  }
308
- if (expiration !== undefined) {
309
- var fresh = expiration.fresh, stale = expiration.stale;
310
- if (fresh === undefined || stale === undefined) {
320
+ if (metadata !== undefined) {
321
+ var expirationTimestamp = metadata.expirationTimestamp, staleTimestamp = metadata.staleTimestamp;
322
+ if (expirationTimestamp === undefined || staleTimestamp === undefined) {
311
323
  // if unexpected expiration data skip reviving
312
324
  hadUnexpectedShape = true;
313
325
  continue;
314
326
  }
315
327
  // if past stale TTL then don't revive
316
- if (stale < now) {
328
+ if (staleTimestamp < now) {
317
329
  continue;
318
330
  }
319
331
  // We don't want to revive a cached value if it's an error and it's
320
- // fresh TTL is expired, otherwise we would never hit the network
332
+ // expirationTimestamp TTL is expired, otherwise we would never hit the network
321
333
  // during resolveSnapshot or rebuildSnapshot in the makeOffline
322
334
  // environment because the way the Reader works.
323
335
  // If a StoreEntry is an error, the Reader will return UnfulfilledSnapshot
324
336
  // if stale TTL is expired. But it will return ErrorSnapshot (instead of
325
- // StaleSnapshot) if fresh TTL is expired (but stale TTL isn't).
337
+ // StaleSnapshot) if expirationTimestamp TTL is expired (but stale TTL isn't).
326
338
  // In makeOffline environment the stale TTL is maxed out so Reader
327
339
  // will always return ErrorSnapshot.
328
- if (isStoreEntryExpiredAndError(data, fresh, now)) {
340
+ if (isStoreEntryExpiredAndError(data, expirationTimestamp, now)) {
329
341
  continue;
330
342
  }
331
- // call base storeSetExpiration so we don't add the key to pendingWriters
332
- environment.storeSetExpiration(key, fresh, stale);
343
+ // call base publishStoreMetadata so we don't add the key to pendingWriters
344
+ environment.publishStoreMetadata(key, metadata);
333
345
  }
334
346
  if (isStoreEntryError(data)) {
335
347
  // freeze errors on way into L1
@@ -408,7 +420,7 @@
408
420
  // now that we have revived the missingLinks
409
421
  var snapshot = baseSnapshot === undefined
410
422
  ? environment.storeLookup(unavailableSnapshot.select, environment.createSnapshot, unavailableSnapshot.refresh)
411
- : environment.rebuildSnapshot(baseSnapshot, environment.getStoreRecords(), environment.getStoreRecordExpirations(), environment.getStoreRedirectKeys(), function () { });
423
+ : environment.rebuildSnapshot(baseSnapshot, environment.getStoreRecords(), environment.getStoreMetadataMap(), environment.getStoreRedirectKeys(), function () { });
412
424
  // if snapshot is pending then some other in-flight refresh will broadcast
413
425
  // later
414
426
  if (snapshot.state === 'Pending') {
@@ -553,6 +565,12 @@
553
565
  pendingWriter.addPendingWrite(recordId);
554
566
  environment.storeSetExpiration(recordId, expiration, staleExpiration);
555
567
  };
568
+ var publishStoreMetadata = function (recordId, storeMetadata) {
569
+ validateNotDisposed();
570
+ // mark this as pending write since we need to re-write with updated metadata values
571
+ pendingWriter.addPendingWrite(recordId);
572
+ environment.publishStoreMetadata(recordId, storeMetadata);
573
+ };
556
574
  var storeBroadcast = function (_rebuildSnapshot, _snapshotDataAvailable) {
557
575
  // don't await the DS write - DS implementation will take care of R/W
558
576
  // synchronization
@@ -587,10 +605,10 @@
587
605
  }
588
606
  return reviveSnapshot(environment, durableStore, pendingWriter, snapshot, refresh, durableStoreErrorHandler);
589
607
  };
590
- var rebuildSnapshot = function (snapshot, records, recordExpirations, redirects, onAsyncRebuild) {
608
+ var rebuildSnapshot = function (snapshot, records, storeMetadataMap, redirects, onAsyncRebuild) {
591
609
  validateNotDisposed();
592
610
  // try rebuilding from memory
593
- var rebuilt = environment.rebuildSnapshot(snapshot, records, recordExpirations, redirects, onAsyncRebuild);
611
+ var rebuilt = environment.rebuildSnapshot(snapshot, records, storeMetadataMap, redirects, onAsyncRebuild);
594
612
  // only try reviving from durable store if snapshot is unfulfilled
595
613
  if (rebuilt.state !== 'Unfulfilled') {
596
614
  return rebuilt;
@@ -649,6 +667,7 @@
649
667
  };
650
668
  return create(environment, {
651
669
  storeSetExpiration: { value: storeSetExpiration },
670
+ publishStoreMetadata: { value: publishStoreMetadata },
652
671
  storeBroadcast: { value: storeBroadcast },
653
672
  storeReset: { value: storeReset },
654
673
  resolveSnapshot: { value: resolveSnapshot },
@@ -695,6 +714,9 @@
695
714
  var setExpiration = function (recordId, expiration, _staleExpiration) {
696
715
  environment.storeSetExpiration(recordId, expiration, Number.MAX_SAFE_INTEGER);
697
716
  };
717
+ var publishStoreMetadata = function (recordId, storeMetadata) {
718
+ environment.publishStoreMetadata(recordId, __assign(__assign({}, storeMetadata), { staleTimestamp: Number.MAX_SAFE_INTEGER }));
719
+ };
698
720
  return create(environment, {
699
721
  storeLookup: { value: storeLookup },
700
722
  snapshotAvailable: {
@@ -703,6 +725,9 @@
703
725
  storeSetExpiration: {
704
726
  value: setExpiration,
705
727
  },
728
+ publishStoreMetadata: {
729
+ value: publishStoreMetadata,
730
+ },
706
731
  });
707
732
  }
708
733
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luvio/environments",
3
- "version": "0.48.3",
3
+ "version": "0.49.0",
4
4
  "description": "Luvio Environments",
5
5
  "main": "dist/umd/es2018/environments.js",
6
6
  "module": "dist/es/es2018/environments.js",
@@ -16,6 +16,6 @@
16
16
  "dist/"
17
17
  ],
18
18
  "dependencies": {
19
- "@luvio/engine": "0.48.3"
19
+ "@luvio/engine": "0.49.0"
20
20
  }
21
21
  }