lambder 7.3.1 → 8.0.2
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/CHANGELOG.md +933 -3
- package/README.md +41 -21
- package/dist/api/LambderApiAnswer.d.ts +18 -22
- package/dist/api/LambderApiAnswer.js +6 -7
- package/dist/api/LambderApiCallContext.d.ts +21 -8
- package/dist/api/LambderApiCallContext.js +22 -4
- package/dist/api/LambderApiDefinition.d.ts +4 -3
- package/dist/api/LambderApiEnvelope.d.ts +14 -9
- package/dist/api/LambderApiEnvelope.js +33 -34
- package/dist/api/LambderApiGuards.d.ts +78 -51
- package/dist/api/LambderApiGuards.js +34 -36
- package/dist/api/LambderApiIdempotency.d.ts +68 -62
- package/dist/api/LambderApiIdempotency.js +214 -151
- package/dist/api/LambderApiOutputValidationError.d.ts +32 -0
- package/dist/api/LambderApiOutputValidationError.js +50 -0
- package/dist/api/LambderApiPipeline.d.ts +47 -38
- package/dist/api/LambderApiPipeline.js +122 -63
- package/dist/api/LambderApiRateLimits.d.ts +201 -54
- package/dist/api/LambderApiRateLimits.js +185 -108
- package/dist/api/LambderApiRequest.d.ts +27 -21
- package/dist/api/LambderApiRequest.js +26 -19
- package/dist/api/LambderApiSignature.d.ts +12 -15
- package/dist/api/LambderApiSignature.js +28 -51
- package/dist/api/LambderApiValidationRefusal.d.ts +9 -9
- package/dist/api/LambderApiValidationRefusal.js +10 -10
- package/dist/build/freshProcessVerifier.d.ts +13 -0
- package/dist/build/freshProcessVerifier.js +19 -0
- package/dist/build/writeApiSignatures.d.ts +109 -0
- package/dist/build/writeApiSignatures.js +222 -0
- package/dist/build.d.ts +9 -0
- package/dist/build.js +8 -0
- package/dist/client/LambderCaller.d.ts +13 -44
- package/dist/client/LambderCaller.js +77 -84
- package/dist/client/LambderReloadLoopBreaker.d.ts +56 -26
- package/dist/client/LambderReloadLoopBreaker.js +90 -46
- package/dist/client/lambderFetchTransport.d.ts +4 -1
- package/dist/client/lambderFetchTransport.js +52 -28
- package/dist/client.d.ts +5 -3
- package/dist/client.js +2 -1
- package/dist/core/Lambder.d.ts +140 -75
- package/dist/core/Lambder.js +347 -227
- package/dist/core/LambderContext.d.ts +82 -15
- package/dist/core/LambderContext.js +107 -20
- package/dist/core/LambderCors.d.ts +21 -3
- package/dist/core/LambderCors.js +35 -16
- package/dist/core/LambderCrashHandling.d.ts +40 -0
- package/dist/core/LambderCrashHandling.js +97 -0
- package/dist/core/LambderCreateOptions.d.ts +151 -75
- package/dist/core/LambderCreateOptions.js +16 -23
- package/dist/core/LambderFiles.d.ts +21 -7
- package/dist/core/LambderFiles.js +62 -34
- package/dist/core/LambderIndexHtml.js +12 -11
- package/dist/core/LambderPolicyBuilders.d.ts +17 -5
- package/dist/core/LambderPolicyBuilders.js +17 -5
- package/dist/core/LambderPublicFiles.d.ts +11 -5
- package/dist/core/LambderPublicFiles.js +32 -4
- package/dist/core/LambderRequestPath.d.ts +43 -0
- package/dist/core/LambderRequestPath.js +63 -0
- package/dist/core/LambderResponse.d.ts +26 -5
- package/dist/core/LambderResponse.js +157 -70
- package/dist/core/LambderResponseBuilder.d.ts +49 -4
- package/dist/core/LambderResponseBuilder.js +64 -3
- package/dist/core/LambderRouting.d.ts +2 -3
- package/dist/core/LambderRouting.js +22 -7
- package/dist/core/LambderTemplatingEngine.js +211 -32
- package/dist/index.d.ts +15 -8
- package/dist/index.js +5 -4
- package/dist/invoke/LambderInvokeCaller.d.ts +37 -42
- package/dist/invoke/LambderInvokeCaller.js +76 -66
- package/dist/invoke/LambderInvokeOutcome.d.ts +27 -26
- package/dist/invoke/LambderInvokeOutcome.js +9 -22
- package/dist/invoke/LambderLambdaEvent.d.ts +29 -9
- package/dist/invoke/LambderLambdaEvent.js +40 -22
- package/dist/invoke/lambderHandlerTransport.d.ts +9 -10
- package/dist/invoke/lambderHandlerTransport.js +15 -18
- package/dist/mock/LambderMockApp.d.ts +67 -83
- package/dist/mock/LambderMockApp.js +167 -153
- package/dist/mock/LambderMockBrowserCookies.d.ts +24 -28
- package/dist/mock/LambderMockBrowserCookies.js +24 -28
- package/dist/mock/LambderMockCallRecorder.d.ts +15 -22
- package/dist/mock/LambderMockCallRecorder.js +19 -28
- package/dist/mock/LambderMockCreateOptions.d.ts +42 -24
- package/dist/mock/LambderMockEntryRegistry.d.ts +11 -12
- package/dist/mock/LambderMockEntryRegistry.js +24 -29
- package/dist/mock/LambderMockFailureInjector.d.ts +3 -6
- package/dist/mock/LambderMockFailureInjector.js +3 -6
- package/dist/mock/LambderMockTypes.d.ts +78 -108
- package/dist/mock/lambderMockInvokeTransport.d.ts +11 -13
- package/dist/mock/lambderMockInvokeTransport.js +11 -10
- package/dist/mock/lambderMockMswHandler.d.ts +33 -29
- package/dist/mock/lambderMockMswHandler.js +50 -39
- package/dist/mock.d.ts +1 -1
- package/dist/mock.js +2 -3
- package/dist/session/LambderSessionController.d.ts +108 -89
- package/dist/session/LambderSessionController.js +187 -168
- package/dist/session/LambderSessionCrypto.d.ts +16 -7
- package/dist/session/LambderSessionCrypto.js +26 -12
- package/dist/session/LambderSessionManager.d.ts +124 -46
- package/dist/session/LambderSessionManager.js +262 -137
- package/dist/shared/LambderHtml.d.ts +42 -3
- package/dist/shared/LambderHtml.js +127 -7
- package/dist/shared/LambderHtmlPositions.d.ts +173 -0
- package/dist/shared/LambderHtmlPositions.js +652 -0
- package/dist/shared/LambderI18n.d.ts +10 -11
- package/dist/shared/LambderI18n.js +33 -21
- package/dist/shared/contracts/LambderCache.d.ts +66 -0
- package/dist/shared/contracts/LambderCache.js +11 -0
- package/dist/shared/contracts/LambderFileSource.d.ts +6 -6
- package/dist/shared/contracts/LambderFileSource.js +5 -8
- package/dist/shared/contracts/LambderIdempotencyStore.d.ts +51 -22
- package/dist/shared/contracts/LambderIdempotencyStore.js +4 -5
- package/dist/shared/contracts/LambderRateLimiter.d.ts +27 -15
- package/dist/shared/contracts/LambderRateLimiter.js +4 -5
- package/dist/shared/contracts/LambderSessionStore.d.ts +65 -26
- package/dist/shared/contracts/LambderSessionStore.js +5 -6
- package/dist/shared/transport/LambderApiTransport.d.ts +27 -27
- package/dist/shared/transport/LambderApiTransport.js +7 -7
- package/dist/shared/transport/LambderCookieJar.d.ts +28 -35
- package/dist/shared/transport/LambderCookieJar.js +54 -66
- package/dist/shared/transport/lambderCookieJarTransport.d.ts +11 -13
- package/dist/shared/transport/lambderCookieJarTransport.js +24 -23
- package/dist/shared/util/LambderCallAbort.d.ts +5 -5
- package/dist/shared/util/LambderCallAbort.js +5 -5
- package/dist/shared/util/LambderClientIp.d.ts +27 -11
- package/dist/shared/util/LambderClientIp.js +96 -13
- package/dist/shared/util/LambderExpiringMap.d.ts +35 -49
- package/dist/shared/util/LambderExpiringMap.js +41 -57
- package/dist/shared/util/LambderNodeModules.js +6 -7
- package/dist/shared/util/LambderOptionChecks.d.ts +4 -4
- package/dist/shared/util/LambderOptionChecks.js +4 -4
- package/dist/shared/util/LambderResponseBrand.d.ts +5 -5
- package/dist/shared/util/LambderResponseBrand.js +5 -5
- package/dist/shared/util/LambderTypeUtilities.d.ts +7 -8
- package/dist/shared/util/LambderTypeUtilities.js +3 -3
- package/dist/shared/util/boundKeyField.d.ts +20 -0
- package/dist/shared/util/boundKeyField.js +34 -0
- package/dist/shared/util/canonicalJson.d.ts +11 -0
- package/dist/shared/util/canonicalJson.js +28 -0
- package/dist/shared/util/joinKeyFields.d.ts +20 -0
- package/dist/shared/util/joinKeyFields.js +22 -0
- package/dist/shared/wire/LambderAnswerHeaders.d.ts +12 -16
- package/dist/shared/wire/LambderAnswerHeaders.js +12 -16
- package/dist/shared/wire/LambderApiContract.d.ts +107 -32
- package/dist/shared/wire/LambderApiOutcome.d.ts +43 -31
- package/dist/shared/wire/LambderApiOutcome.js +48 -23
- package/dist/shared/wire/LambderApiRefusal.d.ts +39 -27
- package/dist/shared/wire/LambderApiRefusal.js +36 -7
- package/dist/shared/wire/LambderApiSignature.d.ts +18 -22
- package/dist/shared/wire/LambderApiSignature.js +16 -19
- package/dist/shared/wire/LambderCallOptions.d.ts +38 -47
- package/dist/shared/wire/LambderCallOptions.js +9 -11
- package/dist/shared/wire/LambderCompressionCodec.d.ts +29 -34
- package/dist/shared/wire/LambderCompressionCodec.js +31 -36
- package/dist/shared/wire/LambderCompressionOption.d.ts +9 -9
- package/dist/shared/wire/LambderCompressionOption.js +9 -9
- package/dist/shared/wire/LambderCrashDetail.d.ts +12 -15
- package/dist/shared/wire/LambderCrashDetail.js +12 -15
- package/dist/shared/wire/LambderDefaultApiPath.d.ts +6 -0
- package/dist/shared/wire/LambderDefaultApiPath.js +6 -0
- package/dist/shared/wire/LambderHttpStatus.d.ts +6 -7
- package/dist/shared/wire/LambderIdempotencyKeyScope.d.ts +89 -0
- package/dist/shared/wire/LambderIdempotencyKeyScope.js +146 -0
- package/dist/shared/wire/LambderInvokeApiId.d.ts +27 -0
- package/dist/shared/wire/LambderInvokeApiId.js +27 -0
- package/dist/shared/wire/LambderOutcomeAssertions.d.ts +6 -7
- package/dist/shared/wire/LambderOutcomeAssertions.js +6 -7
- package/dist/shared/wire/LambderRequestPayload.d.ts +18 -20
- package/dist/shared/wire/LambderRequestPayload.js +4 -6
- package/dist/stores/LambderCacheFiller.d.ts +48 -0
- package/dist/stores/LambderCacheFiller.js +119 -0
- package/dist/stores/LambderCacheKeys.d.ts +26 -0
- package/dist/stores/LambderCacheKeys.js +54 -0
- package/dist/stores/LambderCacheValues.d.ts +45 -0
- package/dist/stores/LambderCacheValues.js +74 -0
- package/dist/stores/LambderDdbCache.d.ts +121 -56
- package/dist/stores/LambderDdbCache.js +528 -225
- package/dist/stores/LambderDdbIdempotencyStore.d.ts +33 -22
- package/dist/stores/LambderDdbIdempotencyStore.js +75 -50
- package/dist/stores/LambderDdbRateLimiter.d.ts +76 -20
- package/dist/stores/LambderDdbRateLimiter.js +151 -39
- package/dist/stores/LambderDdbSdk.d.ts +43 -31
- package/dist/stores/LambderDdbSdk.js +79 -33
- package/dist/stores/LambderDdbSessionStore.d.ts +27 -14
- package/dist/stores/LambderDdbSessionStore.js +119 -47
- package/dist/stores/LambderHttpFileSource.d.ts +15 -6
- package/dist/stores/LambderHttpFileSource.js +15 -13
- package/dist/stores/LambderMemoryCache.d.ts +49 -0
- package/dist/stores/LambderMemoryCache.js +113 -0
- package/dist/stores/LambderMemoryIdempotencyStore.d.ts +13 -12
- package/dist/stores/LambderMemoryIdempotencyStore.js +31 -30
- package/dist/stores/LambderMemoryRateLimiter.d.ts +8 -9
- package/dist/stores/LambderMemoryRateLimiter.js +14 -13
- package/dist/stores/LambderMemorySessionStore.d.ts +14 -11
- package/dist/stores/LambderMemorySessionStore.js +38 -19
- package/dist/stores/LambderS3FileSource.d.ts +21 -6
- package/dist/stores/LambderS3FileSource.js +12 -7
- package/dist/testing/LambderTestApp.d.ts +21 -23
- package/dist/testing/LambderTestApp.js +22 -24
- package/dist/testing/LambderTestVisitor.d.ts +10 -12
- package/dist/testing/LambderTestVisitor.js +15 -15
- package/dist/testing.d.ts +1 -0
- package/dist/testing.js +1 -0
- package/package.json +12 -3
- package/dist/api/LambderApiPolicyEngine.d.ts +0 -47
- package/dist/api/LambderApiPolicyEngine.js +0 -85
- package/dist/shared/util/LambderKeyFields.d.ts +0 -32
- package/dist/shared/util/LambderKeyFields.js +0 -34
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { assertPositiveInteger } from "../shared/util/LambderOptionChecks.js";
|
|
2
|
+
/*
|
|
3
|
+
* What a cache value has to be, and how a cache call's options are read, for
|
|
4
|
+
* every cache here.
|
|
5
|
+
*
|
|
6
|
+
* LambderDdbCache and LambderMemoryCache refuse the same values and the same
|
|
7
|
+
* options for the reason they refuse the same keys (see LambderCacheKeys): a
|
|
8
|
+
* test that runs over the memory cache must not accept what production then
|
|
9
|
+
* throws on. So the rules are written once, here, and both caches call them.
|
|
10
|
+
*/
|
|
11
|
+
/** How long an entry lives when neither the call nor the cache names a TTL: one year. */
|
|
12
|
+
export const DEFAULT_TTL_SECONDS = 365 * 24 * 60 * 60;
|
|
13
|
+
/** Largest value a cache accepts unless told otherwise, in UTF-8 bytes of its JSON: 32 MiB. */
|
|
14
|
+
export const DEFAULT_MAX_VALUE_BYTES = 32 * 1024 * 1024;
|
|
15
|
+
/** How long LambderDdbCache's fill lease holds when getOrSet names none. */
|
|
16
|
+
const DEFAULT_LEASE_SECONDS = 15;
|
|
17
|
+
/**
|
|
18
|
+
* The value as a cache stores it, or a throw when no cache here can hold it:
|
|
19
|
+
* a value JSON cannot represent (undefined, a function) or one whose JSON is
|
|
20
|
+
* past `maxValueBytes`.
|
|
21
|
+
*/
|
|
22
|
+
export const serializeCacheValue = (value, maxValueBytes) => {
|
|
23
|
+
const json = JSON.stringify(value);
|
|
24
|
+
if (json === undefined)
|
|
25
|
+
throw new Error("Cache value must be JSON-serializable");
|
|
26
|
+
const utf8 = new TextEncoder().encode(json);
|
|
27
|
+
if (utf8.length > maxValueBytes) {
|
|
28
|
+
throw new Error(`Cache value exceeds maxValueBytes (${utf8.length} > ${maxValueBytes})`);
|
|
29
|
+
}
|
|
30
|
+
return { json, utf8 };
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* The value as a cache hands a stored one back, a JSON round trip, so a value
|
|
34
|
+
* handed back uncached (a fail-open, a fill a write overtook) has the shape a
|
|
35
|
+
* hit has (a Date as its string). A value JSON cannot hold (undefined, a
|
|
36
|
+
* bigint) is handed back as it is.
|
|
37
|
+
*/
|
|
38
|
+
export const asStoredJson = (value) => {
|
|
39
|
+
let json;
|
|
40
|
+
try {
|
|
41
|
+
json = JSON.stringify(value);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
return json === undefined ? value : JSON.parse(json);
|
|
47
|
+
};
|
|
48
|
+
/** A write's TTL: the call's own or the cache's default, checked either way. */
|
|
49
|
+
export const resolveCacheTtlSeconds = (ttlSeconds, defaultTtlSeconds) => assertPositiveInteger(ttlSeconds ?? defaultTtlSeconds, "ttlSeconds");
|
|
50
|
+
/**
|
|
51
|
+
* getOrSet's options, checked before the call reaches the fail-open (see
|
|
52
|
+
* LambderCacheFiller). Checked inside it, a bad option would read as the
|
|
53
|
+
* cache failing: every call would log, hand the loader's value back
|
|
54
|
+
* uncached, and caching would be off without the caller ever seeing why.
|
|
55
|
+
*
|
|
56
|
+
* The lease options are LambderDdbCache's. The memory cache holds no lease
|
|
57
|
+
* but checks them all the same, so an options object that the table refuses
|
|
58
|
+
* is refused by its twin too.
|
|
59
|
+
*/
|
|
60
|
+
export const resolveGetOrSetOptions = (options, defaultTtlSeconds) => {
|
|
61
|
+
const leaseSeconds = assertPositiveInteger(options.leaseSeconds ?? DEFAULT_LEASE_SECONDS, "leaseSeconds");
|
|
62
|
+
return {
|
|
63
|
+
ttlSeconds: resolveCacheTtlSeconds(options.ttlSeconds, defaultTtlSeconds),
|
|
64
|
+
leaseSeconds,
|
|
65
|
+
// As long as the holder's lease lasts, and a second more, by default:
|
|
66
|
+
// a waiter that gives up sooner runs the loader itself while the
|
|
67
|
+
// holder is still loading, so ten containers asking for one slow key
|
|
68
|
+
// would load it ten times. The extra second is the lease's own
|
|
69
|
+
// rounding: it expires in whole seconds, so a crashed holder's lease
|
|
70
|
+
// becomes free up to a second after it runs out, and a waiter should
|
|
71
|
+
// still be there to take it.
|
|
72
|
+
waitForFillMs: assertPositiveInteger(options.waitForFillMs ?? (leaseSeconds + 1) * 1000, "waitForFillMs"),
|
|
73
|
+
};
|
|
74
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
2
2
|
import { type LambderCompressionOption } from "../shared/wire/LambderCompressionOption.js";
|
|
3
|
+
import type { LambderCache, LambderCacheKey, LambderCacheListOptions, LambderCacheSetOptions } from "../shared/contracts/LambderCache.js";
|
|
3
4
|
export interface LambderDdbCacheOptions {
|
|
4
5
|
tableName: string;
|
|
5
6
|
/** Region the client is created for on first use; the SDK's default chain otherwise. */
|
|
@@ -26,42 +27,23 @@ export interface LambderDdbCacheOptions {
|
|
|
26
27
|
*/
|
|
27
28
|
now?: () => number;
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
* `{ pk, sk }` puts the entry in a partition it can share with others, so a
|
|
32
|
-
* group can be listed or dropped in one call: `{ pk: "division:ist-34", sk:
|
|
33
|
-
* "1700:1800" }` keeps every cached window of one division together.
|
|
34
|
-
* Only the `pk` part is hashed into the DynamoDB partition key; the sort key
|
|
35
|
-
* is stored readable, which is what makes prefix queries possible.
|
|
36
|
-
*/
|
|
37
|
-
export type LambderCacheKey = string | {
|
|
38
|
-
pk: string;
|
|
39
|
-
sk: string;
|
|
40
|
-
};
|
|
41
|
-
export interface LambderDdbCacheSetOptions {
|
|
42
|
-
ttlSeconds?: number;
|
|
43
|
-
}
|
|
44
|
-
export interface LambderDdbCacheGetOrSetOptions extends LambderDdbCacheSetOptions {
|
|
30
|
+
export interface LambderDdbCacheGetOrSetOptions extends LambderCacheSetOptions {
|
|
31
|
+
/** How long one container's fill lease on a missing entry holds the others off. Default: 15. */
|
|
45
32
|
leaseSeconds?: number;
|
|
33
|
+
/** How long a container waits for another's fill before loading itself. Default: (leaseSeconds + 1) * 1000. */
|
|
46
34
|
waitForFillMs?: number;
|
|
47
35
|
}
|
|
48
|
-
export interface LambderDdbCacheListOptions {
|
|
49
|
-
/** Only sort keys starting with this raw (unescaped) prefix. */
|
|
50
|
-
prefix?: string;
|
|
51
|
-
/** Cap on RESULTS, not on items read: the partition (or prefix range) is read either way. */
|
|
52
|
-
limit?: number;
|
|
53
|
-
}
|
|
54
36
|
/**
|
|
55
37
|
* Persistent JSON cache backed by DynamoDB.
|
|
56
38
|
*
|
|
57
39
|
* Values are Brotli-compressed by default (`compression` option; the manifest
|
|
58
40
|
* records each value's encoding, so the option can be switched on a live
|
|
59
41
|
* table). Values within the safe DynamoDB item budget are stored directly in
|
|
60
|
-
* the manifest for a single-request read; larger values are
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
42
|
+
* the manifest for a single-request read; larger values are split into
|
|
43
|
+
* versioned binary chunks. A manifest is written only after every chunk
|
|
44
|
+
* succeeds, so readers see either the previous complete version or the new
|
|
45
|
+
* one. DynamoDB TTL is cleanup only; every read also checks expiresAt because
|
|
46
|
+
* TTL deletion can lag.
|
|
65
47
|
*
|
|
66
48
|
* Table shape: string hash key `pk`, string range key `sk`, TTL on
|
|
67
49
|
* `expiresAt`. Items are prefixed `CACHE#<namespace>#` by default, so the
|
|
@@ -70,12 +52,24 @@ export interface LambderDdbCacheListOptions {
|
|
|
70
52
|
*
|
|
71
53
|
* A key may also be a `{ pk, sk }` pair, which groups entries under one
|
|
72
54
|
* partition so `deletePartition` and `listSortKeys` can work on the group
|
|
73
|
-
* without knowing its members.
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
55
|
+
* without knowing its members. Only the `pk` part is hashed into the
|
|
56
|
+
* DynamoDB partition key; the sort key is stored readable, which makes
|
|
57
|
+
* prefix queries possible. Plain-string keys use the bare item keys (`meta`,
|
|
58
|
+
* `chunk#...`) and grouped entries live beside them under
|
|
59
|
+
* `sk#<encoded sort key>#...`, so both forms can share a partition.
|
|
60
|
+
*
|
|
61
|
+
* getOrSet's fill lease lives on the entry's manifest item (see takeLease),
|
|
62
|
+
* and a fill publishes only while its lease is still there. `set` replaces
|
|
63
|
+
* the manifest, and `delete` and `deletePartition` remove it, lease and all,
|
|
64
|
+
* so a fill that started before any of them never stores over it. Both find
|
|
65
|
+
* what to remove on the leader (`delete` by the manifest's own key,
|
|
66
|
+
* `deletePartition` with a consistent Query), since a replica may not have
|
|
67
|
+
* seen a value or a lease the table accepted a moment before.
|
|
68
|
+
*
|
|
69
|
+
* Implements LambderCache, so code typed against the interface runs over
|
|
70
|
+
* LambderMemoryCache in a test.
|
|
77
71
|
*/
|
|
78
|
-
export declare class LambderDdbCache {
|
|
72
|
+
export declare class LambderDdbCache implements LambderCache {
|
|
79
73
|
readonly tableName: string;
|
|
80
74
|
readonly keyPrefix: string;
|
|
81
75
|
readonly namespace: string;
|
|
@@ -86,41 +80,118 @@ export declare class LambderDdbCache {
|
|
|
86
80
|
private readonly compression;
|
|
87
81
|
private readonly maxValueBytes;
|
|
88
82
|
private readonly memory;
|
|
89
|
-
|
|
83
|
+
/** getOrSet's single-flight and fail-open, shared with LambderMemoryCache (see LambderCacheFiller). */
|
|
84
|
+
private readonly filler;
|
|
90
85
|
private readonly now;
|
|
86
|
+
/** This instance's own writes, as its reads and its memory layer need to know them (see LocalWriteLedger). */
|
|
87
|
+
private readonly localWrites;
|
|
91
88
|
constructor(options: LambderDdbCacheOptions);
|
|
92
89
|
get<T>(key: LambderCacheKey): Promise<T | undefined>;
|
|
93
90
|
private getByAddress;
|
|
91
|
+
/**
|
|
92
|
+
* The value a manifest the leader answered describes, its chunks read
|
|
93
|
+
* consistently, or undefined when it fails that read: then it is corrupt,
|
|
94
|
+
* and its manifest is dropped. `overtaken` comes from the read's watch
|
|
95
|
+
* (see LocalWriteLedger).
|
|
96
|
+
*/
|
|
97
|
+
private readLeaderEntry;
|
|
98
|
+
/**
|
|
99
|
+
* The value a manifest describes, checked against it and kept in the
|
|
100
|
+
* memory layer unless a write of the key finished while it was read
|
|
101
|
+
* (`overtaken`, see LocalWriteLedger).
|
|
102
|
+
*/
|
|
103
|
+
private readEntry;
|
|
94
104
|
has(key: LambderCacheKey): Promise<boolean>;
|
|
95
|
-
set<T>(key: LambderCacheKey, value: T, options?:
|
|
105
|
+
set<T>(key: LambderCacheKey, value: T, options?: LambderCacheSetOptions): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Stores the value and hands back what was stored, the parse of its
|
|
108
|
+
* JSON: what every later read answers too.
|
|
109
|
+
*
|
|
110
|
+
* With `leaseOwner` it is a fill publishing under its lease, and the
|
|
111
|
+
* manifest is written only while that lease is still on it. A set,
|
|
112
|
+
* delete or deletePartition since the lease was taken replaced or
|
|
113
|
+
* removed it, and so did a waiter that took it over once it lapsed; the
|
|
114
|
+
* loader may have read its source before any of those, so its value must
|
|
115
|
+
* not land over them. A refused fill deletes the chunks it wrote, which
|
|
116
|
+
* belong to no manifest, and hands its value back uncached. A write
|
|
117
|
+
* winning is the design and is not logged; a takeover is logged, since it
|
|
118
|
+
* means the loader ran past `leaseSeconds`, and while every fill does,
|
|
119
|
+
* each is refused by the next takeover and the entry never fills. The
|
|
120
|
+
* cure is a lease longer than the loader's worst case, which only the
|
|
121
|
+
* caller can give.
|
|
122
|
+
*/
|
|
96
123
|
private setByAddress;
|
|
124
|
+
/**
|
|
125
|
+
* The chunks of the version a manifest write just replaced, which nothing
|
|
126
|
+
* reads any more and which would otherwise sit in the table until their
|
|
127
|
+
* TTL: a large value refreshed hourly leaves a copy an hour. `ownVersion`
|
|
128
|
+
* is the writer's own, which an SDK retry of a write that had already
|
|
129
|
+
* landed reports as the replaced one.
|
|
130
|
+
*/
|
|
131
|
+
private deleteReplacedChunks;
|
|
132
|
+
/**
|
|
133
|
+
* One version's chunk items, deleted. The write they belonged to is
|
|
134
|
+
* settled whether or not this succeeds, and the chunks carry their own
|
|
135
|
+
* TTL, so a failure here is logged, not the caller's.
|
|
136
|
+
*/
|
|
137
|
+
private deleteChunks;
|
|
138
|
+
/**
|
|
139
|
+
* Removes the entry's manifest item, whatever it holds (a value, or a
|
|
140
|
+
* fill's lease, whose publish is then refused), and its chunks. True when
|
|
141
|
+
* the manifest held a live value: a lease or an expired value the table's
|
|
142
|
+
* TTL has not removed yet is no entry.
|
|
143
|
+
*/
|
|
97
144
|
delete(key: LambderCacheKey): Promise<boolean>;
|
|
98
145
|
/**
|
|
99
146
|
* Drop every entry stored under one `pk`, without knowing which sort keys
|
|
100
147
|
* exist: the invalidation a group of related entries is worth grouping
|
|
101
|
-
* for. Returns the number of
|
|
102
|
-
* OTHER Lambda containers still serve until their own TTL, as they do
|
|
148
|
+
* for. Returns the number of live values removed. In-memory copies held
|
|
149
|
+
* by OTHER Lambda containers still serve until their own TTL, as they do
|
|
103
150
|
* after a single-entry delete.
|
|
104
151
|
*/
|
|
105
152
|
deletePartition(partition: string): Promise<number>;
|
|
106
153
|
/**
|
|
107
154
|
* The live (unexpired) sort keys stored under one `pk`, in table order.
|
|
108
155
|
* Plain-string entries have no sort key, so they never appear here.
|
|
109
|
-
*
|
|
110
|
-
*
|
|
156
|
+
* The partition (or prefix range) is read whatever the limit, and reading
|
|
157
|
+
* a partition whose values are chunked also reads those chunk items, so
|
|
158
|
+
* grouping very large values makes listing more expensive.
|
|
111
159
|
*/
|
|
112
|
-
listSortKeys(partition: string, options?:
|
|
113
|
-
getOrSet<T>(key: LambderCacheKey,
|
|
160
|
+
listSortKeys(partition: string, options?: LambderCacheListOptions): Promise<string[]>;
|
|
161
|
+
getOrSet<T>(key: LambderCacheKey, loader: () => Promise<T>, options?: LambderDdbCacheGetOrSetOptions): Promise<T>;
|
|
162
|
+
/** The fill once a read found nothing: one container loads under the lease while the others wait for its value. */
|
|
163
|
+
private fill;
|
|
114
164
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
165
|
+
* Takes the fill lease on one entry by writing it onto the entry's
|
|
166
|
+
* manifest item, a manifest with no value that the fill's publish then
|
|
167
|
+
* replaces. Readers find no value on it, so to them it is a miss.
|
|
168
|
+
*
|
|
169
|
+
* The write is conditional on the item holding nothing live: none at
|
|
170
|
+
* all, or one whose expiresAt has passed, whether an expired value or a
|
|
171
|
+
* lapsed lease. So a lease never hides a live value, and a waiter taking
|
|
172
|
+
* over a lapsed lease replaces the first holder's, whose publish is then
|
|
173
|
+
* refused. An expired value the lease replaces goes at once, its chunks
|
|
174
|
+
* with it, and readers see a miss until the fill publishes, as they did
|
|
175
|
+
* from the moment it expired. DynamoDB's TTL removes a lease its holder
|
|
176
|
+
* abandoned.
|
|
177
|
+
*
|
|
178
|
+
* A refusal hands back the item that refused it: "held" for another
|
|
179
|
+
* fill's lease, and for a live value its manifest, which the caller
|
|
180
|
+
* serves the value from. A manifest this instance cannot read (written
|
|
181
|
+
* under another chunkBytes or maxValueBytes) is a miss to every read here
|
|
182
|
+
* and would otherwise block fills until its TTL, so the lease is taken
|
|
183
|
+
* over it, conditioned on it being the same manifest still.
|
|
118
184
|
*/
|
|
119
|
-
private
|
|
120
|
-
|
|
121
|
-
private acquireLease;
|
|
185
|
+
private takeLease;
|
|
186
|
+
/** Clears this fill's lease off the manifest item, conditional on it still being this fill's, so it never touches what replaced it. */
|
|
122
187
|
private releaseLease;
|
|
123
188
|
private readManifest;
|
|
189
|
+
/**
|
|
190
|
+
* The value a manifest item describes, or undefined when it describes
|
|
191
|
+
* none this instance can read: a fill's lease with no value under it
|
|
192
|
+
* yet, or a manifest that does not add up. Expiry is the caller's check.
|
|
193
|
+
*/
|
|
194
|
+
private parseManifest;
|
|
124
195
|
private readChunks;
|
|
125
196
|
/** Every item matching a partition (optionally a sort-key prefix), following pagination. */
|
|
126
197
|
private queryItems;
|
|
@@ -130,20 +201,14 @@ export declare class LambderDdbCache {
|
|
|
130
201
|
/** The JSON text of a stored payload. */
|
|
131
202
|
private decode;
|
|
132
203
|
private remember;
|
|
133
|
-
private normalizeKey;
|
|
134
|
-
private normalizePartition;
|
|
135
|
-
/** Length-prefixed so a partition ending in the separator cannot collide with a sort key. */
|
|
136
|
-
private memoryKeyOf;
|
|
137
204
|
private partitionKey;
|
|
138
205
|
/**
|
|
139
|
-
* One of an entry's item keys. A plain-string entry
|
|
140
|
-
* suffix
|
|
141
|
-
*
|
|
142
|
-
*
|
|
206
|
+
* One of an entry's item keys. A plain-string entry uses the bare
|
|
207
|
+
* suffix; a grouped one nests under its escaped sort key, whose trailing
|
|
208
|
+
* `#` is an unambiguous boundary because an escaped sort key never
|
|
209
|
+
* contains a bare `#`.
|
|
143
210
|
*/
|
|
144
211
|
private itemSortKey;
|
|
145
|
-
/** The prefix covering every item of a grouped entry; null for a plain-string entry, which owns the bare item keys instead. */
|
|
146
|
-
private entryItemPrefix;
|
|
147
212
|
private isManifestSortKey;
|
|
148
213
|
private chunkSortKey;
|
|
149
214
|
/** Drop every in-memory copy belonging to one partition. */
|