cdk-nextjs 0.7.6 → 0.7.7
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/.jsii +3 -3
- package/.jsii.tabl.json +1 -1
- package/README.md +12 -3
- package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +31 -13
- package/docs/caching-guide.md +11 -1
- package/docs/harness-coverage.md +2 -1
- package/lib/adapter/aws-cache-store.d.ts +214 -3
- package/lib/adapter/aws-cache-store.js +470 -35
- package/lib/adapter/aws-cache-store.test.js +675 -3
- package/lib/adapter/cache-handler.mjs +421 -30
- package/lib/adapter/use-cache-common.d.ts +53 -1
- package/lib/adapter/use-cache-common.js +121 -14
- package/lib/adapter/use-cache-common.test.js +138 -1
- package/lib/adapter/use-cache-default-handler.js +36 -6
- package/lib/adapter/use-cache-default-handler.mjs +525 -42
- package/lib/adapter/use-cache-handlers.test.js +247 -7
- package/lib/adapter/use-cache-remote-handler.js +9 -7
- package/lib/adapter/use-cache-remote-handler.mjs +516 -40
- package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +2 -1
- package/lib/lambdas/post-deploy/prune-revalidation-table.js +35 -13
- package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +19 -1
- package/lib/nextjs-api.js +1 -1
- package/lib/nextjs-build/nextjs-build.js +1 -1
- package/lib/nextjs-cache.js +1 -1
- package/lib/nextjs-compute/nextjs-containers.js +1 -1
- package/lib/nextjs-compute/nextjs-functions.js +1 -1
- package/lib/nextjs-distribution.js +1 -1
- package/lib/nextjs-post-deploy.js +1 -1
- package/lib/nextjs-static-assets.js +1 -1
- package/lib/root-constructs/nextjs-base-construct.js +1 -1
- package/lib/root-constructs/nextjs-global-containers.js +1 -1
- package/lib/root-constructs/nextjs-global-functions.js +1 -1
- package/lib/root-constructs/nextjs-regional-containers.js +1 -1
- package/lib/root-constructs/nextjs-regional-functions.js +1 -1
- package/lib/runtime/core.js +18 -4
- package/lib/runtime/core.test.js +17 -1
- package/lib/runtime/lambda.mjs +16 -3
- package/lib/runtime/server.mjs +16 -3
- package/lib/runtime/tag-manifest.d.ts +15 -0
- package/lib/runtime/tag-manifest.js +24 -0
- package/lib/runtime/tag-manifest.test.d.ts +1 -0
- package/lib/runtime/tag-manifest.test.js +21 -0
- package/package.json +1 -1
|
@@ -46265,6 +46265,7 @@ var import_debug6 = __toESM(require_src());
|
|
|
46265
46265
|
// src/adapter/aws-cache-store.ts
|
|
46266
46266
|
var import_client_dynamodb = __toESM(require_dist_cjs20());
|
|
46267
46267
|
var import_client_s3 = __toESM(require_dist_cjs16());
|
|
46268
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
46268
46269
|
import { join as join5 } from "node:path";
|
|
46269
46270
|
|
|
46270
46271
|
// src/adapter/cache-utils.ts
|
|
@@ -46390,6 +46391,7 @@ function markerOf(item) {
|
|
|
46390
46391
|
}
|
|
46391
46392
|
var BATCH_GET_MAX_KEYS = 100;
|
|
46392
46393
|
var DEFAULT_TAG_REFRESH_MS = 1e3;
|
|
46394
|
+
var TAG_REFRESH_GRACE_MS = 1e3;
|
|
46393
46395
|
function hashedTag(tag) {
|
|
46394
46396
|
return `#${sha256Hex(tag)}`;
|
|
46395
46397
|
}
|
|
@@ -46603,10 +46605,64 @@ var TrackedTagMarkers = class {
|
|
|
46603
46605
|
* result rather than dropped.
|
|
46604
46606
|
*/
|
|
46605
46607
|
pendingRows = /* @__PURE__ */ new Map();
|
|
46608
|
+
/**
|
|
46609
|
+
* Log rows for tags not tracked and not being read, merged by tag, oldest
|
|
46610
|
+
* first: what the log has said about them since {@link completeSince}. Taken
|
|
46611
|
+
* into a tag's marker when it is read or written.
|
|
46612
|
+
*/
|
|
46613
|
+
logOnly = /* @__PURE__ */ new Map();
|
|
46614
|
+
/** See {@link completeSince}. */
|
|
46615
|
+
floor;
|
|
46616
|
+
/**
|
|
46617
|
+
* The future `expiredAt`s of markers dropped since, as `[from, to]`, in
|
|
46618
|
+
* order: once `from` is past, {@link completeSince} moves to `to`, and not
|
|
46619
|
+
* before, since only then does it expire anything. `from` and `to` are the
|
|
46620
|
+
* same until spans are merged for space ({@link laterFloor}).
|
|
46621
|
+
*/
|
|
46622
|
+
laterFloors = [];
|
|
46623
|
+
/** The in-memory entry stores judged by {@link completeSince}. */
|
|
46624
|
+
entryStores = [];
|
|
46625
|
+
/** How many times {@link forget} ran: a read started before one is made again. */
|
|
46626
|
+
forgotten = 0;
|
|
46606
46627
|
/** Tracked tags whose read failed, for the next refresh to read again. */
|
|
46607
46628
|
unread = /* @__PURE__ */ new Set();
|
|
46629
|
+
/**
|
|
46630
|
+
* Set inside a page render {@link catchUp} let go, for that render alone.
|
|
46631
|
+
* See {@link behindInRender}.
|
|
46632
|
+
*/
|
|
46633
|
+
caughtUpRender = new AsyncLocalStorage();
|
|
46634
|
+
/** When `sync` last scanned the entry stores ({@link oldestEntry}). */
|
|
46635
|
+
lastEntryScan = -Infinity;
|
|
46636
|
+
/**
|
|
46637
|
+
* No `logOnly` row is known by it or earlier, so a {@link pruneLogged}
|
|
46638
|
+
* against it or earlier drops nothing: a marker is only ever known by later,
|
|
46639
|
+
* as its `expiredAt` passes.
|
|
46640
|
+
*/
|
|
46641
|
+
prunedAgainst = -Infinity;
|
|
46642
|
+
/** When the last refresh started, or was skipped. */
|
|
46608
46643
|
lastRefresh = -Infinity;
|
|
46644
|
+
/**
|
|
46645
|
+
* The refresh in flight. One left open across a freeze comes back after the
|
|
46646
|
+
* thaw with what it read before, so {@link refresh} waits for it and then
|
|
46647
|
+
* for a fresh one, rather than the runtime waiting for it before the freeze:
|
|
46648
|
+
* that would bill every Lambda invocation for the query's tail.
|
|
46649
|
+
*/
|
|
46609
46650
|
refreshing;
|
|
46651
|
+
/**
|
|
46652
|
+
* When {@link refreshing} last showed the process running: a timer ticks
|
|
46653
|
+
* while it is in flight, and a tick that comes late, or none at all, means
|
|
46654
|
+
* the process was paused - frozen - since it started.
|
|
46655
|
+
*/
|
|
46656
|
+
lastTick = -Infinity;
|
|
46657
|
+
/** Whether a tick came late since {@link refreshing} started. */
|
|
46658
|
+
pausedWhileRefreshing = false;
|
|
46659
|
+
ticker;
|
|
46660
|
+
canFreeze;
|
|
46661
|
+
/**
|
|
46662
|
+
* When the last refresh settled, either way, unless it spanned a pause: what
|
|
46663
|
+
* it knows is from then. See {@link behind}.
|
|
46664
|
+
*/
|
|
46665
|
+
settledAt;
|
|
46610
46666
|
/**
|
|
46611
46667
|
* Where the next log query starts (`clock()`): the last successful one's
|
|
46612
46668
|
* start, less {@link REVALIDATION_LOG_LOOKBACK_MS}.
|
|
@@ -46628,20 +46684,68 @@ var TrackedTagMarkers = class {
|
|
|
46628
46684
|
this.random = options.random ?? Math.random;
|
|
46629
46685
|
this.debug = options.debug ?? (() => {
|
|
46630
46686
|
});
|
|
46687
|
+
this.canFreeze = options.canFreeze ?? false;
|
|
46631
46688
|
const at = this.clock();
|
|
46632
46689
|
this.cursor = at - REVALIDATION_LOG_LOOKBACK_MS;
|
|
46633
46690
|
this.lastLogRead = at;
|
|
46691
|
+
this.settledAt = at;
|
|
46692
|
+
this.floor = markerClock();
|
|
46634
46693
|
}
|
|
46635
46694
|
/** `tag`'s marker as this instance knows it, if it tracks `tag`. */
|
|
46636
46695
|
get(tag) {
|
|
46637
46696
|
return this.tags.get(tag);
|
|
46638
46697
|
}
|
|
46698
|
+
/**
|
|
46699
|
+
* Since when (`markerClock()`) this instance knows of every revalidation of
|
|
46700
|
+
* every tag, tracked or not: tracked ones from their markers and the log,
|
|
46701
|
+
* the others from the log alone (`logOnly`). So an entry created at or after
|
|
46702
|
+
* it can be judged by {@link state} and {@link expiration} without
|
|
46703
|
+
* {@link ensure} reading anything - which matters inside a `'use cache'`
|
|
46704
|
+
* lookup, where Next.js waits for the answer and a read pushes the entry out
|
|
46705
|
+
* of the static stage of a staged render.
|
|
46706
|
+
*
|
|
46707
|
+
* Starts at construction: the log is followed from before it. Moves to now
|
|
46708
|
+
* when the tracked markers are forgotten, and past the revalidations of
|
|
46709
|
+
* whatever else it lets go of - a marker evicted for space, a log row
|
|
46710
|
+
* pruned - which are no longer known: to its `expiredAt` only once that is
|
|
46711
|
+
* past, since a profile's `expire` can be a year out, and moving there at
|
|
46712
|
+
* once would turn the read-free path off for the instance's life.
|
|
46713
|
+
*
|
|
46714
|
+
* A row is pruned only once it is no later than every entry held, so that
|
|
46715
|
+
* costs those entries nothing. An entry stored afterwards with an older
|
|
46716
|
+
* `timestamp` - Next.js stamps the start of its generation, which can
|
|
46717
|
+
* outlast a lookback - is older than this too, and is read first.
|
|
46718
|
+
*
|
|
46719
|
+
* It does not cover a revalidation older than the log's first lookback
|
|
46720
|
+
* whose `expiredAt` is still to come, which would expire an entry created
|
|
46721
|
+
* after it. So the `'use cache'` handler reads an entry's tags in the
|
|
46722
|
+
* background as it stores it.
|
|
46723
|
+
*/
|
|
46724
|
+
get completeSince() {
|
|
46725
|
+
const at = markerClock();
|
|
46726
|
+
while (this.laterFloors.length > 0 && this.laterFloors[0][0] <= at) {
|
|
46727
|
+
this.floor = Math.max(this.floor, this.laterFloors.shift()[1]);
|
|
46728
|
+
}
|
|
46729
|
+
return this.floor;
|
|
46730
|
+
}
|
|
46731
|
+
/**
|
|
46732
|
+
* Register an in-memory store whose entries are judged by
|
|
46733
|
+
* {@link completeSince}, by the `timestamp` of the oldest entry it holds:
|
|
46734
|
+
* `logOnly` keeps the rows that could still apply to one of them, and no
|
|
46735
|
+
* others. With none registered it keeps nothing. Asked with `scan` false,
|
|
46736
|
+
* `oldestTimestamp` may answer early, but never late, without a scan.
|
|
46737
|
+
*/
|
|
46738
|
+
judgeEntriesOf(oldestTimestamp, holdsAny = () => oldestTimestamp(false) < Infinity) {
|
|
46739
|
+
this.entryStores.push({ oldestTimestamp, holdsAny });
|
|
46740
|
+
}
|
|
46639
46741
|
/**
|
|
46640
46742
|
* Track `tag` with `marker`: what this instance just wrote, which it knows
|
|
46641
46743
|
* without reading it back.
|
|
46642
46744
|
*/
|
|
46643
46745
|
set(tag, marker) {
|
|
46644
|
-
this.
|
|
46746
|
+
const logged = this.logOnly.get(tag);
|
|
46747
|
+
this.logOnly.delete(tag);
|
|
46748
|
+
this.remember(tag, mergeMarkers(marker, logged));
|
|
46645
46749
|
this.known(tag, this.clock());
|
|
46646
46750
|
}
|
|
46647
46751
|
/**
|
|
@@ -46694,27 +46798,103 @@ var TrackedTagMarkers = class {
|
|
|
46694
46798
|
const unread = [];
|
|
46695
46799
|
for (const tag of new Set(tags)) {
|
|
46696
46800
|
const inFlight = this.reading.get(tag);
|
|
46697
|
-
if (
|
|
46698
|
-
waits.push(inFlight);
|
|
46699
|
-
} else if (this.tags.has(tag)) {
|
|
46801
|
+
if (this.tags.has(tag)) {
|
|
46700
46802
|
this.touch(tag);
|
|
46803
|
+
} else if (inFlight) {
|
|
46804
|
+
waits.push(inFlight);
|
|
46701
46805
|
} else {
|
|
46702
46806
|
unread.push(tag);
|
|
46703
46807
|
}
|
|
46704
46808
|
}
|
|
46705
46809
|
if (unread.length > 0) {
|
|
46706
|
-
|
|
46707
|
-
for (const tag of unread) {
|
|
46708
|
-
this.reading.delete(tag);
|
|
46709
|
-
}
|
|
46710
|
-
});
|
|
46711
|
-
for (const tag of unread) {
|
|
46712
|
-
this.reading.set(tag, read);
|
|
46713
|
-
}
|
|
46714
|
-
waits.push(read);
|
|
46810
|
+
waits.push(this.startRead(unread));
|
|
46715
46811
|
}
|
|
46716
46812
|
await Promise.all(waits);
|
|
46717
46813
|
}
|
|
46814
|
+
/**
|
|
46815
|
+
* {@link readInto} `tags`, as the read of each that whoever needs one of
|
|
46816
|
+
* them next waits on ({@link reading}). Never rejects: a failed read leaves
|
|
46817
|
+
* the tags tracked.
|
|
46818
|
+
*/
|
|
46819
|
+
startRead(tags) {
|
|
46820
|
+
const read = this.readInto(tags).then(() => {
|
|
46821
|
+
for (const tag of tags) {
|
|
46822
|
+
this.reading.delete(tag);
|
|
46823
|
+
}
|
|
46824
|
+
});
|
|
46825
|
+
for (const tag of tags) {
|
|
46826
|
+
this.reading.set(tag, read);
|
|
46827
|
+
}
|
|
46828
|
+
return read;
|
|
46829
|
+
}
|
|
46830
|
+
/**
|
|
46831
|
+
* Whether the last refresh settled more than `refreshIntervalMs` plus
|
|
46832
|
+
* {@link TAG_REFRESH_GRACE_MS} ago - one that spanned a freeze counts from
|
|
46833
|
+
* when it started: after the instance sat idle or frozen - or always, with
|
|
46834
|
+
* a `refreshIntervalMs` of `0`. Answering from what it knows then could
|
|
46835
|
+
* serve an entry revalidated elsewhere since, however long ago that was, so
|
|
46836
|
+
* `refreshTags` waits for the refresh, and the runtime waits for it before
|
|
46837
|
+
* a page render starts ({@link catchUp}).
|
|
46838
|
+
*
|
|
46839
|
+
* From when it settled, not when it started, so a slow query the runtime
|
|
46840
|
+
* waited for before the render does not leave the instance behind inside
|
|
46841
|
+
* it. A failed one counts too, so one request does not wait for two: the
|
|
46842
|
+
* same "assume the entry is valid" a failed read answers with, until the
|
|
46843
|
+
* next refresh, at most the interval and the grace later.
|
|
46844
|
+
*/
|
|
46845
|
+
get behind() {
|
|
46846
|
+
return this.log !== void 0 && // `0` asks before every check, so every check waits for the answer.
|
|
46847
|
+
(this.refreshIntervalMs === 0 || this.overdue(this.settledAt));
|
|
46848
|
+
}
|
|
46849
|
+
/**
|
|
46850
|
+
* {@link behind}, as `refreshTags` asks it: never inside a page's render
|
|
46851
|
+
* {@link catchUp} caught up, since the runtime settled it for that request
|
|
46852
|
+
* before the render started, and a wait inside a `'use cache'` lookup is
|
|
46853
|
+
* what it settled it to avoid - a render crossing the line partway through
|
|
46854
|
+
* would otherwise wait after all. So a revalidation elsewhere can go unseen
|
|
46855
|
+
* for a render's duration on top of the usual window.
|
|
46856
|
+
*
|
|
46857
|
+
* A route handler, which no catch-up precedes, waits at the plain line.
|
|
46858
|
+
*/
|
|
46859
|
+
get behindInRender() {
|
|
46860
|
+
return this.refreshIntervalMs !== 0 && this.caughtUpRender.getStore() ? false : this.behind;
|
|
46861
|
+
}
|
|
46862
|
+
/**
|
|
46863
|
+
* Whether a registered store ({@link judgeEntriesOf}) holds any entry: one
|
|
46864
|
+
* a refresh could expire. With none there is nothing to wait for even when
|
|
46865
|
+
* the instance is {@link behind}, since whatever is stored from here on is
|
|
46866
|
+
* newer than what the log would say - which covers the first `'use cache'`
|
|
46867
|
+
* call of a process, which creates the handler inside the render.
|
|
46868
|
+
*/
|
|
46869
|
+
get holdsEntries() {
|
|
46870
|
+
return this.entryStores.some((store) => store.holdsAny());
|
|
46871
|
+
}
|
|
46872
|
+
/**
|
|
46873
|
+
* {@link refresh}, waited for when the instance is {@link behind}. The
|
|
46874
|
+
* runtime calls it before handing a page request to Next.js, outside the
|
|
46875
|
+
* staged render whose static stage a wait inside a `'use cache'` lookup
|
|
46876
|
+
* would cut short. Only for the `'use cache'` handler's entries
|
|
46877
|
+
* ({@link judgeEntriesOf}): the other caches wait for the refresh where they
|
|
46878
|
+
* read anyway. Not with a `refreshIntervalMs` of `0` either, where
|
|
46879
|
+
* `refreshTags` asks again regardless. Then `render`, marked as caught up
|
|
46880
|
+
* for ({@link behindInRender}). Rejects only as `render` does.
|
|
46881
|
+
*/
|
|
46882
|
+
async catchUp(render) {
|
|
46883
|
+
const log = (error2) => console.error("Error refreshing cache tags:", error2);
|
|
46884
|
+
if (this.refreshIntervalMs > 0 && this.behind) {
|
|
46885
|
+
if (!this.holdsEntries) {
|
|
46886
|
+
return render();
|
|
46887
|
+
}
|
|
46888
|
+
await this.refresh().catch(log);
|
|
46889
|
+
} else if (this.refreshIntervalMs > 0) {
|
|
46890
|
+
void this.refresh().catch(log);
|
|
46891
|
+
}
|
|
46892
|
+
return this.caughtUpRender.run(true, render);
|
|
46893
|
+
}
|
|
46894
|
+
/** Whether `at` is more than the interval and the grace ago. */
|
|
46895
|
+
overdue(at) {
|
|
46896
|
+
return this.clock() - at > this.refreshIntervalMs + TAG_REFRESH_GRACE_MS;
|
|
46897
|
+
}
|
|
46718
46898
|
/**
|
|
46719
46899
|
* Catch up on revalidations other instances ran, at most once per
|
|
46720
46900
|
* `refreshIntervalMs`. See {@link TrackedTagMarkers} for the cost.
|
|
@@ -46725,6 +46905,9 @@ var TrackedTagMarkers = class {
|
|
|
46725
46905
|
return;
|
|
46726
46906
|
}
|
|
46727
46907
|
if (this.refreshing) {
|
|
46908
|
+
if (this.behind && this.pausedSinceRefreshStarted()) {
|
|
46909
|
+
return this.refreshing.then(() => this.refresh());
|
|
46910
|
+
}
|
|
46728
46911
|
return this.refreshing;
|
|
46729
46912
|
}
|
|
46730
46913
|
const at = this.clock();
|
|
@@ -46732,14 +46915,47 @@ var TrackedTagMarkers = class {
|
|
|
46732
46915
|
return;
|
|
46733
46916
|
}
|
|
46734
46917
|
this.lastRefresh = at;
|
|
46735
|
-
if (this.tags.size === 0) {
|
|
46918
|
+
if (this.tags.size === 0 && this.entryStores.length === 0) {
|
|
46736
46919
|
return;
|
|
46737
46920
|
}
|
|
46921
|
+
this.startTicking();
|
|
46738
46922
|
this.refreshing = this.sync(at, log).finally(() => {
|
|
46923
|
+
this.settledAt = Math.max(
|
|
46924
|
+
this.settledAt,
|
|
46925
|
+
this.pausedSinceRefreshStarted() ? this.lastRefresh : this.clock()
|
|
46926
|
+
);
|
|
46927
|
+
this.stopTicking();
|
|
46739
46928
|
this.refreshing = void 0;
|
|
46740
46929
|
});
|
|
46741
46930
|
return this.refreshing;
|
|
46742
46931
|
}
|
|
46932
|
+
startTicking() {
|
|
46933
|
+
if (!this.canFreeze) {
|
|
46934
|
+
return;
|
|
46935
|
+
}
|
|
46936
|
+
this.lastTick = this.clock();
|
|
46937
|
+
this.pausedWhileRefreshing = false;
|
|
46938
|
+
this.ticker = setInterval(() => {
|
|
46939
|
+
const at = this.clock();
|
|
46940
|
+
if (at - this.lastTick > REFRESH_PAUSE_MS) {
|
|
46941
|
+
this.pausedWhileRefreshing = true;
|
|
46942
|
+
}
|
|
46943
|
+
this.lastTick = at;
|
|
46944
|
+
}, REFRESH_TICK_MS);
|
|
46945
|
+
this.ticker.unref?.();
|
|
46946
|
+
}
|
|
46947
|
+
stopTicking() {
|
|
46948
|
+
clearInterval(this.ticker);
|
|
46949
|
+
this.ticker = void 0;
|
|
46950
|
+
}
|
|
46951
|
+
/**
|
|
46952
|
+
* Whether the process was paused since {@link refreshing} started: a tick
|
|
46953
|
+
* came late, or the next one is overdue (after a thaw, a request can run
|
|
46954
|
+
* before the timer does).
|
|
46955
|
+
*/
|
|
46956
|
+
pausedSinceRefreshStarted() {
|
|
46957
|
+
return this.canFreeze && (this.pausedWhileRefreshing || this.clock() - this.lastTick > REFRESH_PAUSE_MS);
|
|
46958
|
+
}
|
|
46743
46959
|
/**
|
|
46744
46960
|
* Record a revalidation of `tags`: here at once, and in the revalidation
|
|
46745
46961
|
* table for every other instance - the marker row plus a log row per tag.
|
|
@@ -46772,7 +46988,7 @@ var TrackedTagMarkers = class {
|
|
|
46772
46988
|
const at = markerClock();
|
|
46773
46989
|
let state2 = "fresh";
|
|
46774
46990
|
for (const tag of tags) {
|
|
46775
|
-
const marker = this.
|
|
46991
|
+
const marker = this.knownMarker(tag);
|
|
46776
46992
|
if (!marker) {
|
|
46777
46993
|
continue;
|
|
46778
46994
|
}
|
|
@@ -46796,7 +47012,7 @@ var TrackedTagMarkers = class {
|
|
|
46796
47012
|
const at = markerClock();
|
|
46797
47013
|
let latest = 0;
|
|
46798
47014
|
for (const tag of tags) {
|
|
46799
|
-
const marker = this.
|
|
47015
|
+
const marker = this.knownMarker(tag);
|
|
46800
47016
|
if (!marker) {
|
|
46801
47017
|
continue;
|
|
46802
47018
|
}
|
|
@@ -46883,13 +47099,14 @@ var TrackedTagMarkers = class {
|
|
|
46883
47099
|
);
|
|
46884
47100
|
return;
|
|
46885
47101
|
}
|
|
46886
|
-
const
|
|
46887
|
-
|
|
46888
|
-
|
|
46889
|
-
|
|
46890
|
-
|
|
46891
|
-
|
|
46892
|
-
|
|
47102
|
+
const due = this.due(at);
|
|
47103
|
+
if (due.length > 0) {
|
|
47104
|
+
void this.startRead(due);
|
|
47105
|
+
}
|
|
47106
|
+
const result = await log.query(this.cursor).catch((error2) => {
|
|
47107
|
+
console.error("Error reading tag revalidation log:", error2);
|
|
47108
|
+
return void 0;
|
|
47109
|
+
});
|
|
46893
47110
|
if (!result) {
|
|
46894
47111
|
return;
|
|
46895
47112
|
}
|
|
@@ -46900,6 +47117,11 @@ var TrackedTagMarkers = class {
|
|
|
46900
47117
|
);
|
|
46901
47118
|
return;
|
|
46902
47119
|
}
|
|
47120
|
+
const scan = at - this.lastEntryScan > ENTRY_SCAN_INTERVAL_MS;
|
|
47121
|
+
if (scan) {
|
|
47122
|
+
this.lastEntryScan = at;
|
|
47123
|
+
}
|
|
47124
|
+
const oldest = this.oldestEntry(scan);
|
|
46903
47125
|
let applied = 0;
|
|
46904
47126
|
for (const row of result.rows) {
|
|
46905
47127
|
if (this.applied.has(row.sk)) {
|
|
@@ -46914,11 +47136,20 @@ var TrackedTagMarkers = class {
|
|
|
46914
47136
|
mergeMarkers(this.pendingRows.get(row.tag), row.marker)
|
|
46915
47137
|
);
|
|
46916
47138
|
} else {
|
|
47139
|
+
this.rememberLogged(
|
|
47140
|
+
row.tag,
|
|
47141
|
+
mergeMarkers(this.logOnly.get(row.tag), row.marker),
|
|
47142
|
+
oldest
|
|
47143
|
+
);
|
|
46917
47144
|
continue;
|
|
46918
47145
|
}
|
|
46919
47146
|
this.applied.set(row.sk, row.at);
|
|
46920
47147
|
applied++;
|
|
46921
47148
|
}
|
|
47149
|
+
if (oldest > this.prunedAgainst) {
|
|
47150
|
+
this.pruneLogged(oldest);
|
|
47151
|
+
}
|
|
47152
|
+
this.prunedAgainst = oldest;
|
|
46922
47153
|
this.lastLogRead = at;
|
|
46923
47154
|
this.advance(at - REVALIDATION_LOG_LOOKBACK_MS);
|
|
46924
47155
|
this.debug(
|
|
@@ -46934,14 +47165,16 @@ var TrackedTagMarkers = class {
|
|
|
46934
47165
|
const due = [];
|
|
46935
47166
|
for (const tag of this.unread) {
|
|
46936
47167
|
if (due.length >= BATCH_GET_MAX_KEYS) return due;
|
|
46937
|
-
|
|
47168
|
+
if (!this.reading.has(tag)) {
|
|
47169
|
+
due.push(tag);
|
|
47170
|
+
}
|
|
46938
47171
|
}
|
|
46939
47172
|
const jitter = this.resyncIntervalMs * TAG_RESYNC_JITTER;
|
|
46940
47173
|
for (const [tag, dueAt] of this.dueAt) {
|
|
46941
47174
|
if (due.length >= BATCH_GET_MAX_KEYS || dueAt - jitter > at) {
|
|
46942
47175
|
break;
|
|
46943
47176
|
}
|
|
46944
|
-
if (dueAt <= at && !this.unread.has(tag)) {
|
|
47177
|
+
if (dueAt <= at && !this.unread.has(tag) && !this.reading.has(tag)) {
|
|
46945
47178
|
due.push(tag);
|
|
46946
47179
|
}
|
|
46947
47180
|
}
|
|
@@ -46954,10 +47187,19 @@ var TrackedTagMarkers = class {
|
|
|
46954
47187
|
*/
|
|
46955
47188
|
forget(at, why) {
|
|
46956
47189
|
this.debug(`forgetting ${this.tags.size} tracked tags: ${why}`);
|
|
47190
|
+
this.forgotten++;
|
|
47191
|
+
for (const marker of this.tags.values()) {
|
|
47192
|
+
this.raiseFloor(marker);
|
|
47193
|
+
}
|
|
47194
|
+
for (const marker of this.logOnly.values()) {
|
|
47195
|
+
this.raiseFloor(marker);
|
|
47196
|
+
}
|
|
46957
47197
|
this.tags.clear();
|
|
46958
47198
|
this.dueAt.clear();
|
|
46959
47199
|
this.unread.clear();
|
|
46960
47200
|
this.applied.clear();
|
|
47201
|
+
this.logOnly.clear();
|
|
47202
|
+
this.floor = Math.max(this.floor, markerClock());
|
|
46961
47203
|
this.cursor = at - REVALIDATION_LOG_LOOKBACK_MS;
|
|
46962
47204
|
this.lastLogRead = at;
|
|
46963
47205
|
}
|
|
@@ -46983,13 +47225,17 @@ var TrackedTagMarkers = class {
|
|
|
46983
47225
|
* always answered with, rather than a read on every request while DynamoDB
|
|
46984
47226
|
* is unavailable.
|
|
46985
47227
|
*/
|
|
46986
|
-
async readInto(tags) {
|
|
47228
|
+
async readInto(tags, again = false) {
|
|
46987
47229
|
if (tags.length === 0) {
|
|
46988
47230
|
return true;
|
|
46989
47231
|
}
|
|
46990
47232
|
const at = this.clock();
|
|
47233
|
+
const forgotten = this.forgotten;
|
|
46991
47234
|
try {
|
|
46992
47235
|
const read = await this.markers.read(tags);
|
|
47236
|
+
if (this.forgotten !== forgotten && !again) {
|
|
47237
|
+
return await this.readInto(tags, true);
|
|
47238
|
+
}
|
|
46993
47239
|
for (const tag of tags) {
|
|
46994
47240
|
this.unread.delete(tag);
|
|
46995
47241
|
this.remember(
|
|
@@ -47005,6 +47251,9 @@ var TrackedTagMarkers = class {
|
|
|
47005
47251
|
return true;
|
|
47006
47252
|
} catch (error2) {
|
|
47007
47253
|
console.error("Error reading tag markers:", error2);
|
|
47254
|
+
if (this.forgotten !== forgotten && !again) {
|
|
47255
|
+
return this.readInto(tags, true);
|
|
47256
|
+
}
|
|
47008
47257
|
this.trackUnread(tags);
|
|
47009
47258
|
for (const tag of tags) {
|
|
47010
47259
|
this.unread.add(tag);
|
|
@@ -47018,8 +47267,119 @@ var TrackedTagMarkers = class {
|
|
|
47018
47267
|
}
|
|
47019
47268
|
takePendingRows(tag) {
|
|
47020
47269
|
const pending = this.pendingRows.get(tag);
|
|
47270
|
+
const logged = this.logOnly.get(tag);
|
|
47021
47271
|
this.pendingRows.delete(tag);
|
|
47022
|
-
|
|
47272
|
+
this.logOnly.delete(tag);
|
|
47273
|
+
return logged ? mergeMarkers(logged, pending) : pending;
|
|
47274
|
+
}
|
|
47275
|
+
/**
|
|
47276
|
+
* What this instance knows of `tag`: tracked, or from the log alone -
|
|
47277
|
+
* including rows that arrived while its first read is in flight.
|
|
47278
|
+
*/
|
|
47279
|
+
knownMarker(tag) {
|
|
47280
|
+
const tracked = this.tags.get(tag);
|
|
47281
|
+
if (tracked) {
|
|
47282
|
+
return tracked;
|
|
47283
|
+
}
|
|
47284
|
+
const logged = this.logOnly.get(tag);
|
|
47285
|
+
const pending = this.pendingRows.get(tag);
|
|
47286
|
+
return logged || pending ? mergeMarkers(logged, pending) : void 0;
|
|
47287
|
+
}
|
|
47288
|
+
/**
|
|
47289
|
+
* Keep `tag`'s log rows in `logOnly`, unless they cannot apply to an entry
|
|
47290
|
+
* held, `oldest` or newer (see {@link pruneLogged}), as bounded as the
|
|
47291
|
+
* tracked tags. Either way a row let go of takes what it knew with it, so
|
|
47292
|
+
* `completeSince` moves past it.
|
|
47293
|
+
*/
|
|
47294
|
+
rememberLogged(tag, marker, oldest) {
|
|
47295
|
+
this.logOnly.delete(tag);
|
|
47296
|
+
if (knownBy(marker, markerClock()) <= oldest) {
|
|
47297
|
+
this.raiseFloor(marker);
|
|
47298
|
+
return;
|
|
47299
|
+
}
|
|
47300
|
+
this.logOnly.set(tag, marker);
|
|
47301
|
+
for (const [first, dropped] of this.logOnly) {
|
|
47302
|
+
if (this.logOnly.size <= this.maxTrackedTags) {
|
|
47303
|
+
break;
|
|
47304
|
+
}
|
|
47305
|
+
this.logOnly.delete(first);
|
|
47306
|
+
this.raiseFloor(dropped);
|
|
47307
|
+
}
|
|
47308
|
+
}
|
|
47309
|
+
/**
|
|
47310
|
+
* Drop the `logOnly` rows that cannot apply to an entry held, `oldest` or
|
|
47311
|
+
* newer: every revalidation they name so far is no later than it. That
|
|
47312
|
+
* moves `completeSince` no further than `oldest`, which costs the entries
|
|
47313
|
+
* held nothing, and a profile's `expiredAt` still to come waits in
|
|
47314
|
+
* `laterFloors`. Without this, a deployment revalidating many distinct tags
|
|
47315
|
+
* filled `logOnly` with tags no entry here carries, and the evictions past
|
|
47316
|
+
* its bound kept moving `completeSince` up to the present.
|
|
47317
|
+
*/
|
|
47318
|
+
pruneLogged(oldest) {
|
|
47319
|
+
const at = markerClock();
|
|
47320
|
+
for (const [tag, marker] of this.logOnly) {
|
|
47321
|
+
if (knownBy(marker, at) <= oldest) {
|
|
47322
|
+
this.logOnly.delete(tag);
|
|
47323
|
+
this.raiseFloor(marker);
|
|
47324
|
+
}
|
|
47325
|
+
}
|
|
47326
|
+
}
|
|
47327
|
+
/**
|
|
47328
|
+
* The oldest entry timestamp of any registered store, `Infinity` with none:
|
|
47329
|
+
* early, never late, unless `scan`.
|
|
47330
|
+
*/
|
|
47331
|
+
oldestEntry(scan) {
|
|
47332
|
+
let oldest = Infinity;
|
|
47333
|
+
for (const { oldestTimestamp } of this.entryStores) {
|
|
47334
|
+
oldest = Math.min(oldest, oldestTimestamp(scan));
|
|
47335
|
+
}
|
|
47336
|
+
return oldest;
|
|
47337
|
+
}
|
|
47338
|
+
/**
|
|
47339
|
+
* Move `completeSince` past `marker`'s revalidations: what is no longer
|
|
47340
|
+
* known about a tag once its marker is dropped. A future `expiredAt` waits
|
|
47341
|
+
* in `laterFloors` until it is past.
|
|
47342
|
+
*/
|
|
47343
|
+
raiseFloor(marker) {
|
|
47344
|
+
const at = markerClock();
|
|
47345
|
+
this.floor = Math.max(this.floor, knownBy(marker, at));
|
|
47346
|
+
const { expiredAt } = marker;
|
|
47347
|
+
if (expiredAt !== void 0 && expiredAt > Math.max(at, this.floor)) {
|
|
47348
|
+
this.laterFloor(expiredAt);
|
|
47349
|
+
}
|
|
47350
|
+
}
|
|
47351
|
+
/**
|
|
47352
|
+
* Add `time` to `laterFloors`, in order. Past the tracked-tag bound the two
|
|
47353
|
+
* spans closest together are merged: from the first's start,
|
|
47354
|
+
* `completeSince` is the second's end, early - which only costs reads, and
|
|
47355
|
+
* for as short a time as any merge allows. Never later than its time, which
|
|
47356
|
+
* would let an entry expire unseen.
|
|
47357
|
+
*/
|
|
47358
|
+
laterFloor(time2) {
|
|
47359
|
+
const floors = this.laterFloors;
|
|
47360
|
+
let low = 0;
|
|
47361
|
+
let high = floors.length;
|
|
47362
|
+
while (low < high) {
|
|
47363
|
+
const mid = Math.floor((low + high) / 2);
|
|
47364
|
+
if (floors[mid][0] < time2) {
|
|
47365
|
+
low = mid + 1;
|
|
47366
|
+
} else {
|
|
47367
|
+
high = mid;
|
|
47368
|
+
}
|
|
47369
|
+
}
|
|
47370
|
+
if (low > 0 && floors[low - 1][1] >= time2 || floors[low]?.[0] === time2) {
|
|
47371
|
+
return;
|
|
47372
|
+
}
|
|
47373
|
+
floors.splice(low, 0, [time2, time2]);
|
|
47374
|
+
if (floors.length > this.maxTrackedTags) {
|
|
47375
|
+
let merge2 = 0;
|
|
47376
|
+
for (let i5 = 1; i5 < floors.length - 1; i5++) {
|
|
47377
|
+
if (floors[i5 + 1][1] - floors[i5][0] < floors[merge2 + 1][1] - floors[merge2][0]) {
|
|
47378
|
+
merge2 = i5;
|
|
47379
|
+
}
|
|
47380
|
+
}
|
|
47381
|
+
floors.splice(merge2, 2, [floors[merge2][0], floors[merge2 + 1][1]]);
|
|
47382
|
+
}
|
|
47023
47383
|
}
|
|
47024
47384
|
/** Record that `tag`'s marker was known from the table at `at`. */
|
|
47025
47385
|
known(tag, at) {
|
|
@@ -47036,6 +47396,7 @@ var TrackedTagMarkers = class {
|
|
|
47036
47396
|
if (this.tags.size <= this.maxTrackedTags) {
|
|
47037
47397
|
break;
|
|
47038
47398
|
}
|
|
47399
|
+
this.raiseFloor(this.tags.get(oldest));
|
|
47039
47400
|
this.tags.delete(oldest);
|
|
47040
47401
|
this.dueAt.delete(oldest);
|
|
47041
47402
|
this.unread.delete(oldest);
|
|
@@ -47048,7 +47409,18 @@ var TrackedTagMarkers = class {
|
|
|
47048
47409
|
}
|
|
47049
47410
|
}
|
|
47050
47411
|
};
|
|
47412
|
+
function knownBy(marker, at) {
|
|
47413
|
+
const { revalidatedAt, staleAt, expiredAt } = marker;
|
|
47414
|
+
return Math.max(
|
|
47415
|
+
revalidatedAt ?? -Infinity,
|
|
47416
|
+
staleAt ?? -Infinity,
|
|
47417
|
+
expiredAt !== void 0 && expiredAt <= at ? expiredAt : -Infinity
|
|
47418
|
+
);
|
|
47419
|
+
}
|
|
47051
47420
|
var MAX_LOG_PUT_MS = REVALIDATION_LOG_LOOKBACK_MS / 2;
|
|
47421
|
+
var ENTRY_SCAN_INTERVAL_MS = 6e4;
|
|
47422
|
+
var REFRESH_TICK_MS = 250;
|
|
47423
|
+
var REFRESH_PAUSE_MS = 1e3;
|
|
47052
47424
|
function mergeMarkers(local, remote) {
|
|
47053
47425
|
if (!local) {
|
|
47054
47426
|
return remote ?? {};
|
|
@@ -47111,6 +47483,13 @@ var CacheBucket = class {
|
|
|
47111
47483
|
// src/adapter/use-cache-common.ts
|
|
47112
47484
|
var import_client_dynamodb2 = __toESM(require_dist_cjs20());
|
|
47113
47485
|
var import_debug5 = __toESM(require_src());
|
|
47486
|
+
|
|
47487
|
+
// src/runtime/tag-manifest.ts
|
|
47488
|
+
var TAG_MANIFEST_SYMBOL = /* @__PURE__ */ Symbol.for(
|
|
47489
|
+
"cdk-nextjs.use-cache.tag-manifest"
|
|
47490
|
+
);
|
|
47491
|
+
|
|
47492
|
+
// src/adapter/use-cache-common.ts
|
|
47114
47493
|
function isBuildPhase() {
|
|
47115
47494
|
return process.env.NEXT_PHASE === "phase-production-build";
|
|
47116
47495
|
}
|
|
@@ -47191,6 +47570,12 @@ var EntryLru = class {
|
|
|
47191
47570
|
maxBytes;
|
|
47192
47571
|
entries = /* @__PURE__ */ new Map();
|
|
47193
47572
|
bytes = 0;
|
|
47573
|
+
/**
|
|
47574
|
+
* No later than the oldest entry's `timestamp`: the last scan's answer, less
|
|
47575
|
+
* whatever was set since. Entries dropped since only make it early. See
|
|
47576
|
+
* {@link oldestBound}.
|
|
47577
|
+
*/
|
|
47578
|
+
lowest = Infinity;
|
|
47194
47579
|
get(key) {
|
|
47195
47580
|
const entry = this.entries.get(key);
|
|
47196
47581
|
if (entry) {
|
|
@@ -47207,6 +47592,7 @@ var EntryLru = class {
|
|
|
47207
47592
|
}
|
|
47208
47593
|
this.entries.set(key, entry);
|
|
47209
47594
|
this.bytes += size;
|
|
47595
|
+
this.lowest = Math.min(this.lowest, entry.timestamp);
|
|
47210
47596
|
for (const [oldestKey, oldest] of this.entries) {
|
|
47211
47597
|
if (this.bytes <= this.maxBytes) {
|
|
47212
47598
|
break;
|
|
@@ -47220,8 +47606,59 @@ var EntryLru = class {
|
|
|
47220
47606
|
if (existing) {
|
|
47221
47607
|
this.entries.delete(key);
|
|
47222
47608
|
this.bytes -= sizeOf2(key, existing);
|
|
47609
|
+
if (this.entries.size === 0) {
|
|
47610
|
+
this.lowest = Infinity;
|
|
47611
|
+
}
|
|
47223
47612
|
}
|
|
47224
47613
|
}
|
|
47614
|
+
/**
|
|
47615
|
+
* The `timestamp` of the oldest entry held, `Infinity` with none, dropping
|
|
47616
|
+
* on the way the entries past `revalidate` at `at` (`now()`): a handler
|
|
47617
|
+
* that drops them when next read would otherwise hold them until then, and
|
|
47618
|
+
* they would count here meanwhile. A scan, so asked once in a while: in
|
|
47619
|
+
* between, {@link oldestBound} answers.
|
|
47620
|
+
*/
|
|
47621
|
+
oldestTimestamp(at = -Infinity) {
|
|
47622
|
+
let oldest = Infinity;
|
|
47623
|
+
for (const [key, entry] of this.entries) {
|
|
47624
|
+
if (isPastRevalidate(entry, at)) {
|
|
47625
|
+
this.delete(key);
|
|
47626
|
+
} else {
|
|
47627
|
+
oldest = Math.min(oldest, entry.timestamp);
|
|
47628
|
+
}
|
|
47629
|
+
}
|
|
47630
|
+
this.lowest = oldest;
|
|
47631
|
+
return oldest;
|
|
47632
|
+
}
|
|
47633
|
+
/**
|
|
47634
|
+
* No later than {@link oldestTimestamp}, without its scan: as of the last
|
|
47635
|
+
* one, less the entries set since. `Infinity` with none held. Drops the
|
|
47636
|
+
* entries past `revalidate` at `at` from the least recently used end, up to
|
|
47637
|
+
* the first that isn't, so {@link holdsLive} doesn't walk past them on every
|
|
47638
|
+
* request until the next scan.
|
|
47639
|
+
*/
|
|
47640
|
+
oldestBound(at = -Infinity) {
|
|
47641
|
+
for (const [key, entry] of this.entries) {
|
|
47642
|
+
if (!isPastRevalidate(entry, at)) {
|
|
47643
|
+
break;
|
|
47644
|
+
}
|
|
47645
|
+
this.delete(key);
|
|
47646
|
+
}
|
|
47647
|
+
return this.entries.size === 0 ? Infinity : this.lowest;
|
|
47648
|
+
}
|
|
47649
|
+
/**
|
|
47650
|
+
* Whether an entry not past `revalidate` at `at` is held. Usually the first
|
|
47651
|
+
* entry answers; the expired ones it passes are dropped by the scan
|
|
47652
|
+
* {@link oldestTimestamp} makes, not here, so asking changes nothing.
|
|
47653
|
+
*/
|
|
47654
|
+
holdsLive(at) {
|
|
47655
|
+
for (const entry of this.entries.values()) {
|
|
47656
|
+
if (!isPastRevalidate(entry, at)) {
|
|
47657
|
+
return true;
|
|
47658
|
+
}
|
|
47659
|
+
}
|
|
47660
|
+
return false;
|
|
47661
|
+
}
|
|
47225
47662
|
get size() {
|
|
47226
47663
|
return this.entries.size;
|
|
47227
47664
|
}
|
|
@@ -47229,14 +47666,39 @@ var EntryLru = class {
|
|
|
47229
47666
|
function sizeOf2(key, entry) {
|
|
47230
47667
|
return entry.value.byteLength + key.length;
|
|
47231
47668
|
}
|
|
47669
|
+
function isPastRevalidate(stored, at) {
|
|
47670
|
+
return at > stored.timestamp + stored.revalidate * 1e3;
|
|
47671
|
+
}
|
|
47232
47672
|
var DEFAULT_MEMORY_BYTES = 50 * 1024 * 1024;
|
|
47233
|
-
|
|
47673
|
+
var TAG_TABLE_REQUEST_TIMEOUT_MS = 3e3;
|
|
47674
|
+
async function awaitIf(wait, work, failure) {
|
|
47675
|
+
const logged = work.catch((error2) => {
|
|
47676
|
+
console.error(failure, error2);
|
|
47677
|
+
});
|
|
47678
|
+
if (wait) {
|
|
47679
|
+
await logged;
|
|
47680
|
+
}
|
|
47681
|
+
}
|
|
47682
|
+
function tagMethods(tags, options = {}) {
|
|
47234
47683
|
return {
|
|
47235
|
-
|
|
47236
|
-
|
|
47237
|
-
|
|
47238
|
-
|
|
47239
|
-
|
|
47684
|
+
// Started, not awaited, while the instance keeps up, unless `blocking`.
|
|
47685
|
+
// Next.js awaits `refreshTags` inside the first `'use cache'` lookup of a
|
|
47686
|
+
// request (`use-cache-wrapper`), and a staged render ends its static stage
|
|
47687
|
+
// on a timer: a log `Query` there pushed the entry out of the static
|
|
47688
|
+
// stage, so a cached navigation stored the page segment without it. What
|
|
47689
|
+
// the query finds applies from the next request. Awaited once the instance
|
|
47690
|
+
// is `behind`, which the runtime settles before a page render starts
|
|
47691
|
+
// (`catchUp`): the first request after an idle or frozen spell would
|
|
47692
|
+
// otherwise serve whatever was revalidated elsewhere meanwhile. A page's
|
|
47693
|
+
// render just after `catchUp` gets a grace more (`behindInRender`), so a
|
|
47694
|
+
// request that came in just short of the line doesn't cross it inside
|
|
47695
|
+
// the render. Not even then while the instance holds no entry the query
|
|
47696
|
+
// could expire (`holdsEntries`), with a `refreshIntervalMs` of `0` too.
|
|
47697
|
+
refreshTags: () => awaitIf(
|
|
47698
|
+
options.blocking === true || tags.behindInRender && tags.holdsEntries,
|
|
47699
|
+
tags.refresh(),
|
|
47700
|
+
"Error refreshing cache tags:"
|
|
47701
|
+
),
|
|
47240
47702
|
async updateTags(revalidatedTags, durations) {
|
|
47241
47703
|
await tags.update(revalidatedTags, durations);
|
|
47242
47704
|
}
|
|
@@ -47253,7 +47715,6 @@ function lazyHandler(create) {
|
|
|
47253
47715
|
updateTags: (tags, durations) => instance().updateTags(tags, durations)
|
|
47254
47716
|
};
|
|
47255
47717
|
}
|
|
47256
|
-
var TAG_MANIFEST_SYMBOL = /* @__PURE__ */ Symbol.for("cdk-nextjs.use-cache.tag-manifest");
|
|
47257
47718
|
function sharedTagManifest() {
|
|
47258
47719
|
const global = globalThis;
|
|
47259
47720
|
if (!global[TAG_MANIFEST_SYMBOL]) {
|
|
@@ -47263,12 +47724,24 @@ function sharedTagManifest() {
|
|
|
47263
47724
|
DEFAULT_TAG_REFRESH_MS
|
|
47264
47725
|
);
|
|
47265
47726
|
if (config.tableName && !isBuildPhase()) {
|
|
47266
|
-
const client = new import_client_dynamodb2.DynamoDBClient({
|
|
47727
|
+
const client = new import_client_dynamodb2.DynamoDBClient({
|
|
47728
|
+
region: config.region,
|
|
47729
|
+
// Without `throwOnRequestTimeout` the timeout only logs a warning. It
|
|
47730
|
+
// ends once the response headers arrive: `socketTimeout`, an
|
|
47731
|
+
// inactivity timer kept until the request closes, covers the body.
|
|
47732
|
+
requestHandler: {
|
|
47733
|
+
requestTimeout: TAG_TABLE_REQUEST_TIMEOUT_MS,
|
|
47734
|
+
throwOnRequestTimeout: true,
|
|
47735
|
+
socketTimeout: TAG_TABLE_REQUEST_TIMEOUT_MS
|
|
47736
|
+
}
|
|
47737
|
+
});
|
|
47267
47738
|
global[TAG_MANIFEST_SYMBOL] = new TrackedTagMarkers({
|
|
47268
47739
|
markers: new TagMarkerTable(client, config.tableName, config.buildId),
|
|
47269
47740
|
log: new RevalidationLog(client, config.tableName, config.buildId),
|
|
47270
47741
|
refreshIntervalMs,
|
|
47271
|
-
debug: (0, import_debug5.default)("cdk-nextjs:cache-handler:tags")
|
|
47742
|
+
debug: (0, import_debug5.default)("cdk-nextjs:cache-handler:tags"),
|
|
47743
|
+
// Set in every Lambda runtime; a container is never frozen.
|
|
47744
|
+
canFreeze: process.env.AWS_LAMBDA_FUNCTION_NAME !== void 0
|
|
47272
47745
|
});
|
|
47273
47746
|
} else {
|
|
47274
47747
|
if (!isBuildPhase()) {
|
|
@@ -47298,9 +47771,6 @@ function bucketFromEnv() {
|
|
|
47298
47771
|
}
|
|
47299
47772
|
return new CacheBucket(new import_client_s32.S3Client({ region }), bucketName);
|
|
47300
47773
|
}
|
|
47301
|
-
function isPastRevalidate(stored, at) {
|
|
47302
|
-
return at > stored.timestamp + stored.revalidate * 1e3;
|
|
47303
|
-
}
|
|
47304
47774
|
function isPastExpire(stored, at) {
|
|
47305
47775
|
return at > stored.timestamp + stored.expire * 1e3;
|
|
47306
47776
|
}
|
|
@@ -47420,7 +47890,13 @@ function createRemoteUseCacheHandler(options = {}) {
|
|
|
47420
47890
|
done();
|
|
47421
47891
|
await writeToS3(cacheKey, stored);
|
|
47422
47892
|
},
|
|
47423
|
-
|
|
47893
|
+
// Waits for the log query on every request: an entry read from S3 may
|
|
47894
|
+
// predate this instance, so what the query says applies to it at once.
|
|
47895
|
+
...tagMethods(tags, { blocking: true }),
|
|
47896
|
+
async getExpiration(implicitTags) {
|
|
47897
|
+
await tags.ensure(implicitTags);
|
|
47898
|
+
return tags.expiration(implicitTags);
|
|
47899
|
+
}
|
|
47424
47900
|
};
|
|
47425
47901
|
}
|
|
47426
47902
|
var use_cache_remote_handler_default = lazyHandler(() => createRemoteUseCacheHandler());
|