@luvio/environments 0.99.2 → 0.102.1

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,4 +1,4 @@
1
- import { emitAdapterEvent, buildStaleWhileRevalidateImplementation, InMemoryStore } from '@luvio/engine';
1
+ import { emitAdapterEvent, InMemoryStore, buildStaleWhileRevalidateImplementation, Reader } from '@luvio/engine';
2
2
 
3
3
  function isDeprecatedDurableStoreEntry(durableRecord) {
4
4
  if (durableRecord.expiration !== undefined) {
@@ -343,6 +343,31 @@ function emitDurableEnvironmentAdapterEvent(eventData, observers) {
343
343
  }, observers);
344
344
  }
345
345
 
346
+ async function reviveTTLOverrides(ttlStore, environment) {
347
+ const map = await ttlStore.getDurableTTLOverrides();
348
+ const { defaultTTL, overrides } = map;
349
+ if (defaultTTL !== undefined) {
350
+ environment.storeSetDefaultTTLOverride(defaultTTL.ttl);
351
+ }
352
+ for (let i = 0, len = overrides.length; i < len; i++) {
353
+ const { namespace, representationName, ttl } = overrides[i];
354
+ environment.storeSetTTLOverride(namespace, representationName, ttl);
355
+ }
356
+ }
357
+
358
+ /**
359
+ * Returns an empty InMemoryStore that can be used for ingestion. Copies over
360
+ * the TTLOverrides from the given Environment's Store.
361
+ */
362
+ function buildIngestStagingStore(environment) {
363
+ const store = new InMemoryStore();
364
+ // need to make sure any TTL overrides are brought over from real L1
365
+ // because storePublishMetadata uses those overrides
366
+ store.ttlOverrides = environment.storeGetTTLOverrides();
367
+ store.defaultTTLOverride = environment.storeGetDefaultTTLOverride();
368
+ return store;
369
+ }
370
+
346
371
  const AdapterContextSegment = 'ADAPTER-CONTEXT';
347
372
  const ADAPTER_CONTEXT_ID_SUFFIX = '__NAMED_CONTEXT';
348
373
  function reviveOrCreateContext(adapterId, durableStore, durableStoreErrorHandler, onContextLoaded) {
@@ -399,20 +424,12 @@ function isUnfulfilledSnapshot(cachedSnapshotResult) {
399
424
  function makeDurable(environment, { durableStore, instrumentation }) {
400
425
  let ingestStagingStore = null;
401
426
  const durableTTLStore = new DurableTTLStore(durableStore);
402
- let isRevivingTTLOverrides;
403
- isRevivingTTLOverrides = new Promise((resolve) => {
404
- durableTTLStore.getDurableTTLOverrides().then((map) => {
405
- const { defaultTTL, overrides } = map;
406
- if (defaultTTL !== undefined) {
407
- environment.storeSetDefaultTTLOverride(defaultTTL.ttl);
408
- }
409
- for (let i = 0, len = overrides.length; i < len; i++) {
410
- const { namespace, representationName, ttl } = overrides[i];
411
- environment.storeSetTTLOverride(namespace, representationName, ttl);
412
- }
427
+ let initializationPromise = new Promise((resolve) => {
428
+ const finish = () => {
413
429
  resolve();
414
- isRevivingTTLOverrides = undefined;
415
- });
430
+ initializationPromise = undefined;
431
+ };
432
+ reviveTTLOverrides(durableTTLStore, environment).then(finish);
416
433
  });
417
434
  //instrumentation for durable store errors
418
435
  const durableStoreErrorHandler = handleDurableStoreRejection(instrumentation);
@@ -464,7 +481,7 @@ function makeDurable(environment, { durableStore, instrumentation }) {
464
481
  const storePublish = function (key, data) {
465
482
  validateNotDisposed();
466
483
  if (ingestStagingStore === null) {
467
- ingestStagingStore = new InMemoryStore();
484
+ ingestStagingStore = buildIngestStagingStore(environment);
468
485
  }
469
486
  ingestStagingStore.publish(key, data);
470
487
  // remove record from main luvio L1 cache while we are on the synchronous path
@@ -476,7 +493,7 @@ function makeDurable(environment, { durableStore, instrumentation }) {
476
493
  const publishStoreMetadata = function (recordId, storeMetadata) {
477
494
  validateNotDisposed();
478
495
  if (ingestStagingStore === null) {
479
- ingestStagingStore = new InMemoryStore();
496
+ ingestStagingStore = buildIngestStagingStore(environment);
480
497
  }
481
498
  ingestStagingStore.publishMetadata(recordId, storeMetadata);
482
499
  };
@@ -485,14 +502,14 @@ function makeDurable(environment, { durableStore, instrumentation }) {
485
502
  // we don't ingest to the luvio L1 store from network directly, we ingest to
486
503
  // L2 and let DurableStore on change event revive keys into luvio L1 store
487
504
  if (ingestStagingStore === null) {
488
- ingestStagingStore = new InMemoryStore();
505
+ ingestStagingStore = buildIngestStagingStore(environment);
489
506
  }
490
507
  environment.storeIngest(key, ingest, response, luvio, ingestStagingStore);
491
508
  };
492
509
  const storeIngestError = function (key, errorSnapshot, storeMetadataParams, _storeOverride) {
493
510
  validateNotDisposed();
494
511
  if (ingestStagingStore === null) {
495
- ingestStagingStore = new InMemoryStore();
512
+ ingestStagingStore = buildIngestStagingStore(environment);
496
513
  }
497
514
  environment.storeIngestError(key, errorSnapshot, storeMetadataParams, ingestStagingStore);
498
515
  };
@@ -515,7 +532,8 @@ function makeDurable(environment, { durableStore, instrumentation }) {
515
532
  validateNotDisposed();
516
533
  // if this lookup is right after an ingest there will be a staging store
517
534
  if (ingestStagingStore !== null) {
518
- return ingestStagingStore.lookup(sel, createSnapshot, refresh, ttlStrategy);
535
+ const reader = new Reader(ingestStagingStore, sel.variables, refresh, undefined, ttlStrategy);
536
+ return reader.read(sel);
519
537
  }
520
538
  // otherwise this is from buildCachedSnapshot and we should use the luvio
521
539
  // L1 store
@@ -524,28 +542,28 @@ function makeDurable(environment, { durableStore, instrumentation }) {
524
542
  const storeEvict = function (key) {
525
543
  validateNotDisposed();
526
544
  if (ingestStagingStore === null) {
527
- ingestStagingStore = new InMemoryStore();
545
+ ingestStagingStore = buildIngestStagingStore(environment);
528
546
  }
529
547
  ingestStagingStore.evict(key);
530
548
  };
531
549
  const getNode = function (key) {
532
550
  validateNotDisposed();
533
551
  if (ingestStagingStore === null) {
534
- ingestStagingStore = new InMemoryStore();
552
+ ingestStagingStore = buildIngestStagingStore(environment);
535
553
  }
536
554
  return environment.getNode(key, ingestStagingStore);
537
555
  };
538
556
  const wrapNormalizedGraphNode = function (normalized) {
539
557
  validateNotDisposed();
540
558
  if (ingestStagingStore === null) {
541
- ingestStagingStore = new InMemoryStore();
559
+ ingestStagingStore = buildIngestStagingStore(environment);
542
560
  }
543
561
  return environment.wrapNormalizedGraphNode(normalized, ingestStagingStore);
544
562
  };
545
- const rebuildSnapshot = function (snapshot, records, storeMetadataMap, redirects, onAsyncRebuild) {
563
+ const rebuildSnapshot = function (snapshot, onAsyncRebuild) {
546
564
  validateNotDisposed();
547
565
  // try rebuilding from memory
548
- const rebuilt = environment.rebuildSnapshot(snapshot, records, storeMetadataMap, redirects, onAsyncRebuild);
566
+ const rebuilt = environment.rebuildSnapshot(snapshot, onAsyncRebuild);
549
567
  // only try reviving from durable store if snapshot is unfulfilled
550
568
  if (rebuilt.state !== 'Unfulfilled') {
551
569
  return rebuilt;
@@ -554,7 +572,7 @@ function makeDurable(environment, { durableStore, instrumentation }) {
554
572
  reviveSnapshot(environment, durableStore, rebuilt, durableStoreErrorHandler, () =>
555
573
  // reviveSnapshot will revive into L1, and since "records" is a reference
556
574
  // (and not a copy) to the L1 records we can use it for rebuild
557
- environment.rebuildSnapshot(snapshot, records, storeMetadataMap, redirects, () => { })).then((result) => {
575
+ environment.rebuildSnapshot(snapshot, () => { })).then((result) => {
558
576
  onAsyncRebuild(result.snapshot);
559
577
  });
560
578
  // synchronously return the base snapshot as Pending if not already
@@ -606,16 +624,28 @@ function makeDurable(environment, { durableStore, instrumentation }) {
606
624
  validateNotDisposed();
607
625
  return durableTTLStore.getDurableTTLOverrides();
608
626
  };
627
+ const dispatchResourceRequest = async function (request, context, eventObservers) {
628
+ validateNotDisposed();
629
+ // non-GET adapters call dispatchResourceRequest before any other luvio
630
+ // function so this is our chance to ensure we're initialized
631
+ if (initializationPromise !== undefined) {
632
+ await initializationPromise;
633
+ }
634
+ return environment.dispatchResourceRequest(request, context, eventObservers);
635
+ };
636
+ // NOTE: we can't use "async" keyword on this function because that would
637
+ // force it to always be an async response. The signature is a union
638
+ // of sync/async so no "awaiting" in this function, just promise-chaining
609
639
  const applyCachePolicy = function (luvio, adapterRequestContext, buildSnapshotContext, buildCachedSnapshot, buildNetworkSnapshot) {
610
640
  validateNotDisposed();
611
- const wrappedCacheLookup = (buildSnapshotContext, storeLookup) => {
612
- const snapshot = buildCachedSnapshot(buildSnapshotContext, storeLookup, luvio);
641
+ const wrappedCacheLookup = (injectedBuildSnapshotContext, injectedStoreLookup) => {
642
+ const snapshot = buildCachedSnapshot(injectedBuildSnapshotContext, injectedStoreLookup, luvio);
613
643
  // if the adapter attempted to do an L1 lookup and it was unfulfilled
614
644
  // then we can attempt an L2 lookup
615
645
  if (isUnfulfilledSnapshot(snapshot)) {
616
646
  const start = Date.now();
617
647
  emitDurableEnvironmentAdapterEvent({ type: 'l2-revive-start' }, adapterRequestContext.eventObservers);
618
- const revivedSnapshot = reviveSnapshot(environment, durableStore, snapshot, durableStoreErrorHandler, () => storeLookup(snapshot.select, snapshot.refresh)).then((result) => {
648
+ const revivedSnapshot = reviveSnapshot(environment, durableStore, snapshot, durableStoreErrorHandler, () => injectedStoreLookup(snapshot.select, snapshot.refresh)).then((result) => {
619
649
  emitDurableEnvironmentAdapterEvent({
620
650
  type: 'l2-revive-end',
621
651
  duration: Date.now() - start,
@@ -629,12 +659,14 @@ function makeDurable(environment, { durableStore, instrumentation }) {
629
659
  // otherwise just return what buildCachedSnapshot gave us
630
660
  return snapshot;
631
661
  };
632
- const applyCachePolicy = () => {
662
+ const wrappedApplyCachePolicy = () => {
633
663
  return environment.applyCachePolicy(luvio, adapterRequestContext, buildSnapshotContext, wrappedCacheLookup, buildNetworkSnapshot);
634
664
  };
635
- return isRevivingTTLOverrides !== undefined
636
- ? isRevivingTTLOverrides.then(applyCachePolicy)
637
- : applyCachePolicy();
665
+ // GET adapters call applyCachePolicy before any other luvio
666
+ // function so this is our chance to ensure we're initialized
667
+ return initializationPromise !== undefined
668
+ ? initializationPromise.then(wrappedApplyCachePolicy)
669
+ : wrappedApplyCachePolicy();
638
670
  };
639
671
  const getIngestStagingStoreRecords = function () {
640
672
  validateNotDisposed();
@@ -666,7 +698,7 @@ function makeDurable(environment, { durableStore, instrumentation }) {
666
698
  const toPrime = existingRecords !== undefined
667
699
  ? { ...revivedRecords, ...existingRecords }
668
700
  : revivedRecords;
669
- ingestStagingStore = new InMemoryStore();
701
+ ingestStagingStore = buildIngestStagingStore(environment);
670
702
  ingestStagingStore.records = toPrime;
671
703
  const snapshotFromMemoryIngest = ingestAndBroadcastFunc();
672
704
  return publishChangesToDurableStore().then(() => {
@@ -736,6 +768,7 @@ function makeDurable(environment, { durableStore, instrumentation }) {
736
768
  dispose: { value: dispose },
737
769
  publishChangesToDurableStore: { value: publishChangesToDurableStore },
738
770
  getDurableTTLOverrides: { value: getDurableTTLOverrides },
771
+ dispatchResourceRequest: { value: dispatchResourceRequest },
739
772
  applyCachePolicy: { value: applyCachePolicy },
740
773
  getIngestStagingStoreRecords: { value: getIngestStagingStoreRecords },
741
774
  getIngestStagingStoreMetadata: { value: getIngestStagingStoreMetadata },
@@ -0,0 +1,7 @@
1
+ import { InMemoryStore } from '@luvio/engine';
2
+ import type { Environment } from '@luvio/engine';
3
+ /**
4
+ * Returns an empty InMemoryStore that can be used for ingestion. Copies over
5
+ * the TTLOverrides from the given Environment's Store.
6
+ */
7
+ export declare function buildIngestStagingStore(environment: Environment): InMemoryStore;
@@ -0,0 +1,3 @@
1
+ import type { Environment } from '@luvio/engine';
2
+ import type { DurableTTLStore } from '../DurableTTLStore';
3
+ export declare function reviveTTLOverrides(ttlStore: DurableTTLStore, environment: Environment): Promise<void>;
@@ -1,5 +1,4 @@
1
- import type { CacheKeySet, Environment, RecordSource, Snapshot } from '@luvio/engine';
2
- import { InMemoryStore } from '@luvio/engine';
1
+ import type { CacheKeySet, Environment, RecordSource, Snapshot, InMemoryStore } from '@luvio/engine';
3
2
  import type { DurableStore } from './DurableStore';
4
3
  import type { InstrumentationFunction } from './makeDurable/error';
5
4
  import type { TTLOverridesMap } from './DurableTTLStore';
@@ -347,6 +347,31 @@
347
347
  }, observers);
348
348
  }
349
349
 
350
+ async function reviveTTLOverrides(ttlStore, environment) {
351
+ const map = await ttlStore.getDurableTTLOverrides();
352
+ const { defaultTTL, overrides } = map;
353
+ if (defaultTTL !== undefined) {
354
+ environment.storeSetDefaultTTLOverride(defaultTTL.ttl);
355
+ }
356
+ for (let i = 0, len = overrides.length; i < len; i++) {
357
+ const { namespace, representationName, ttl } = overrides[i];
358
+ environment.storeSetTTLOverride(namespace, representationName, ttl);
359
+ }
360
+ }
361
+
362
+ /**
363
+ * Returns an empty InMemoryStore that can be used for ingestion. Copies over
364
+ * the TTLOverrides from the given Environment's Store.
365
+ */
366
+ function buildIngestStagingStore(environment) {
367
+ const store = new engine.InMemoryStore();
368
+ // need to make sure any TTL overrides are brought over from real L1
369
+ // because storePublishMetadata uses those overrides
370
+ store.ttlOverrides = environment.storeGetTTLOverrides();
371
+ store.defaultTTLOverride = environment.storeGetDefaultTTLOverride();
372
+ return store;
373
+ }
374
+
350
375
  const AdapterContextSegment = 'ADAPTER-CONTEXT';
351
376
  const ADAPTER_CONTEXT_ID_SUFFIX = '__NAMED_CONTEXT';
352
377
  function reviveOrCreateContext(adapterId, durableStore, durableStoreErrorHandler, onContextLoaded) {
@@ -403,20 +428,12 @@
403
428
  function makeDurable(environment, { durableStore, instrumentation }) {
404
429
  let ingestStagingStore = null;
405
430
  const durableTTLStore = new DurableTTLStore(durableStore);
406
- let isRevivingTTLOverrides;
407
- isRevivingTTLOverrides = new Promise((resolve) => {
408
- durableTTLStore.getDurableTTLOverrides().then((map) => {
409
- const { defaultTTL, overrides } = map;
410
- if (defaultTTL !== undefined) {
411
- environment.storeSetDefaultTTLOverride(defaultTTL.ttl);
412
- }
413
- for (let i = 0, len = overrides.length; i < len; i++) {
414
- const { namespace, representationName, ttl } = overrides[i];
415
- environment.storeSetTTLOverride(namespace, representationName, ttl);
416
- }
431
+ let initializationPromise = new Promise((resolve) => {
432
+ const finish = () => {
417
433
  resolve();
418
- isRevivingTTLOverrides = undefined;
419
- });
434
+ initializationPromise = undefined;
435
+ };
436
+ reviveTTLOverrides(durableTTLStore, environment).then(finish);
420
437
  });
421
438
  //instrumentation for durable store errors
422
439
  const durableStoreErrorHandler = handleDurableStoreRejection(instrumentation);
@@ -468,7 +485,7 @@
468
485
  const storePublish = function (key, data) {
469
486
  validateNotDisposed();
470
487
  if (ingestStagingStore === null) {
471
- ingestStagingStore = new engine.InMemoryStore();
488
+ ingestStagingStore = buildIngestStagingStore(environment);
472
489
  }
473
490
  ingestStagingStore.publish(key, data);
474
491
  // remove record from main luvio L1 cache while we are on the synchronous path
@@ -480,7 +497,7 @@
480
497
  const publishStoreMetadata = function (recordId, storeMetadata) {
481
498
  validateNotDisposed();
482
499
  if (ingestStagingStore === null) {
483
- ingestStagingStore = new engine.InMemoryStore();
500
+ ingestStagingStore = buildIngestStagingStore(environment);
484
501
  }
485
502
  ingestStagingStore.publishMetadata(recordId, storeMetadata);
486
503
  };
@@ -489,14 +506,14 @@
489
506
  // we don't ingest to the luvio L1 store from network directly, we ingest to
490
507
  // L2 and let DurableStore on change event revive keys into luvio L1 store
491
508
  if (ingestStagingStore === null) {
492
- ingestStagingStore = new engine.InMemoryStore();
509
+ ingestStagingStore = buildIngestStagingStore(environment);
493
510
  }
494
511
  environment.storeIngest(key, ingest, response, luvio, ingestStagingStore);
495
512
  };
496
513
  const storeIngestError = function (key, errorSnapshot, storeMetadataParams, _storeOverride) {
497
514
  validateNotDisposed();
498
515
  if (ingestStagingStore === null) {
499
- ingestStagingStore = new engine.InMemoryStore();
516
+ ingestStagingStore = buildIngestStagingStore(environment);
500
517
  }
501
518
  environment.storeIngestError(key, errorSnapshot, storeMetadataParams, ingestStagingStore);
502
519
  };
@@ -519,7 +536,8 @@
519
536
  validateNotDisposed();
520
537
  // if this lookup is right after an ingest there will be a staging store
521
538
  if (ingestStagingStore !== null) {
522
- return ingestStagingStore.lookup(sel, createSnapshot, refresh, ttlStrategy);
539
+ const reader = new engine.Reader(ingestStagingStore, sel.variables, refresh, undefined, ttlStrategy);
540
+ return reader.read(sel);
523
541
  }
524
542
  // otherwise this is from buildCachedSnapshot and we should use the luvio
525
543
  // L1 store
@@ -528,28 +546,28 @@
528
546
  const storeEvict = function (key) {
529
547
  validateNotDisposed();
530
548
  if (ingestStagingStore === null) {
531
- ingestStagingStore = new engine.InMemoryStore();
549
+ ingestStagingStore = buildIngestStagingStore(environment);
532
550
  }
533
551
  ingestStagingStore.evict(key);
534
552
  };
535
553
  const getNode = function (key) {
536
554
  validateNotDisposed();
537
555
  if (ingestStagingStore === null) {
538
- ingestStagingStore = new engine.InMemoryStore();
556
+ ingestStagingStore = buildIngestStagingStore(environment);
539
557
  }
540
558
  return environment.getNode(key, ingestStagingStore);
541
559
  };
542
560
  const wrapNormalizedGraphNode = function (normalized) {
543
561
  validateNotDisposed();
544
562
  if (ingestStagingStore === null) {
545
- ingestStagingStore = new engine.InMemoryStore();
563
+ ingestStagingStore = buildIngestStagingStore(environment);
546
564
  }
547
565
  return environment.wrapNormalizedGraphNode(normalized, ingestStagingStore);
548
566
  };
549
- const rebuildSnapshot = function (snapshot, records, storeMetadataMap, redirects, onAsyncRebuild) {
567
+ const rebuildSnapshot = function (snapshot, onAsyncRebuild) {
550
568
  validateNotDisposed();
551
569
  // try rebuilding from memory
552
- const rebuilt = environment.rebuildSnapshot(snapshot, records, storeMetadataMap, redirects, onAsyncRebuild);
570
+ const rebuilt = environment.rebuildSnapshot(snapshot, onAsyncRebuild);
553
571
  // only try reviving from durable store if snapshot is unfulfilled
554
572
  if (rebuilt.state !== 'Unfulfilled') {
555
573
  return rebuilt;
@@ -558,7 +576,7 @@
558
576
  reviveSnapshot(environment, durableStore, rebuilt, durableStoreErrorHandler, () =>
559
577
  // reviveSnapshot will revive into L1, and since "records" is a reference
560
578
  // (and not a copy) to the L1 records we can use it for rebuild
561
- environment.rebuildSnapshot(snapshot, records, storeMetadataMap, redirects, () => { })).then((result) => {
579
+ environment.rebuildSnapshot(snapshot, () => { })).then((result) => {
562
580
  onAsyncRebuild(result.snapshot);
563
581
  });
564
582
  // synchronously return the base snapshot as Pending if not already
@@ -610,16 +628,28 @@
610
628
  validateNotDisposed();
611
629
  return durableTTLStore.getDurableTTLOverrides();
612
630
  };
631
+ const dispatchResourceRequest = async function (request, context, eventObservers) {
632
+ validateNotDisposed();
633
+ // non-GET adapters call dispatchResourceRequest before any other luvio
634
+ // function so this is our chance to ensure we're initialized
635
+ if (initializationPromise !== undefined) {
636
+ await initializationPromise;
637
+ }
638
+ return environment.dispatchResourceRequest(request, context, eventObservers);
639
+ };
640
+ // NOTE: we can't use "async" keyword on this function because that would
641
+ // force it to always be an async response. The signature is a union
642
+ // of sync/async so no "awaiting" in this function, just promise-chaining
613
643
  const applyCachePolicy = function (luvio, adapterRequestContext, buildSnapshotContext, buildCachedSnapshot, buildNetworkSnapshot) {
614
644
  validateNotDisposed();
615
- const wrappedCacheLookup = (buildSnapshotContext, storeLookup) => {
616
- const snapshot = buildCachedSnapshot(buildSnapshotContext, storeLookup, luvio);
645
+ const wrappedCacheLookup = (injectedBuildSnapshotContext, injectedStoreLookup) => {
646
+ const snapshot = buildCachedSnapshot(injectedBuildSnapshotContext, injectedStoreLookup, luvio);
617
647
  // if the adapter attempted to do an L1 lookup and it was unfulfilled
618
648
  // then we can attempt an L2 lookup
619
649
  if (isUnfulfilledSnapshot(snapshot)) {
620
650
  const start = Date.now();
621
651
  emitDurableEnvironmentAdapterEvent({ type: 'l2-revive-start' }, adapterRequestContext.eventObservers);
622
- const revivedSnapshot = reviveSnapshot(environment, durableStore, snapshot, durableStoreErrorHandler, () => storeLookup(snapshot.select, snapshot.refresh)).then((result) => {
652
+ const revivedSnapshot = reviveSnapshot(environment, durableStore, snapshot, durableStoreErrorHandler, () => injectedStoreLookup(snapshot.select, snapshot.refresh)).then((result) => {
623
653
  emitDurableEnvironmentAdapterEvent({
624
654
  type: 'l2-revive-end',
625
655
  duration: Date.now() - start,
@@ -633,12 +663,14 @@
633
663
  // otherwise just return what buildCachedSnapshot gave us
634
664
  return snapshot;
635
665
  };
636
- const applyCachePolicy = () => {
666
+ const wrappedApplyCachePolicy = () => {
637
667
  return environment.applyCachePolicy(luvio, adapterRequestContext, buildSnapshotContext, wrappedCacheLookup, buildNetworkSnapshot);
638
668
  };
639
- return isRevivingTTLOverrides !== undefined
640
- ? isRevivingTTLOverrides.then(applyCachePolicy)
641
- : applyCachePolicy();
669
+ // GET adapters call applyCachePolicy before any other luvio
670
+ // function so this is our chance to ensure we're initialized
671
+ return initializationPromise !== undefined
672
+ ? initializationPromise.then(wrappedApplyCachePolicy)
673
+ : wrappedApplyCachePolicy();
642
674
  };
643
675
  const getIngestStagingStoreRecords = function () {
644
676
  validateNotDisposed();
@@ -670,7 +702,7 @@
670
702
  const toPrime = existingRecords !== undefined
671
703
  ? { ...revivedRecords, ...existingRecords }
672
704
  : revivedRecords;
673
- ingestStagingStore = new engine.InMemoryStore();
705
+ ingestStagingStore = buildIngestStagingStore(environment);
674
706
  ingestStagingStore.records = toPrime;
675
707
  const snapshotFromMemoryIngest = ingestAndBroadcastFunc();
676
708
  return publishChangesToDurableStore().then(() => {
@@ -740,6 +772,7 @@
740
772
  dispose: { value: dispose },
741
773
  publishChangesToDurableStore: { value: publishChangesToDurableStore },
742
774
  getDurableTTLOverrides: { value: getDurableTTLOverrides },
775
+ dispatchResourceRequest: { value: dispatchResourceRequest },
743
776
  applyCachePolicy: { value: applyCachePolicy },
744
777
  getIngestStagingStoreRecords: { value: getIngestStagingStoreRecords },
745
778
  getIngestStagingStoreMetadata: { value: getIngestStagingStoreMetadata },
@@ -0,0 +1,7 @@
1
+ import { InMemoryStore } from '@luvio/engine';
2
+ import type { Environment } from '@luvio/engine';
3
+ /**
4
+ * Returns an empty InMemoryStore that can be used for ingestion. Copies over
5
+ * the TTLOverrides from the given Environment's Store.
6
+ */
7
+ export declare function buildIngestStagingStore(environment: Environment): InMemoryStore;
@@ -0,0 +1,3 @@
1
+ import type { Environment } from '@luvio/engine';
2
+ import type { DurableTTLStore } from '../DurableTTLStore';
3
+ export declare function reviveTTLOverrides(ttlStore: DurableTTLStore, environment: Environment): Promise<void>;
@@ -1,5 +1,4 @@
1
- import type { CacheKeySet, Environment, RecordSource, Snapshot } from '@luvio/engine';
2
- import { InMemoryStore } from '@luvio/engine';
1
+ import type { CacheKeySet, Environment, RecordSource, Snapshot, InMemoryStore } from '@luvio/engine';
3
2
  import type { DurableStore } from './DurableStore';
4
3
  import type { InstrumentationFunction } from './makeDurable/error';
5
4
  import type { TTLOverridesMap } from './DurableTTLStore';
@@ -44,6 +44,44 @@
44
44
  return __assign.apply(this, arguments);
45
45
  };
46
46
 
47
+ function __awaiter(thisArg, _arguments, P, generator) {
48
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
49
+ return new (P || (P = Promise))(function (resolve, reject) {
50
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
51
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
52
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
53
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
54
+ });
55
+ }
56
+
57
+ function __generator(thisArg, body) {
58
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
59
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
60
+ function verb(n) { return function (v) { return step([n, v]); }; }
61
+ function step(op) {
62
+ if (f) throw new TypeError("Generator is already executing.");
63
+ while (_) try {
64
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
65
+ if (y = 0, t) op = [op[0] & 2, t.value];
66
+ switch (op[0]) {
67
+ case 0: case 1: t = op; break;
68
+ case 4: _.label++; return { value: op[1], done: false };
69
+ case 5: _.label++; y = op[1]; op = [0]; continue;
70
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
71
+ default:
72
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
73
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
74
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
75
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
76
+ if (t[2]) _.ops.pop();
77
+ _.trys.pop(); continue;
78
+ }
79
+ op = body.call(thisArg, _);
80
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
81
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
82
+ }
83
+ }
84
+
47
85
  function __spreadArray(to, from, pack) {
48
86
  if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
49
87
  if (ar || !(i in from)) {
@@ -390,6 +428,41 @@
390
428
  }, observers);
391
429
  }
392
430
 
431
+ function reviveTTLOverrides(ttlStore, environment) {
432
+ return __awaiter(this, void 0, void 0, function () {
433
+ var map, defaultTTL, overrides, i, len, _a, namespace, representationName, ttl;
434
+ return __generator(this, function (_b) {
435
+ switch (_b.label) {
436
+ case 0: return [4 /*yield*/, ttlStore.getDurableTTLOverrides()];
437
+ case 1:
438
+ map = _b.sent();
439
+ defaultTTL = map.defaultTTL, overrides = map.overrides;
440
+ if (defaultTTL !== undefined) {
441
+ environment.storeSetDefaultTTLOverride(defaultTTL.ttl);
442
+ }
443
+ for (i = 0, len = overrides.length; i < len; i++) {
444
+ _a = overrides[i], namespace = _a.namespace, representationName = _a.representationName, ttl = _a.ttl;
445
+ environment.storeSetTTLOverride(namespace, representationName, ttl);
446
+ }
447
+ return [2 /*return*/];
448
+ }
449
+ });
450
+ });
451
+ }
452
+
453
+ /**
454
+ * Returns an empty InMemoryStore that can be used for ingestion. Copies over
455
+ * the TTLOverrides from the given Environment's Store.
456
+ */
457
+ function buildIngestStagingStore(environment) {
458
+ var store = new engine.InMemoryStore();
459
+ // need to make sure any TTL overrides are brought over from real L1
460
+ // because storePublishMetadata uses those overrides
461
+ store.ttlOverrides = environment.storeGetTTLOverrides();
462
+ store.defaultTTLOverride = environment.storeGetDefaultTTLOverride();
463
+ return store;
464
+ }
465
+
393
466
  var AdapterContextSegment = 'ADAPTER-CONTEXT';
394
467
  var ADAPTER_CONTEXT_ID_SUFFIX = '__NAMED_CONTEXT';
395
468
  function reviveOrCreateContext(adapterId, durableStore, durableStoreErrorHandler, onContextLoaded) {
@@ -448,20 +521,12 @@
448
521
  var durableStore = _a.durableStore, instrumentation = _a.instrumentation;
449
522
  var ingestStagingStore = null;
450
523
  var durableTTLStore = new DurableTTLStore(durableStore);
451
- var isRevivingTTLOverrides;
452
- isRevivingTTLOverrides = new Promise(function (resolve) {
453
- durableTTLStore.getDurableTTLOverrides().then(function (map) {
454
- var defaultTTL = map.defaultTTL, overrides = map.overrides;
455
- if (defaultTTL !== undefined) {
456
- environment.storeSetDefaultTTLOverride(defaultTTL.ttl);
457
- }
458
- for (var i = 0, len = overrides.length; i < len; i++) {
459
- var _a = overrides[i], namespace = _a.namespace, representationName = _a.representationName, ttl = _a.ttl;
460
- environment.storeSetTTLOverride(namespace, representationName, ttl);
461
- }
524
+ var initializationPromise = new Promise(function (resolve) {
525
+ var finish = function () {
462
526
  resolve();
463
- isRevivingTTLOverrides = undefined;
464
- });
527
+ initializationPromise = undefined;
528
+ };
529
+ reviveTTLOverrides(durableTTLStore, environment).then(finish);
465
530
  });
466
531
  //instrumentation for durable store errors
467
532
  var durableStoreErrorHandler = handleDurableStoreRejection(instrumentation);
@@ -513,7 +578,7 @@
513
578
  var storePublish = function (key, data) {
514
579
  validateNotDisposed();
515
580
  if (ingestStagingStore === null) {
516
- ingestStagingStore = new engine.InMemoryStore();
581
+ ingestStagingStore = buildIngestStagingStore(environment);
517
582
  }
518
583
  ingestStagingStore.publish(key, data);
519
584
  // remove record from main luvio L1 cache while we are on the synchronous path
@@ -525,7 +590,7 @@
525
590
  var publishStoreMetadata = function (recordId, storeMetadata) {
526
591
  validateNotDisposed();
527
592
  if (ingestStagingStore === null) {
528
- ingestStagingStore = new engine.InMemoryStore();
593
+ ingestStagingStore = buildIngestStagingStore(environment);
529
594
  }
530
595
  ingestStagingStore.publishMetadata(recordId, storeMetadata);
531
596
  };
@@ -534,14 +599,14 @@
534
599
  // we don't ingest to the luvio L1 store from network directly, we ingest to
535
600
  // L2 and let DurableStore on change event revive keys into luvio L1 store
536
601
  if (ingestStagingStore === null) {
537
- ingestStagingStore = new engine.InMemoryStore();
602
+ ingestStagingStore = buildIngestStagingStore(environment);
538
603
  }
539
604
  environment.storeIngest(key, ingest, response, luvio, ingestStagingStore);
540
605
  };
541
606
  var storeIngestError = function (key, errorSnapshot, storeMetadataParams, _storeOverride) {
542
607
  validateNotDisposed();
543
608
  if (ingestStagingStore === null) {
544
- ingestStagingStore = new engine.InMemoryStore();
609
+ ingestStagingStore = buildIngestStagingStore(environment);
545
610
  }
546
611
  environment.storeIngestError(key, errorSnapshot, storeMetadataParams, ingestStagingStore);
547
612
  };
@@ -564,7 +629,8 @@
564
629
  validateNotDisposed();
565
630
  // if this lookup is right after an ingest there will be a staging store
566
631
  if (ingestStagingStore !== null) {
567
- return ingestStagingStore.lookup(sel, createSnapshot, refresh, ttlStrategy);
632
+ var reader = new engine.Reader(ingestStagingStore, sel.variables, refresh, undefined, ttlStrategy);
633
+ return reader.read(sel);
568
634
  }
569
635
  // otherwise this is from buildCachedSnapshot and we should use the luvio
570
636
  // L1 store
@@ -573,28 +639,28 @@
573
639
  var storeEvict = function (key) {
574
640
  validateNotDisposed();
575
641
  if (ingestStagingStore === null) {
576
- ingestStagingStore = new engine.InMemoryStore();
642
+ ingestStagingStore = buildIngestStagingStore(environment);
577
643
  }
578
644
  ingestStagingStore.evict(key);
579
645
  };
580
646
  var getNode = function (key) {
581
647
  validateNotDisposed();
582
648
  if (ingestStagingStore === null) {
583
- ingestStagingStore = new engine.InMemoryStore();
649
+ ingestStagingStore = buildIngestStagingStore(environment);
584
650
  }
585
651
  return environment.getNode(key, ingestStagingStore);
586
652
  };
587
653
  var wrapNormalizedGraphNode = function (normalized) {
588
654
  validateNotDisposed();
589
655
  if (ingestStagingStore === null) {
590
- ingestStagingStore = new engine.InMemoryStore();
656
+ ingestStagingStore = buildIngestStagingStore(environment);
591
657
  }
592
658
  return environment.wrapNormalizedGraphNode(normalized, ingestStagingStore);
593
659
  };
594
- var rebuildSnapshot = function (snapshot, records, storeMetadataMap, redirects, onAsyncRebuild) {
660
+ var rebuildSnapshot = function (snapshot, onAsyncRebuild) {
595
661
  validateNotDisposed();
596
662
  // try rebuilding from memory
597
- var rebuilt = environment.rebuildSnapshot(snapshot, records, storeMetadataMap, redirects, onAsyncRebuild);
663
+ var rebuilt = environment.rebuildSnapshot(snapshot, onAsyncRebuild);
598
664
  // only try reviving from durable store if snapshot is unfulfilled
599
665
  if (rebuilt.state !== 'Unfulfilled') {
600
666
  return rebuilt;
@@ -603,7 +669,7 @@
603
669
  reviveSnapshot(environment, durableStore, rebuilt, durableStoreErrorHandler, function () {
604
670
  // reviveSnapshot will revive into L1, and since "records" is a reference
605
671
  // (and not a copy) to the L1 records we can use it for rebuild
606
- return environment.rebuildSnapshot(snapshot, records, storeMetadataMap, redirects, function () { });
672
+ return environment.rebuildSnapshot(snapshot, function () { });
607
673
  }).then(function (result) {
608
674
  onAsyncRebuild(result.snapshot);
609
675
  });
@@ -653,16 +719,35 @@
653
719
  validateNotDisposed();
654
720
  return durableTTLStore.getDurableTTLOverrides();
655
721
  };
722
+ var dispatchResourceRequest = function (request, context, eventObservers) {
723
+ return __awaiter(this, void 0, void 0, function () {
724
+ return __generator(this, function (_a) {
725
+ switch (_a.label) {
726
+ case 0:
727
+ validateNotDisposed();
728
+ if (!(initializationPromise !== undefined)) return [3 /*break*/, 2];
729
+ return [4 /*yield*/, initializationPromise];
730
+ case 1:
731
+ _a.sent();
732
+ _a.label = 2;
733
+ case 2: return [2 /*return*/, environment.dispatchResourceRequest(request, context, eventObservers)];
734
+ }
735
+ });
736
+ });
737
+ };
738
+ // NOTE: we can't use "async" keyword on this function because that would
739
+ // force it to always be an async response. The signature is a union
740
+ // of sync/async so no "awaiting" in this function, just promise-chaining
656
741
  var applyCachePolicy = function (luvio, adapterRequestContext, buildSnapshotContext, buildCachedSnapshot, buildNetworkSnapshot) {
657
742
  validateNotDisposed();
658
- var wrappedCacheLookup = function (buildSnapshotContext, storeLookup) {
659
- var snapshot = buildCachedSnapshot(buildSnapshotContext, storeLookup, luvio);
743
+ var wrappedCacheLookup = function (injectedBuildSnapshotContext, injectedStoreLookup) {
744
+ var snapshot = buildCachedSnapshot(injectedBuildSnapshotContext, injectedStoreLookup, luvio);
660
745
  // if the adapter attempted to do an L1 lookup and it was unfulfilled
661
746
  // then we can attempt an L2 lookup
662
747
  if (isUnfulfilledSnapshot(snapshot)) {
663
748
  var start_1 = Date.now();
664
749
  emitDurableEnvironmentAdapterEvent({ type: 'l2-revive-start' }, adapterRequestContext.eventObservers);
665
- var revivedSnapshot = reviveSnapshot(environment, durableStore, snapshot, durableStoreErrorHandler, function () { return storeLookup(snapshot.select, snapshot.refresh); }).then(function (result) {
750
+ var revivedSnapshot = reviveSnapshot(environment, durableStore, snapshot, durableStoreErrorHandler, function () { return injectedStoreLookup(snapshot.select, snapshot.refresh); }).then(function (result) {
666
751
  emitDurableEnvironmentAdapterEvent({
667
752
  type: 'l2-revive-end',
668
753
  duration: Date.now() - start_1,
@@ -676,12 +761,14 @@
676
761
  // otherwise just return what buildCachedSnapshot gave us
677
762
  return snapshot;
678
763
  };
679
- var applyCachePolicy = function () {
764
+ var wrappedApplyCachePolicy = function () {
680
765
  return environment.applyCachePolicy(luvio, adapterRequestContext, buildSnapshotContext, wrappedCacheLookup, buildNetworkSnapshot);
681
766
  };
682
- return isRevivingTTLOverrides !== undefined
683
- ? isRevivingTTLOverrides.then(applyCachePolicy)
684
- : applyCachePolicy();
767
+ // GET adapters call applyCachePolicy before any other luvio
768
+ // function so this is our chance to ensure we're initialized
769
+ return initializationPromise !== undefined
770
+ ? initializationPromise.then(wrappedApplyCachePolicy)
771
+ : wrappedApplyCachePolicy();
685
772
  };
686
773
  var getIngestStagingStoreRecords = function () {
687
774
  validateNotDisposed();
@@ -712,7 +799,7 @@
712
799
  var ingestAndPublish = function (revivedRecords) {
713
800
  var toPrime = existingRecords !== undefined
714
801
  ? __assign(__assign({}, revivedRecords), existingRecords) : revivedRecords;
715
- ingestStagingStore = new engine.InMemoryStore();
802
+ ingestStagingStore = buildIngestStagingStore(environment);
716
803
  ingestStagingStore.records = toPrime;
717
804
  var snapshotFromMemoryIngest = ingestAndBroadcastFunc();
718
805
  return publishChangesToDurableStore().then(function () {
@@ -784,6 +871,7 @@
784
871
  dispose: { value: dispose },
785
872
  publishChangesToDurableStore: { value: publishChangesToDurableStore },
786
873
  getDurableTTLOverrides: { value: getDurableTTLOverrides },
874
+ dispatchResourceRequest: { value: dispatchResourceRequest },
787
875
  applyCachePolicy: { value: applyCachePolicy },
788
876
  getIngestStagingStoreRecords: { value: getIngestStagingStoreRecords },
789
877
  getIngestStagingStoreMetadata: { value: getIngestStagingStoreMetadata },
@@ -0,0 +1,7 @@
1
+ import { InMemoryStore } from '@luvio/engine';
2
+ import type { Environment } from '@luvio/engine';
3
+ /**
4
+ * Returns an empty InMemoryStore that can be used for ingestion. Copies over
5
+ * the TTLOverrides from the given Environment's Store.
6
+ */
7
+ export declare function buildIngestStagingStore(environment: Environment): InMemoryStore;
@@ -0,0 +1,3 @@
1
+ import type { Environment } from '@luvio/engine';
2
+ import type { DurableTTLStore } from '../DurableTTLStore';
3
+ export declare function reviveTTLOverrides(ttlStore: DurableTTLStore, environment: Environment): Promise<void>;
@@ -1,5 +1,4 @@
1
- import type { CacheKeySet, Environment, RecordSource, Snapshot } from '@luvio/engine';
2
- import { InMemoryStore } from '@luvio/engine';
1
+ import type { CacheKeySet, Environment, RecordSource, Snapshot, InMemoryStore } from '@luvio/engine';
3
2
  import type { DurableStore } from './DurableStore';
4
3
  import type { InstrumentationFunction } from './makeDurable/error';
5
4
  import type { TTLOverridesMap } from './DurableTTLStore';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luvio/environments",
3
- "version": "0.99.2",
3
+ "version": "0.102.1",
4
4
  "description": "Luvio Environments",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,7 +23,7 @@
23
23
  "watch": "yarn build --watch"
24
24
  },
25
25
  "dependencies": {
26
- "@luvio/engine": "0.99.2"
26
+ "@luvio/engine": "0.102.1"
27
27
  },
28
28
  "bundlesize": [
29
29
  {