@rangojs/router 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/types/browser/cookie-name.d.ts +6 -0
- package/dist/types/browser/event-controller.d.ts +3 -3
- package/dist/types/browser/history-state.d.ts +18 -0
- package/dist/types/browser/navigation-transaction.d.ts +20 -2
- package/dist/types/browser/partial-update.d.ts +16 -1
- package/dist/types/browser/prefetch/cache.d.ts +6 -6
- package/dist/types/browser/react/Link.d.ts +19 -9
- package/dist/types/browser/react/context.d.ts +2 -2
- package/dist/types/browser/react/location-state-shared.d.ts +95 -56
- package/dist/types/browser/react/location-state.d.ts +1 -1
- package/dist/types/browser/transition-when.d.ts +80 -0
- package/dist/types/browser/types.d.ts +104 -9
- package/dist/types/build/generate-manifest.d.ts +8 -0
- package/dist/types/cache/background-task.d.ts +24 -2
- package/dist/types/cache/cache-exec-scope.d.ts +31 -0
- package/dist/types/cache/cache-key-utils.d.ts +48 -2
- package/dist/types/cache/cache-policy.d.ts +18 -1
- package/dist/types/cache/cache-runtime.d.ts +7 -0
- package/dist/types/cache/cache-scope.d.ts +192 -26
- package/dist/types/cache/cache-tag.d.ts +116 -11
- package/dist/types/cache/cf/cf-base64.d.ts +6 -0
- package/dist/types/cache/cf/cf-cache-constants.d.ts +11 -0
- package/dist/types/cache/cf/cf-cache-store.d.ts +224 -72
- package/dist/types/cache/cf/cf-cache-types.d.ts +31 -4
- package/dist/types/cache/cf/cf-shell-frame.d.ts +95 -0
- package/dist/types/cache/cf/cf-tag-marker-memo.d.ts +19 -0
- package/dist/types/cache/document-cache.d.ts +10 -0
- package/dist/types/cache/handle-snapshot.d.ts +41 -8
- package/dist/types/cache/index.d.ts +1 -0
- package/dist/types/cache/invalidation-order.d.ts +23 -0
- package/dist/types/cache/isolate-tag-memo.d.ts +149 -0
- package/dist/types/cache/request-tag-mask.d.ts +54 -0
- package/dist/types/cache/shell-memo.d.ts +178 -0
- package/dist/types/cache/shell-snapshot.d.ts +141 -105
- package/dist/types/cache/tag-invalidation.d.ts +54 -3
- package/dist/types/cache/types.d.ts +267 -96
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +123 -18
- package/dist/types/client-urls/navigation.d.ts +28 -2
- package/dist/types/client-urls/server-projection.d.ts +5 -2
- package/dist/types/client-urls/types.d.ts +5 -5
- package/dist/types/client.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.rsc.d.ts +1 -1
- package/dist/types/prerender/build-shell-capture.d.ts +11 -4
- package/dist/types/route-definition/helpers-types.d.ts +11 -11
- package/dist/types/route-name.d.ts +7 -0
- package/dist/types/router/error-handling.d.ts +1 -1
- package/dist/types/router/instrument.d.ts +8 -0
- package/dist/types/router/intercept-resolution.d.ts +2 -0
- package/dist/types/router/match-context.d.ts +5 -0
- package/dist/types/router/match-middleware/background-revalidation.d.ts +0 -4
- package/dist/types/router/middleware-types.d.ts +6 -1
- package/dist/types/router/router-options.d.ts +4 -1
- package/dist/types/router/segment-resolution/loader-cache.d.ts +58 -12
- package/dist/types/router/segment-resolution/loader-mask.d.ts +3 -4
- package/dist/types/router/segment-resolution/loader-snapshot.d.ts +33 -48
- package/dist/types/router/segment-resolution/mask-nested.d.ts +73 -24
- package/dist/types/router/segment-resolution/view-transition-default.d.ts +7 -5
- package/dist/types/router/transition-when.d.ts +24 -10
- package/dist/types/rsc/attach-transition-when.d.ts +18 -0
- package/dist/types/rsc/full-payload.d.ts +21 -0
- package/dist/types/rsc/handler.d.ts +1 -1
- package/dist/types/rsc/response-cache-serve.d.ts +15 -12
- package/dist/types/rsc/shell-build-manifest.d.ts +12 -3
- package/dist/types/rsc/shell-capture-constants.d.ts +116 -12
- package/dist/types/rsc/shell-capture.d.ts +202 -74
- package/dist/types/rsc/shell-serve.d.ts +144 -50
- package/dist/types/rsc/types.d.ts +9 -0
- package/dist/types/segment-system.d.ts +7 -0
- package/dist/types/server/context.d.ts +155 -33
- package/dist/types/server/cookie-store.d.ts +33 -0
- package/dist/types/server/handle-store.d.ts +52 -1
- package/dist/types/server/request-context.d.ts +210 -63
- package/dist/types/server/request-headers.d.ts +44 -0
- package/dist/types/server.d.ts +1 -0
- package/dist/types/ssr/index.d.ts +9 -0
- package/dist/types/ssr/ssr-root.d.ts +9 -8
- package/dist/types/testing/e2e/index.d.ts +1 -1
- package/dist/types/testing/flight.entry.d.ts +7 -0
- package/dist/types/testing/index.d.ts +3 -2
- package/dist/types/testing/internal/action-id.d.ts +7 -0
- package/dist/types/testing/location-state-key.d.ts +24 -0
- package/dist/types/testing/render-route.d.ts +17 -1
- package/dist/types/testing/run-loader.d.ts +18 -3
- package/dist/types/testing/run-transition-when.d.ts +44 -69
- package/dist/types/testing/serve-shell-request.d.ts +133 -0
- package/dist/types/testing/shell-status.d.ts +44 -19
- package/dist/types/transition-when-ref.d.ts +79 -0
- package/dist/types/types/cache-types.d.ts +15 -3
- package/dist/types/types/handler-context.d.ts +14 -1
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/segments.d.ts +86 -71
- package/dist/types/urls/path-helper-types.d.ts +3 -4
- package/dist/types/urls/pattern-types.d.ts +21 -18
- package/dist/types/vite/plugins/transition-when-hoist.d.ts +45 -0
- package/dist/types/vite/router-discovery.d.ts +29 -2
- package/dist/vite/index.js +1005 -105
- package/package.json +1 -1
- package/skills/breadcrumbs/SKILL.md +17 -7
- package/skills/cache-guide/SKILL.md +175 -76
- package/skills/caching/SKILL.md +361 -33
- package/skills/catalog.json +1 -1
- package/skills/client-urls/SKILL.md +12 -7
- package/skills/cloudflare/SKILL.md +15 -0
- package/skills/comparison/references/framework-comparison.md +52 -37
- package/skills/defer-hydration/SKILL.md +50 -30
- package/skills/deployment-caching/SKILL.md +5 -2
- package/skills/document-cache/SKILL.md +32 -2
- package/skills/handler-use/SKILL.md +2 -0
- package/skills/hooks/SKILL.md +3 -1
- package/skills/hooks/handle-and-actions.md +3 -1
- package/skills/hooks/navigation.md +23 -2
- package/skills/hooks/state.md +101 -7
- package/skills/intercept/SKILL.md +29 -12
- package/skills/loader/SKILL.md +197 -44
- package/skills/middleware/SKILL.md +34 -9
- package/skills/migrate-nextjs/SKILL.md +68 -37
- package/skills/migrate-react-router/SKILL.md +2 -1
- package/skills/migrate-react-router/component-migration.md +3 -1
- package/skills/migrate-react-router/data-and-actions.md +3 -1
- package/skills/migrate-react-router/route-mapping.md +7 -4
- package/skills/observability/SKILL.md +65 -0
- package/skills/parallel/SKILL.md +13 -8
- package/skills/ppr/SKILL.md +715 -371
- package/skills/prerender/SKILL.md +30 -17
- package/skills/rango/SKILL.md +72 -34
- package/skills/route/SKILL.md +14 -7
- package/skills/router-setup/SKILL.md +4 -2
- package/skills/scripts/SKILL.md +8 -1
- package/skills/server-actions/SKILL.md +11 -0
- package/skills/shell-manifest/SKILL.md +21 -12
- package/skills/testing/SKILL.md +49 -43
- package/skills/testing/cache-prerender.md +15 -14
- package/skills/testing/client-components.md +45 -3
- package/skills/testing/loader.md +19 -1
- package/skills/testing/middleware.md +1 -0
- package/skills/testing/predicates.md +49 -49
- package/skills/testing/render-handler.md +1 -0
- package/skills/testing/serve-shell-request.md +202 -0
- package/skills/testing/server-actions.md +9 -3
- package/skills/theme/SKILL.md +56 -4
- package/skills/typesafety/env-and-bindings.md +18 -2
- package/skills/use-cache/SKILL.md +91 -23
- package/skills/vercel/SKILL.md +14 -2
- package/skills/view-transitions/SKILL.md +150 -29
- package/src/__augment-tests__/augmented.check.ts +23 -0
- package/src/browser/cookie-name.ts +23 -0
- package/src/browser/event-controller.ts +4 -4
- package/src/browser/history-state.ts +75 -1
- package/src/browser/link-interceptor.ts +4 -0
- package/src/browser/navigation-bridge.ts +77 -18
- package/src/browser/navigation-client.ts +4 -3
- package/src/browser/navigation-store.ts +43 -1
- package/src/browser/navigation-transaction.ts +31 -11
- package/src/browser/partial-update.ts +146 -35
- package/src/browser/prefetch/cache.ts +6 -6
- package/src/browser/prefetch/fetch.ts +2 -2
- package/src/browser/react/Link.tsx +38 -33
- package/src/browser/react/NavigationProvider.tsx +2 -2
- package/src/browser/react/context.ts +2 -2
- package/src/browser/react/location-state-shared.ts +241 -49
- package/src/browser/react/location-state.ts +5 -2
- package/src/browser/rsc-router.tsx +9 -0
- package/src/browser/server-action-bridge.ts +84 -15
- package/src/browser/transition-when.ts +205 -0
- package/src/browser/types.ts +124 -10
- package/src/build/generate-manifest.ts +77 -1
- package/src/cache/background-task.ts +55 -2
- package/src/cache/cache-exec-scope.ts +48 -1
- package/src/cache/cache-key-utils.ts +62 -2
- package/src/cache/cache-policy.ts +31 -4
- package/src/cache/cache-runtime.ts +209 -129
- package/src/cache/cache-scope.ts +573 -69
- package/src/cache/cache-tag.ts +475 -19
- package/src/cache/cf/cf-base64.ts +36 -4
- package/src/cache/cf/cf-cache-constants.ts +12 -0
- package/src/cache/cf/cf-cache-store.ts +1094 -376
- package/src/cache/cf/cf-cache-types.ts +32 -4
- package/src/cache/cf/cf-shell-frame.ts +258 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +55 -40
- package/src/cache/document-cache.ts +53 -7
- package/src/cache/handle-snapshot.ts +53 -9
- package/src/cache/index.ts +2 -0
- package/src/cache/invalidation-order.ts +84 -0
- package/src/cache/isolate-tag-memo.ts +308 -0
- package/src/cache/request-tag-mask.ts +147 -0
- package/src/cache/shell-memo.ts +341 -0
- package/src/cache/shell-snapshot.ts +249 -277
- package/src/cache/tag-invalidation.ts +109 -18
- package/src/cache/types.ts +274 -102
- package/src/cache/vercel/vercel-cache-store.ts +561 -74
- package/src/client-urls/client-root.tsx +8 -4
- package/src/client-urls/client-urls.ts +8 -6
- package/src/client-urls/navigation.ts +55 -4
- package/src/client-urls/server-projection.ts +31 -10
- package/src/client-urls/types.ts +12 -5
- package/src/client.tsx +2 -0
- package/src/host/cookie-handler.ts +2 -1
- package/src/index.rsc.ts +3 -0
- package/src/index.ts +3 -0
- package/src/loader-redirect.tsx +7 -3
- package/src/prerender/build-shell-capture.ts +173 -110
- package/src/route-definition/dsl-helpers.ts +6 -3
- package/src/route-definition/helpers-types.ts +11 -11
- package/src/route-name.ts +12 -0
- package/src/router/content-negotiation.ts +4 -1
- package/src/router/error-handling.ts +5 -2
- package/src/router/handler-context.ts +42 -5
- package/src/router/instrument.ts +54 -2
- package/src/router/intercept-resolution.ts +30 -8
- package/src/router/loader-resolution.ts +89 -33
- package/src/router/logging.ts +5 -3
- package/src/router/match-api.ts +89 -42
- package/src/router/match-context.ts +5 -0
- package/src/router/match-handlers.ts +14 -29
- package/src/router/match-middleware/background-revalidation.ts +3 -5
- package/src/router/match-middleware/cache-lookup.ts +52 -19
- package/src/router/match-middleware/cache-store.ts +36 -10
- package/src/router/match-result.ts +1 -0
- package/src/router/middleware-types.ts +6 -1
- package/src/router/middleware.ts +20 -4
- package/src/router/navigation-snapshot.ts +6 -5
- package/src/router/prerender-match.ts +10 -0
- package/src/router/request-classification.ts +7 -4
- package/src/router/router-options.ts +4 -1
- package/src/router/segment-resolution/fresh.ts +18 -13
- package/src/router/segment-resolution/helpers.ts +4 -2
- package/src/router/segment-resolution/loader-cache.ts +366 -70
- package/src/router/segment-resolution/loader-mask.ts +3 -4
- package/src/router/segment-resolution/loader-snapshot.ts +215 -126
- package/src/router/segment-resolution/mask-nested.ts +161 -42
- package/src/router/segment-resolution/revalidation.ts +27 -13
- package/src/router/segment-resolution/view-transition-default.ts +6 -21
- package/src/router/telemetry.ts +6 -3
- package/src/router/transition-when.ts +34 -52
- package/src/router.ts +2 -1
- package/src/rsc/attach-transition-when.ts +47 -0
- package/src/rsc/full-payload.ts +47 -3
- package/src/rsc/handler.ts +24 -10
- package/src/rsc/loader-fetch.ts +2 -1
- package/src/rsc/manifest-init.ts +4 -0
- package/src/rsc/origin-guard.ts +8 -5
- package/src/rsc/progressive-enhancement.ts +10 -32
- package/src/rsc/response-cache-serve.ts +69 -78
- package/src/rsc/response-route-handler.ts +2 -2
- package/src/rsc/rsc-rendering.ts +712 -338
- package/src/rsc/server-action.ts +8 -20
- package/src/rsc/shell-build-manifest.ts +49 -29
- package/src/rsc/shell-capture-constants.ts +182 -12
- package/src/rsc/shell-capture.ts +1126 -612
- package/src/rsc/shell-serve.ts +331 -85
- package/src/rsc/ssr-setup.ts +3 -2
- package/src/rsc/types.ts +9 -0
- package/src/segment-system.tsx +40 -7
- package/src/server/context.ts +328 -72
- package/src/server/cookie-store.ts +184 -133
- package/src/server/handle-store.ts +245 -27
- package/src/server/request-context.ts +364 -100
- package/src/server/request-headers.ts +134 -0
- package/src/server.ts +4 -0
- package/src/ssr/index.tsx +96 -37
- package/src/ssr/ssr-root.tsx +9 -8
- package/src/testing/dispatch.ts +4 -7
- package/src/testing/e2e/index.ts +1 -0
- package/src/testing/flight.entry.ts +14 -0
- package/src/testing/index.ts +5 -0
- package/src/testing/internal/action-id.ts +25 -0
- package/src/testing/internal/context.ts +1 -1
- package/src/testing/location-state-key.ts +45 -0
- package/src/testing/render-handler.ts +1 -1
- package/src/testing/render-route.tsx +109 -16
- package/src/testing/run-client-revalidate.ts +3 -19
- package/src/testing/run-loader.ts +67 -5
- package/src/testing/run-transition-when.ts +109 -172
- package/src/testing/serve-shell-request.ts +381 -0
- package/src/testing/shell-status.ts +73 -47
- package/src/theme/ThemeProvider.tsx +7 -6
- package/src/transition-when-ref.ts +220 -0
- package/src/types/cache-types.ts +15 -3
- package/src/types/handler-context.ts +14 -1
- package/src/types/index.ts +3 -0
- package/src/types/segments.ts +94 -91
- package/src/urls/path-helper-types.ts +3 -4
- package/src/urls/pattern-types.ts +21 -18
- package/src/vite/discovery/discover-routers.ts +3 -0
- package/src/vite/discovery/shell-prerender-phase.ts +9 -2
- package/src/vite/discovery/virtual-module-codegen.ts +16 -6
- package/src/vite/plugins/transition-when-hoist.ts +1064 -0
- package/src/vite/rango.ts +2 -0
- package/src/vite/router-discovery.ts +89 -9
- package/dist/types/rsc/transition-gate.d.ts +0 -23
- package/src/rsc/transition-gate.ts +0 -86
|
@@ -44,21 +44,54 @@ export declare function decodeHandleValue<T>(encoded: string): Promise<T | null>
|
|
|
44
44
|
export declare function captureHandles(segments: ResolvedSegment[], handleStore: HandleStore): Record<string, SegmentHandleData>;
|
|
45
45
|
/** The owners of captureHandles' values; undefined when none is owned. */
|
|
46
46
|
export declare function captureHandleOwners(segments: ResolvedSegment[], handleStore: HandleStore): HandleOwners | undefined;
|
|
47
|
+
/** How restoreHandles delivers a record's loader-owned values. */
|
|
48
|
+
export interface OwnedPushDelivery {
|
|
49
|
+
/**
|
|
50
|
+
* Asked once per owner delivered through pushReplayed
|
|
51
|
+
* (setupLoaderAccess _claimLoaderPushes); an owner it refuses is skipped.
|
|
52
|
+
*/
|
|
53
|
+
claim?: (loaderId: string) => boolean;
|
|
54
|
+
/**
|
|
55
|
+
* A PPR shell's record (capture, document HIT tail, navigation replay): the
|
|
56
|
+
* loaders the route runs on the live lane (liveLaneLoaderIds), marked on
|
|
57
|
+
* the store (HandleStore.markLiveLane). A hole's values are replayed
|
|
58
|
+
* unclaimed, so its own cache() HIT redelivers its entry's pushes in their
|
|
59
|
+
* place (HandleStore.redeliverReplays), and its run ending without a push
|
|
60
|
+
* drops them (HandleStore.settleLoaderRun).
|
|
61
|
+
*/
|
|
62
|
+
liveLane?: ReadonlySet<string>;
|
|
63
|
+
/**
|
|
64
|
+
* A document HIT tail: every owner outside `liveLane` goes through
|
|
65
|
+
* pushRestored and stands, unclaimed.
|
|
66
|
+
*/
|
|
67
|
+
restore?: boolean;
|
|
68
|
+
}
|
|
47
69
|
/**
|
|
48
70
|
* Restore handle data from a cached snapshot into the handle store.
|
|
49
71
|
* Used when serving cached segments to replay their handle data: a route
|
|
50
72
|
* cache() record owns its segments' arrays, so it REPLACES them.
|
|
51
73
|
*
|
|
52
74
|
* A segment with `owners` is replaced with empty arrays and re-pushed in
|
|
53
|
-
* recorded order, an owned value through pushReplayed: the owning loader
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* loader's own cache() HIT does not replay its pushes a second
|
|
58
|
-
* (loader-cache.ts replayLoaderHandles)
|
|
59
|
-
*
|
|
75
|
+
* recorded order, an owned value through pushReplayed: if the owning loader
|
|
76
|
+
* runs (a client navigation replaying a ppr route's cache() record runs its
|
|
77
|
+
* `ssr: false` loaders), its live pushes replace the recorded ones in place
|
|
78
|
+
* instead of appending a second copy. `owned.claim` is asked once per
|
|
79
|
+
* owner, so the loader's own cache() HIT does not replay its pushes a second
|
|
80
|
+
* time (loader-cache.ts replayLoaderHandles). A record without owners
|
|
81
|
+
* restores as a plain replay.
|
|
82
|
+
*
|
|
83
|
+
* `owned.restore`: a document HIT tail restoring the shell's doc record
|
|
84
|
+
* (withCacheLookup). A bake-lane owner's values are the prelude's, so they go
|
|
85
|
+
* through pushRestored and stand: a run of that loader on the HIT (a
|
|
86
|
+
* promise-carrying `ssr: false` loader, one whose record asks for a run)
|
|
87
|
+
* reads the store, and its settled pushes are dropped, not swapped in.
|
|
88
|
+
* Nothing is claimed, so the loader's own cache() HIT still replays the
|
|
89
|
+
* pushes the record could not keep (the thenable ones pushRestored lets
|
|
90
|
+
* through). A loader the route also runs on the live lane is a hole: its
|
|
91
|
+
* values keep pushReplayed, unclaimed, and its live run replaces them
|
|
92
|
+
* (#936), even inside a restored loader's body (`owned.liveLane`).
|
|
60
93
|
*/
|
|
61
|
-
export declare function restoreHandles(handles: Record<string, SegmentHandleData>, handleStore: HandleStore, owners?: HandleOwners,
|
|
94
|
+
export declare function restoreHandles(handles: Record<string, SegmentHandleData>, handleStore: HandleStore, owners?: HandleOwners, owned?: OwnedPushDelivery): void;
|
|
62
95
|
/**
|
|
63
96
|
* Append recorded handle pushes to the store, in recorded order, via push()
|
|
64
97
|
* so active captures and loader-scope tagging see them like live pushes. For
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export type { SegmentCacheStore, CachedEntryData, CacheGetResult, CacheItemResult, CacheItemOptions, ShellCacheEntry, SerializedSegmentData, SegmentHandleData, CacheReadError, } from "./types.js";
|
|
2
2
|
export { CACHE_READ_ERROR } from "./types.js";
|
|
3
3
|
export { MemorySegmentCacheStore } from "./memory-segment-store.js";
|
|
4
|
+
export type { StoreMemoOptions } from "./shell-memo.js";
|
|
4
5
|
export { CFCacheStore, type CFCacheStoreOptions, type CFCacheDebug, type CFCacheReadDebugEvent, type KVNamespace, CACHE_STALE_AT_HEADER, CACHE_STATUS_HEADER, CACHE_REVALIDATING_AT_HEADER, EDGE_LOOKUP_TIMEOUT_MS, EDGE_READ_TIMEOUT_MS, KV_READ_TIMEOUT_MS, createCloudflareZonePurge, type CloudflareZonePurgeOptions, } from "./cf/index.js";
|
|
5
6
|
export { VercelCacheStore, type VercelCacheStoreOptions, type VercelRuntimeCache, type VercelCacheDebug, type VercelCacheReadDebugEvent, type VercelCacheReadOutcome, VERCEL_MAX_ITEM_BYTES, VERCEL_MAX_TAGS_PER_ITEM, VERCEL_MAX_TAG_BYTES, } from "./vercel/index.js";
|
|
6
7
|
export { TRACKING_SEARCH_PARAMS, type CacheSearchParams, } from "./search-params-filter.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a cache execution ("use cache", a loader's own cache(), a route
|
|
3
|
+
* cache() render, a request's document) started: its position in this
|
|
4
|
+
* isolate's order, and the store clock for invalidations this isolate did
|
|
5
|
+
* not see.
|
|
6
|
+
*/
|
|
7
|
+
export interface ExecutionStart {
|
|
8
|
+
readonly seq: number;
|
|
9
|
+
readonly at: number;
|
|
10
|
+
}
|
|
11
|
+
/** Record an execution's start, before it reads its data. */
|
|
12
|
+
export declare function executionStart(): ExecutionStart;
|
|
13
|
+
/**
|
|
14
|
+
* Whether this isolate invalidated any of `tags` after `since` (the `seq` of
|
|
15
|
+
* an ExecutionStart), in any request: the execution's value may predate the
|
|
16
|
+
* invalidation, so it is neither joined nor written (#973, #977).
|
|
17
|
+
*/
|
|
18
|
+
export declare function invalidatedSince(tags: readonly string[] | undefined, since: number): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Record an invalidation of `tags` in this isolate's order
|
|
21
|
+
* (updateTag()/revalidateTag(), before any store sees it).
|
|
22
|
+
*/
|
|
23
|
+
export declare function markInvalidated(tags: readonly string[]): void;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-isolate tag-marker memos shared by the built-in stores (issue #941;
|
|
3
|
+
* docs/design/shell-entry-layout.md "The tag-marker memo").
|
|
4
|
+
*
|
|
5
|
+
* A tagged shell HIT waits for its tag-invalidation markers before the first
|
|
6
|
+
* byte. Two things here shorten that wait:
|
|
7
|
+
*
|
|
8
|
+
* - {@link TagNameHints}: which tag NAMES a shell key carried last time, so a
|
|
9
|
+
* HIT can start the marker reads alongside the entry read instead of after
|
|
10
|
+
* the entry's head names its tags. Never marker values.
|
|
11
|
+
* - {@link TagMarkerMemo}: the marker VALUES (a tag's latest invalidatedAt,
|
|
12
|
+
* or null), served stale-while-revalidate. A value younger than
|
|
13
|
+
* `markerFreshMs` is used as is; one younger than `markerMaxStaleMs` is used
|
|
14
|
+
* and refreshed from the store in the background; an older one blocks on
|
|
15
|
+
* the store read as before.
|
|
16
|
+
*
|
|
17
|
+
* Simple reads get SWR; a mutation gets correct reads. The request that runs
|
|
18
|
+
* updateTag()/revalidateTag() reads its own writes through the per-request
|
|
19
|
+
* memo; the isolate that runs it writes the new value through into this memo;
|
|
20
|
+
* and its response sets the fresh-reads cookie (request-context.ts), so the
|
|
21
|
+
* same user's next requests on OTHER isolates skip this memo and the shell
|
|
22
|
+
* memo for as long as either can be stale. Other users can see a marker up to
|
|
23
|
+
* `markerMaxStaleMs` old, on top of the platform's own consistency
|
|
24
|
+
* (Cloudflare KV is eventually consistent across locations, up to about 60 s;
|
|
25
|
+
* Vercel's `tm` markers are regional).
|
|
26
|
+
*
|
|
27
|
+
* Only PPR shell reads use the value memo. Cached data families (`cache()`,
|
|
28
|
+
* `"use cache"`, responses) and the shell write gate
|
|
29
|
+
* (`isTagsInvalidatedSince`) keep reading their markers, in every request,
|
|
30
|
+
* whatever its shell read found: a shell read's memoized values never reach
|
|
31
|
+
* the data families' per-request memo (cf-tag-marker-memo.ts
|
|
32
|
+
* ShellMarkerReads).
|
|
33
|
+
*/
|
|
34
|
+
import type { RequestContext } from "../server/request-context.js";
|
|
35
|
+
import type { ShellReadStats } from "./types.js";
|
|
36
|
+
/** Default freshness of a memoized marker on CFCacheStore (ms). */
|
|
37
|
+
export declare const DEFAULT_CF_MARKER_FRESH_MS = 1000;
|
|
38
|
+
/** Default freshness of a memoized marker on VercelCacheStore (ms). */
|
|
39
|
+
export declare const DEFAULT_VERCEL_MARKER_FRESH_MS = 300;
|
|
40
|
+
/** Default oldest memoized marker served while it refreshes (ms), CF. */
|
|
41
|
+
export declare const DEFAULT_CF_MARKER_MAX_STALE_MS = 10000;
|
|
42
|
+
/**
|
|
43
|
+
* The same cap on VercelCacheStore: the runtime cache expires tags globally
|
|
44
|
+
* within about 300 ms, so a much longer stale window would widen that for
|
|
45
|
+
* other users more than KV's own up-to-60 s cross-location lag does on CF.
|
|
46
|
+
*/
|
|
47
|
+
export declare const DEFAULT_VERCEL_MARKER_MAX_STALE_MS = 2000;
|
|
48
|
+
/**
|
|
49
|
+
* Most shell keys a hint map holds (least recently used evicted).
|
|
50
|
+
* @internal Exported for tests that fill the map to its cap.
|
|
51
|
+
*/
|
|
52
|
+
export declare const TAG_HINTS_MAX_ENTRIES = 2048;
|
|
53
|
+
/** How a marker read was answered, for the debugPerformance marker row. */
|
|
54
|
+
export type MarkerMemoOutcome = "fresh" | "stale" | "read" | "bypass";
|
|
55
|
+
/** A memoized marker a read may use: its value, and whether it is stale. */
|
|
56
|
+
export interface MarkerMemoHit {
|
|
57
|
+
value: number | null;
|
|
58
|
+
stale: boolean;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A store read of a marker for {@link TagMarkerMemo.readThrough}: the value,
|
|
62
|
+
* and whether it may be memoized (a timed-out read that failed open may not).
|
|
63
|
+
*/
|
|
64
|
+
export interface MarkerFetch {
|
|
65
|
+
value: number | null;
|
|
66
|
+
memoize: boolean;
|
|
67
|
+
}
|
|
68
|
+
/** Options of {@link TagMarkerMemo.readThrough}. */
|
|
69
|
+
export interface MarkerReadThroughOptions {
|
|
70
|
+
/** Fresh window (ms); 0 or less reads the store and memoizes nothing. */
|
|
71
|
+
freshMs: number;
|
|
72
|
+
/** The oldest value served while it refreshes (ms). */
|
|
73
|
+
maxStaleMs: number;
|
|
74
|
+
/** The request carries the fresh-reads cookie: read the store. */
|
|
75
|
+
bypass: boolean;
|
|
76
|
+
/** Keeps a background refresh alive after the response (waitUntil). */
|
|
77
|
+
keepAlive?: (pending: Promise<void>) => void;
|
|
78
|
+
/** How the read was answered, for the debugPerformance marker row. */
|
|
79
|
+
onOutcome?: (outcome: MarkerMemoOutcome) => void;
|
|
80
|
+
}
|
|
81
|
+
export declare class TagMarkerMemo {
|
|
82
|
+
private readonly maxEntries;
|
|
83
|
+
private readonly slots;
|
|
84
|
+
private readonly refreshing;
|
|
85
|
+
constructor(maxEntries?: number);
|
|
86
|
+
/**
|
|
87
|
+
* The memoized marker for `key` if it is younger than `maxStaleMs` (stale
|
|
88
|
+
* when older than `freshMs`), or undefined when the caller must read the
|
|
89
|
+
* store. `freshMs <= 0` disables the memo.
|
|
90
|
+
*/
|
|
91
|
+
lookup(key: string, freshMs: number, maxStaleMs: number, now?: number): MarkerMemoHit | undefined;
|
|
92
|
+
/**
|
|
93
|
+
* Record a marker the store returned to a read that started at
|
|
94
|
+
* `readStartedAt`. The age counts from the read's start, not its end: a
|
|
95
|
+
* marker written while the read was in flight may be missing from it, so
|
|
96
|
+
* the value is only known to be current as of the start. Markers only move
|
|
97
|
+
* forward, so a value older than one already held (a write-through that
|
|
98
|
+
* landed during the read) is kept at the newer value, with the later stamp.
|
|
99
|
+
*/
|
|
100
|
+
store(key: string, value: number | null, readStartedAt?: number): void;
|
|
101
|
+
/**
|
|
102
|
+
* Refresh a stale marker in the background: one read per key at a time,
|
|
103
|
+
* handed to `keepAlive` (the store's waitUntil) so the runtime lets it
|
|
104
|
+
* finish after the response; without it the read runs detached. A read
|
|
105
|
+
* that fails, or may not be memoized, stores nothing.
|
|
106
|
+
*/
|
|
107
|
+
refresh(key: string, read: () => Promise<MarkerFetch>, keepAlive?: (pending: Promise<void>) => void): void;
|
|
108
|
+
/**
|
|
109
|
+
* A marker through the memo, stale-while-revalidate: a value within
|
|
110
|
+
* `freshMs` is used as is; one within `maxStaleMs` is used while one
|
|
111
|
+
* background read refreshes it; otherwise, and for a request carrying the
|
|
112
|
+
* fresh-reads cookie, the store is read (`fetch(false)`) and the result
|
|
113
|
+
* memoized. `fetch(true)` is the background refresh, outside any request.
|
|
114
|
+
*/
|
|
115
|
+
readThrough(key: string, fetch: (background: boolean) => Promise<MarkerFetch>, options: MarkerReadThroughOptions): Promise<number | null>;
|
|
116
|
+
clear(): void;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The tag names a shell key's entry carried when it was last read or written
|
|
120
|
+
* in this isolate, so the next HIT can start their marker reads before the
|
|
121
|
+
* entry names them. A wrong or missing hint costs a wasted read or nothing;
|
|
122
|
+
* the freshness check always uses the entry's own tags.
|
|
123
|
+
*/
|
|
124
|
+
export declare class TagNameHints {
|
|
125
|
+
private readonly maxEntries;
|
|
126
|
+
private readonly keys;
|
|
127
|
+
constructor(maxEntries?: number);
|
|
128
|
+
get(key: string): readonly string[] | undefined;
|
|
129
|
+
remember(key: string, tags: readonly string[] | undefined): void;
|
|
130
|
+
clear(): void;
|
|
131
|
+
}
|
|
132
|
+
/** The union of a key's remembered tag names and the route's static tags. */
|
|
133
|
+
export declare function hintedTags(remembered: readonly string[] | undefined, routeTags: readonly string[] | undefined): string[];
|
|
134
|
+
/**
|
|
135
|
+
* The marker row's memo outcome for a read's tags: the most store-bound one
|
|
136
|
+
* (a bypass or store read outranks a stale value, which outranks a fresh one).
|
|
137
|
+
*/
|
|
138
|
+
export declare function summarizeMarkerOutcomes(tags: readonly string[] | undefined, outcomes: ReadonlyMap<string, MarkerMemoOutcome>): MarkerMemoOutcome | undefined;
|
|
139
|
+
/**
|
|
140
|
+
* Fill a shell read's marker-row stats (debugPerformance) for the entry's
|
|
141
|
+
* own tags: the memo outcome, and how many of them the read had hinted.
|
|
142
|
+
*/
|
|
143
|
+
export declare function recordMarkerRow(stats: ShellReadStats, tags: readonly string[] | undefined, outcomes: ReadonlyMap<string, MarkerMemoOutcome> | undefined): void;
|
|
144
|
+
/**
|
|
145
|
+
* True when this request carries the fresh-reads cookie: a request of the same
|
|
146
|
+
* user after an updateTag()/revalidateTag(), which must not be served from an
|
|
147
|
+
* isolate memo (shell or marker) that could predate the mutation.
|
|
148
|
+
*/
|
|
149
|
+
export declare function freshReadsRequired(ctx: Pick<RequestContext, "_freshReads"> | undefined): boolean;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The per-request tag mask behind read-your-own-writes (#973).
|
|
3
|
+
*
|
|
4
|
+
* updateTag() and revalidateTag() call a store's invalidateTags() inside the
|
|
5
|
+
* request, and a built-in store masks the tags here before its first await:
|
|
6
|
+
* every later read in that request, through any context derived from it,
|
|
7
|
+
* treats an entry carrying one of the tags, written at or before the mask, as
|
|
8
|
+
* invalidated, without waiting for the durable write (the KV marker put, the
|
|
9
|
+
* tag purge, expireTag()) that revalidateTag() leaves to waitUntil. The mask
|
|
10
|
+
* only ever turns this request's hits into misses: if the durable write then
|
|
11
|
+
* fails, the request paid extra misses, never a stale read, and other
|
|
12
|
+
* requests read the durable state. CFCacheStore and VercelCacheStore share it.
|
|
13
|
+
*/
|
|
14
|
+
/** Request context -> store instance -> T, both levels weakly held. */
|
|
15
|
+
export type PerRequestStoreMap<T> = WeakMap<object, WeakMap<object, T>>;
|
|
16
|
+
/** The value for (ctx, store), created on first use. */
|
|
17
|
+
export declare function perRequestStoreValue<T>(map: PerRequestStoreMap<T>, ctx: object, store: object, create: () => T): T;
|
|
18
|
+
/**
|
|
19
|
+
* The request a context belongs to: RequestContext._requestRoot, which
|
|
20
|
+
* createRequestContext defines and a derived context (Object.create: a shell
|
|
21
|
+
* capture, a PPR HIT tail) inherits. A bare test context is its own root.
|
|
22
|
+
*/
|
|
23
|
+
export declare function requestRoot<T extends object>(ctx: T & {
|
|
24
|
+
_requestRoot?: T;
|
|
25
|
+
}): T;
|
|
26
|
+
/** Mask `tags` at `at` through `store` for the rest of `ctx`'s request. */
|
|
27
|
+
export declare function maskRequestTags(ctx: object, store: object, tags: readonly string[], at: number): void;
|
|
28
|
+
/**
|
|
29
|
+
* Whether `ctx`'s request masked one of `tags` through `store` at or after
|
|
30
|
+
* `taggedAt`. `>=`, as the stores' marker checks: an entry written in the
|
|
31
|
+
* invalidation's millisecond may hold a value computed before it, so it
|
|
32
|
+
* misses (a false miss, never a stale read).
|
|
33
|
+
*/
|
|
34
|
+
export declare function maskedForRequest(ctx: object | undefined, store: object, tags: readonly string[] | undefined, taggedAt: number): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* A marker read for a write gate (isTagsInvalidatedSince, from
|
|
37
|
+
* tag-invalidation.ts predatesInvalidation), shared by the gates of a
|
|
38
|
+
* request that ask while it is in flight. A page's writes (its "use cache"
|
|
39
|
+
* misses, its route record, its document) finish together and often carry
|
|
40
|
+
* the same tags, and each read its own marker before: one KV or
|
|
41
|
+
* runtime-cache read per tag per write.
|
|
42
|
+
*
|
|
43
|
+
* A read answers only for invalidations before it was issued. So a gate
|
|
44
|
+
* shares one still in flight, issued at or after its execution started
|
|
45
|
+
* (`sinceMs` is the millisecond after that start), and the read is dropped
|
|
46
|
+
* once it settles: a gate asking later reads again, and a shared read
|
|
47
|
+
* leaves open at most one marker round-trip. Reusing a settled read let a
|
|
48
|
+
* gate asking long after it miss another isolate's invalidation in
|
|
49
|
+
* between (a capture's putShell answered by a "use cache" write's read
|
|
50
|
+
* from the start of the capture), and kept a timed-out read's fail-open
|
|
51
|
+
* answer for the rest of the request. Without a request context `read()`
|
|
52
|
+
* runs unshared.
|
|
53
|
+
*/
|
|
54
|
+
export declare function gateMarkerRead<T>(ctx: object | undefined, store: object, tag: string, sinceMs: number, read: () => Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-isolate memo of fresh PPR shell reads (issue #941, decision 1;
|
|
3
|
+
* docs/design/shell-entry-layout.md).
|
|
4
|
+
*
|
|
5
|
+
* A warm isolate serving the same shell many times a second re-reads, and
|
|
6
|
+
* re-parses, the same stored entry on every HIT. The store keeps the last
|
|
7
|
+
* fresh read per key for a short window (`memo.shellMs`) and serves the next
|
|
8
|
+
* HIT from memory. What the memo does NOT skip is the part that decides
|
|
9
|
+
* whether the entry may be served: the store still runs its tag-marker check
|
|
10
|
+
* on every read, so with KV bound `updateTag()` / `revalidateTag()` stay
|
|
11
|
+
* immediate across isolates. The isolate that runs the invalidation drops its
|
|
12
|
+
* own copies and keeps reads that were in flight from memoizing them again
|
|
13
|
+
* (RecentTagInvalidations). What another isolate can serve for up to one
|
|
14
|
+
* window: a newer capture of the same key; a KV-less purge-mode purge; on
|
|
15
|
+
* Vercel, an invalidation from another region (tag markers are regional) and
|
|
16
|
+
* a platform `expireTag` issued outside rango (it writes no tag marker).
|
|
17
|
+
*
|
|
18
|
+
* Store instances are usually created per request, so the memo must outlive
|
|
19
|
+
* them: CFCacheStore keeps one module-level memo per isolate, VercelCacheStore
|
|
20
|
+
* one per runtime-cache handle (the handle carries the namespace). One byte
|
|
21
|
+
* budget (`memo.shellMaxBytes`) caps a memo; storing sweeps entries past their
|
|
22
|
+
* window, then evicts the least recently used. Measured on a 3.2 MB shell
|
|
23
|
+
* (Node 22 heap): CFCacheStore holds 1.08x what it counts (prelude plus
|
|
24
|
+
* snapshot JSON); VercelCacheStore holds 0.93x (envelope JSON plus the
|
|
25
|
+
* decoded prelude).
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Per-isolate memos a built-in store keeps (`CFCacheStore`: one per isolate;
|
|
29
|
+
* `VercelCacheStore`: one per `cache` handle). A window of 0 turns that memo
|
|
30
|
+
* off.
|
|
31
|
+
*/
|
|
32
|
+
export interface StoreMemoOptions {
|
|
33
|
+
/**
|
|
34
|
+
* PPR shell memo window (ms): after a shell read, the next HITs of that key
|
|
35
|
+
* within the window are served from memory, with no store read and no
|
|
36
|
+
* parse. Only a fresh shell whose snapshot read completed is kept. The
|
|
37
|
+
* tag-marker check still runs on every HIT, and the isolate that runs
|
|
38
|
+
* `updateTag()` / `revalidateTag()` drops its own copies, so neither that
|
|
39
|
+
* request nor a later one on the same isolate gets the invalidated shell.
|
|
40
|
+
* What ANOTHER isolate can serve for up to one window:
|
|
41
|
+
* - a newer capture of the same key;
|
|
42
|
+
* - `CFCacheStore` without KV, in purge mode: a purged shell. The purge
|
|
43
|
+
* removes the stored entry, not other isolates' memos;
|
|
44
|
+
* - `VercelCacheStore`: an invalidation from another region (the tag
|
|
45
|
+
* markers are a regional `cache.set`; only `expireTag` is global), and a
|
|
46
|
+
* platform `expireTag` issued outside rango.
|
|
47
|
+
*
|
|
48
|
+
* The mutating user is not served these: the response of a request that
|
|
49
|
+
* ran `updateTag()` / `revalidateTag()` sets the fresh-reads cookie, and
|
|
50
|
+
* requests carrying it skip the memos. Set `{ shellMs: 0, markerFreshMs: 0 }`
|
|
51
|
+
* where every user's next request must see an invalidation (with KV,
|
|
52
|
+
* `CFCacheStore`'s marker memo alone can serve an invalidated shell for up
|
|
53
|
+
* to `markerMaxStaleMs`). Default 2000.
|
|
54
|
+
*/
|
|
55
|
+
shellMs?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Total bytes (prelude plus snapshot) the shell memo may hold; the least
|
|
58
|
+
* recently used shells are evicted first, and a shell larger than the whole
|
|
59
|
+
* budget is not kept. Default 16 MiB. 0 turns the memo off.
|
|
60
|
+
*/
|
|
61
|
+
shellMaxBytes?: number;
|
|
62
|
+
/**
|
|
63
|
+
* Tag-marker memo for PPR shell reads: a tag's invalidation marker read
|
|
64
|
+
* within this many ms is used without a store read. Default 1000 on
|
|
65
|
+
* `CFCacheStore` (with KV; without KV there are no markers), 300 on
|
|
66
|
+
* `VercelCacheStore`. 0 turns the marker memo off. Cached data families
|
|
67
|
+
* (`cache()`, `"use cache"`, responses) keep reading their markers.
|
|
68
|
+
*/
|
|
69
|
+
markerFreshMs?: number;
|
|
70
|
+
/**
|
|
71
|
+
* The oldest memoized marker a shell read still uses while a background
|
|
72
|
+
* read refreshes it; an older one blocks on the store read. Default 10000
|
|
73
|
+
* on `CFCacheStore`, 2000 on `VercelCacheStore`. The isolate that runs
|
|
74
|
+
* `updateTag()` / `revalidateTag()` writes the new marker into its memo,
|
|
75
|
+
* and the response sets the fresh-reads cookie, so the same user's next
|
|
76
|
+
* requests skip both memos on any isolate.
|
|
77
|
+
*/
|
|
78
|
+
markerMaxStaleMs?: number;
|
|
79
|
+
}
|
|
80
|
+
/** Default memo window (ms). */
|
|
81
|
+
export declare const DEFAULT_SHELL_MEMO_MS = 2000;
|
|
82
|
+
/** Default total memo size per isolate (bytes). */
|
|
83
|
+
export declare const DEFAULT_SHELL_MEMO_MAX_BYTES: number;
|
|
84
|
+
/** A store's memo options, validated. */
|
|
85
|
+
export interface ResolvedShellMemoOptions {
|
|
86
|
+
shellMs: number;
|
|
87
|
+
shellMaxBytes: number;
|
|
88
|
+
markerFreshMs: number;
|
|
89
|
+
markerMaxStaleMs: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Validate a store's `memo` option; the marker memo's defaults are per store
|
|
93
|
+
* (isolate-tag-memo.ts). A non-finite value (`NaN` from `Number(env.UNSET)`,
|
|
94
|
+
* `Infinity`, null) falls back to the default, like the CFCacheStore read
|
|
95
|
+
* budgets; a finite 0 or negative passes through and turns that memo off.
|
|
96
|
+
*/
|
|
97
|
+
export declare function resolveShellMemoOptions(memo: StoreMemoOptions | undefined, markerDefaults: {
|
|
98
|
+
markerFreshMs: number;
|
|
99
|
+
markerMaxStaleMs: number;
|
|
100
|
+
}): ResolvedShellMemoOptions;
|
|
101
|
+
/**
|
|
102
|
+
* Headroom on the fresh-reads cookie's lifetime: revalidateTag() writes its
|
|
103
|
+
* markers in the background, so they can land after the response that sets
|
|
104
|
+
* the cookie, and the memos' windows count from then.
|
|
105
|
+
*/
|
|
106
|
+
export declare const FRESH_READS_MARGIN_MS = 1000;
|
|
107
|
+
/**
|
|
108
|
+
* How long the fresh-reads cookie keeps a mutating user off a store's memos:
|
|
109
|
+
* the longest either memo can still hold a value from before the mutation
|
|
110
|
+
* (the shell window; the marker memo's max-stale cap when the store reads
|
|
111
|
+
* markers through it, counted from the start of the read that filled it),
|
|
112
|
+
* plus FRESH_READS_MARGIN_MS. 0 when both memos are off: no cookie.
|
|
113
|
+
*/
|
|
114
|
+
export declare function freshReadsWindowMs(memo: ResolvedShellMemoOptions, markerMemo: boolean): number;
|
|
115
|
+
/**
|
|
116
|
+
* Whether a shell is neither stale nor expired: the only kind a memo keeps or
|
|
117
|
+
* serves (a stale read stays with the store, which schedules the recapture).
|
|
118
|
+
*/
|
|
119
|
+
export declare function isShellFresh(staleAt: number, expiresAt: number, now?: number): boolean;
|
|
120
|
+
/** Whether a shell's tags include any of `tags`. */
|
|
121
|
+
export declare function shellHasAnyTag(shellTags: readonly string[] | undefined, tags: readonly string[]): boolean;
|
|
122
|
+
export declare class ShellMemo<T> {
|
|
123
|
+
private readonly slots;
|
|
124
|
+
private totalBytes;
|
|
125
|
+
/**
|
|
126
|
+
* The value stored under `key` less than `windowMs` ago, or undefined.
|
|
127
|
+
* A hit becomes the most recently used entry.
|
|
128
|
+
*/
|
|
129
|
+
get(key: string, windowMs: number, now?: number): T | undefined;
|
|
130
|
+
/**
|
|
131
|
+
* Store `value` (`bytes` counted against `maxBytes`). Entries past their own
|
|
132
|
+
* window are dropped first, so a key that is never read again does not hold
|
|
133
|
+
* memory until the cap pushes it out; then the least recently used entries
|
|
134
|
+
* are evicted until the value fits. A value larger than the whole budget, or
|
|
135
|
+
* a window of 0, is not stored.
|
|
136
|
+
*/
|
|
137
|
+
set(key: string, value: T, bytes: number, windowMs: number, maxBytes: number, now?: number): void;
|
|
138
|
+
delete(key: string): void;
|
|
139
|
+
/** Drop every entry `predicate` selects. */
|
|
140
|
+
deleteWhere(predicate: (value: T) => boolean): void;
|
|
141
|
+
/** Bytes currently held. */
|
|
142
|
+
get size(): number;
|
|
143
|
+
clear(): void;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Tags this isolate invalidated recently, and when. `invalidateTags()` drops
|
|
147
|
+
* the isolate's memoized shells for its tags at once, but a read that was in
|
|
148
|
+
* flight (its store read done, its snapshot still arriving) can memoize one
|
|
149
|
+
* of them again while the markers or the purge are still being written. With
|
|
150
|
+
* KV that copy is harmless (every memo hit reads the markers); in KV-less
|
|
151
|
+
* purge mode the memo-hit check sees only the request's own marker memo, so
|
|
152
|
+
* nothing would reject it for a whole window, and the mutating user's next
|
|
153
|
+
* request on this isolate got the invalidated shell.
|
|
154
|
+
*
|
|
155
|
+
* A record lives from the invalidation's start until `holdMs` after it
|
|
156
|
+
* settles, which covers a read in flight when it settled (its snapshot read
|
|
157
|
+
* is bounded by the store's read budget, 170 ms by default on CFCacheStore).
|
|
158
|
+
* While it lives, a shell carrying the tag and tagged at or before the
|
|
159
|
+
* invalidation is neither memoized nor served from the memo. It only adds
|
|
160
|
+
* rejections: a shell tagged after the invalidation is not affected, and no
|
|
161
|
+
* marker read is skipped. Records are per tag across namespaces, like the
|
|
162
|
+
* memo drop in `invalidateTags()`: another namespace's shell with the same
|
|
163
|
+
* tag skips the memo for the record's life.
|
|
164
|
+
*/
|
|
165
|
+
export declare class RecentTagInvalidations {
|
|
166
|
+
private readonly records;
|
|
167
|
+
/** An invalidation of `tags` at `at` started. */
|
|
168
|
+
begin(tags: readonly string[], at: number, now?: number): void;
|
|
169
|
+
/** The invalidation begun for `tags` settled: hold its records `holdMs`. */
|
|
170
|
+
settle(tags: readonly string[], holdMs: number, now?: number): void;
|
|
171
|
+
/**
|
|
172
|
+
* Whether a shell carrying `tags`, tagged at `taggedAt`, predates a live
|
|
173
|
+
* record of one of them (a tagged shell with no tag time is treated as
|
|
174
|
+
* predating it).
|
|
175
|
+
*/
|
|
176
|
+
covers(tags: readonly string[] | undefined, taggedAt: number | undefined, now?: number): boolean;
|
|
177
|
+
clear(): void;
|
|
178
|
+
}
|