effect-dynamodb 1.24.0 → 1.26.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.
Files changed (106) hide show
  1. package/dist/Aggregate.d.ts +12 -2
  2. package/dist/Aggregate.d.ts.map +1 -1
  3. package/dist/Aggregate.js +284 -55
  4. package/dist/Aggregate.js.map +1 -1
  5. package/dist/Batch.d.ts +14 -5
  6. package/dist/Batch.d.ts.map +1 -1
  7. package/dist/Batch.js +184 -119
  8. package/dist/Batch.js.map +1 -1
  9. package/dist/Collection.d.ts +9 -1
  10. package/dist/Collection.d.ts.map +1 -1
  11. package/dist/Collection.js +5 -4
  12. package/dist/Collection.js.map +1 -1
  13. package/dist/DynamoClient.d.ts +80 -28
  14. package/dist/DynamoClient.d.ts.map +1 -1
  15. package/dist/DynamoClient.js +125 -25
  16. package/dist/DynamoClient.js.map +1 -1
  17. package/dist/Entity.d.ts +99 -40
  18. package/dist/Entity.d.ts.map +1 -1
  19. package/dist/Entity.js +693 -302
  20. package/dist/Entity.js.map +1 -1
  21. package/dist/EventStore.d.ts +598 -75
  22. package/dist/EventStore.d.ts.map +1 -1
  23. package/dist/EventStore.js +852 -221
  24. package/dist/EventStore.js.map +1 -1
  25. package/dist/Query.d.ts +100 -14
  26. package/dist/Query.d.ts.map +1 -1
  27. package/dist/Query.js +275 -71
  28. package/dist/Query.js.map +1 -1
  29. package/dist/StorageEncoding.d.ts +160 -0
  30. package/dist/StorageEncoding.d.ts.map +1 -0
  31. package/dist/StorageEncoding.js +258 -0
  32. package/dist/StorageEncoding.js.map +1 -0
  33. package/dist/Table.d.ts +56 -6
  34. package/dist/Table.d.ts.map +1 -1
  35. package/dist/Table.js +142 -60
  36. package/dist/Table.js.map +1 -1
  37. package/dist/Transaction.d.ts +8 -0
  38. package/dist/Transaction.d.ts.map +1 -1
  39. package/dist/Transaction.js +72 -22
  40. package/dist/Transaction.js.map +1 -1
  41. package/dist/VectorSearchEmulation.d.ts +3 -2
  42. package/dist/VectorSearchEmulation.d.ts.map +1 -1
  43. package/dist/VectorSearchEmulation.js +14 -2
  44. package/dist/VectorSearchEmulation.js.map +1 -1
  45. package/dist/compression/zlib.d.ts +75 -0
  46. package/dist/compression/zlib.d.ts.map +1 -0
  47. package/dist/compression/zlib.js +109 -0
  48. package/dist/compression/zlib.js.map +1 -0
  49. package/dist/index.d.ts +4 -1
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +3 -1
  52. package/dist/index.js.map +1 -1
  53. package/dist/internal/BoundCrud.d.ts +39 -35
  54. package/dist/internal/BoundCrud.d.ts.map +1 -1
  55. package/dist/internal/BoundCrud.js.map +1 -1
  56. package/dist/internal/BoundQuery.d.ts +6 -5
  57. package/dist/internal/BoundQuery.d.ts.map +1 -1
  58. package/dist/internal/BoundQuery.js.map +1 -1
  59. package/dist/internal/BoundVectorQuery.d.ts +17 -1
  60. package/dist/internal/BoundVectorQuery.d.ts.map +1 -1
  61. package/dist/internal/BoundVectorQuery.js +31 -6
  62. package/dist/internal/BoundVectorQuery.js.map +1 -1
  63. package/dist/internal/EntityCombinators.d.ts +8 -5
  64. package/dist/internal/EntityCombinators.d.ts.map +1 -1
  65. package/dist/internal/EntityCombinators.js +24 -6
  66. package/dist/internal/EntityCombinators.js.map +1 -1
  67. package/dist/internal/EntityOps.d.ts +1 -1
  68. package/dist/internal/Expr.d.ts +9 -3
  69. package/dist/internal/Expr.d.ts.map +1 -1
  70. package/dist/internal/Expr.js +7 -5
  71. package/dist/internal/Expr.js.map +1 -1
  72. package/dist/internal/ExpressionLimits.d.ts +45 -0
  73. package/dist/internal/ExpressionLimits.d.ts.map +1 -0
  74. package/dist/internal/ExpressionLimits.js +89 -0
  75. package/dist/internal/ExpressionLimits.js.map +1 -0
  76. package/dist/internal/Hydrate.d.ts +62 -0
  77. package/dist/internal/Hydrate.d.ts.map +1 -0
  78. package/dist/internal/Hydrate.js +191 -0
  79. package/dist/internal/Hydrate.js.map +1 -0
  80. package/dist/internal/ItemSize.d.ts +60 -24
  81. package/dist/internal/ItemSize.d.ts.map +1 -1
  82. package/dist/internal/ItemSize.js +122 -39
  83. package/dist/internal/ItemSize.js.map +1 -1
  84. package/dist/internal/Packed.d.ts +289 -0
  85. package/dist/internal/Packed.d.ts.map +1 -0
  86. package/dist/internal/Packed.js +654 -0
  87. package/dist/internal/Packed.js.map +1 -0
  88. package/dist/internal/PathBuilder.d.ts +45 -2
  89. package/dist/internal/PathBuilder.d.ts.map +1 -1
  90. package/dist/internal/PathBuilder.js +4 -0
  91. package/dist/internal/PathBuilder.js.map +1 -1
  92. package/dist/internal/TransactWriteOps.d.ts +22 -46
  93. package/dist/internal/TransactWriteOps.d.ts.map +1 -1
  94. package/dist/internal/TransactWriteOps.js +26 -95
  95. package/dist/internal/TransactWriteOps.js.map +1 -1
  96. package/dist/internal/TransactableOps.d.ts +1 -1
  97. package/dist/internal/TransactableOps.d.ts.map +1 -1
  98. package/dist/internal/TransactableOps.js +2 -0
  99. package/dist/internal/TransactableOps.js.map +1 -1
  100. package/dist/internal/WriteDiagnosis.d.ts +353 -0
  101. package/dist/internal/WriteDiagnosis.d.ts.map +1 -0
  102. package/dist/internal/WriteDiagnosis.js +1028 -0
  103. package/dist/internal/WriteDiagnosis.js.map +1 -0
  104. package/dist/internal/sparse_check.js +43 -79
  105. package/dist/internal/sparse_check.js.map +1 -1
  106. package/package.json +6 -2
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @internal `BatchGetItem` by key, results in input order — shared by
3
+ * `Batch.get` and the hydration of a stream index that does not project the
4
+ * events it indexes (`EventStore.makeStream({ indexes: { …, projection: "keys" } })`
5
+ * on a GSI, read through `Query`'s `hydration` hook).
6
+ *
7
+ * - Chunks of 100 keys (DynamoDB's `BatchGetItem` limit).
8
+ * - `UnprocessedKeys` are retried with exponential backoff (`baseDelayMs`,
9
+ * doubling); when `maxRetries` run out the call fails with `DynamoError`
10
+ * (`operation: "BatchGetItem"`).
11
+ * - `BatchGetItem` does not preserve order, so responses are matched back to
12
+ * their keys through a `Map` on the key attribute values.
13
+ * - With `rereadMissing`, keys absent from every response are read once more
14
+ * with `ConsistentRead: true` — an eventually consistent table read can lag
15
+ * a GSI that already holds the entry.
16
+ *
17
+ * Keys are sent as given. Callers pass keys that are unique within one
18
+ * request — a page of one stream's index never repeats a key — and a repeated
19
+ * key is not de-duplicated: DynamoDB rejects the request ("Provided list of
20
+ * item keys contains duplicates"), and the rejection is diagnosed (#144) as a
21
+ * `DynamoError` naming both positions (`describe`), DynamoDB's error kept as
22
+ * the cause.
23
+ */
24
+ import type { AttributeValue } from "@aws-sdk/client-dynamodb";
25
+ import { Effect } from "effect";
26
+ import type { DynamoClientError, DynamoClientService } from "../DynamoClient.js";
27
+ /** DynamoDB's limit on the keys of one `BatchGetItem` request. */
28
+ export declare const MAX_BATCH_GET = 100;
29
+ /** Default retries of `UnprocessedKeys`. */
30
+ export declare const MAX_RETRIES = 5;
31
+ /** Default first backoff delay, doubled on each retry. */
32
+ export declare const BASE_DELAY_MS = 100;
33
+ /** One key to fetch: the table and the item's full primary key. */
34
+ export interface HydrateRequest {
35
+ readonly tableName: string;
36
+ readonly key: Record<string, AttributeValue>;
37
+ }
38
+ export interface HydrateOptions {
39
+ /** A `ProjectionExpression` (and its names) sent for every table. */
40
+ readonly projection?: {
41
+ readonly expression: string;
42
+ readonly names: Record<string, string>;
43
+ } | undefined;
44
+ readonly maxRetries?: number | undefined;
45
+ readonly baseDelayMs?: number | undefined;
46
+ /** Re-read keys missing from the responses once, strongly consistently. */
47
+ readonly rereadMissing?: boolean | undefined;
48
+ /**
49
+ * The entity a request reads and how to name it in an error (`get 2
50
+ * (User)`), for a rejection of a repeated key. Default: `request <i>`.
51
+ */
52
+ readonly describe?: ((position: number) => {
53
+ readonly entityType: string;
54
+ readonly source: string;
55
+ }) | undefined;
56
+ }
57
+ /**
58
+ * Fetch `requests` and return the raw items in input order, `undefined` where
59
+ * an item does not exist.
60
+ */
61
+ export declare const batchGetRaw: (client: DynamoClientService, requests: ReadonlyArray<HydrateRequest>, options?: HydrateOptions) => Effect.Effect<Array<Record<string, AttributeValue> | undefined>, DynamoClientError>;
62
+ //# sourceMappingURL=Hydrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Hydrate.d.ts","sourceRoot":"","sources":["../../src/internal/Hydrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,0BAA0B,CAAA;AAEjF,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAQhF,kEAAkE;AAClE,eAAO,MAAM,aAAa,MAAM,CAAA;AAChC,4CAA4C;AAC5C,eAAO,MAAM,WAAW,IAAI,CAAA;AAC5B,0DAA0D;AAC1D,eAAO,MAAM,aAAa,MAAM,CAAA;AAEhC,mEAAmE;AACnE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;CAC7C;AAED,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,QAAQ,CAAC,UAAU,CAAC,EAChB;QAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GACvE,SAAS,CAAA;IACb,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzC,2EAA2E;IAC3E,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC5C;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EACd,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK;QAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,GAChF,SAAS,CAAA;CACd;AAkBD;;;GAGG;AACH,eAAO,MAAM,WAAW,GACtB,QAAQ,mBAAmB,EAC3B,UAAU,aAAa,CAAC,cAAc,CAAC,EACvC,UAAS,cAAmB,KAC3B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,SAAS,CAAC,EAAE,iBAAiB,CAoKjF,CAAA"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * @internal `BatchGetItem` by key, results in input order — shared by
3
+ * `Batch.get` and the hydration of a stream index that does not project the
4
+ * events it indexes (`EventStore.makeStream({ indexes: { …, projection: "keys" } })`
5
+ * on a GSI, read through `Query`'s `hydration` hook).
6
+ *
7
+ * - Chunks of 100 keys (DynamoDB's `BatchGetItem` limit).
8
+ * - `UnprocessedKeys` are retried with exponential backoff (`baseDelayMs`,
9
+ * doubling); when `maxRetries` run out the call fails with `DynamoError`
10
+ * (`operation: "BatchGetItem"`).
11
+ * - `BatchGetItem` does not preserve order, so responses are matched back to
12
+ * their keys through a `Map` on the key attribute values.
13
+ * - With `rereadMissing`, keys absent from every response are read once more
14
+ * with `ConsistentRead: true` — an eventually consistent table read can lag
15
+ * a GSI that already holds the entry.
16
+ *
17
+ * Keys are sent as given. Callers pass keys that are unique within one
18
+ * request — a page of one stream's index never repeats a key — and a repeated
19
+ * key is not de-duplicated: DynamoDB rejects the request ("Provided list of
20
+ * item keys contains duplicates"), and the rejection is diagnosed (#144) as a
21
+ * `DynamoError` naming both positions (`describe`), DynamoDB's error kept as
22
+ * the cause.
23
+ */
24
+ import { DynamoError } from "@effect-dynamodb/schema/Errors.js";
25
+ import { Effect } from "effect";
26
+ import { diagnoseFailure, transactItemTarget, withCause, } from "./WriteDiagnosis.js";
27
+ /** DynamoDB's limit on the keys of one `BatchGetItem` request. */
28
+ export const MAX_BATCH_GET = 100;
29
+ /** Default retries of `UnprocessedKeys`. */
30
+ export const MAX_RETRIES = 5;
31
+ /** Default first backoff delay, doubled on each retry. */
32
+ export const BASE_DELAY_MS = 100;
33
+ /** A key attribute value, as a string that is equal iff the values are. */
34
+ const scalarIdentity = (value) => {
35
+ if (value === undefined)
36
+ return "-";
37
+ if (value.S !== undefined)
38
+ return `S${value.S}`;
39
+ if (value.N !== undefined)
40
+ return `N${value.N}`;
41
+ if (value.B !== undefined)
42
+ return `B${Array.from(value.B).join(",")}`;
43
+ return `J${JSON.stringify(value)}`;
44
+ };
45
+ const identity = (tableName, names, item) => [tableName, ...names.map((name) => `${name}=${scalarIdentity(item[name])}`)].join("\u0000");
46
+ /**
47
+ * Fetch `requests` and return the raw items in input order, `undefined` where
48
+ * an item does not exist.
49
+ */
50
+ export const batchGetRaw = (client, requests, options = {}) => Effect.gen(function* () {
51
+ const results = new Array(requests.length).fill(undefined);
52
+ if (requests.length === 0)
53
+ return results;
54
+ const maxRetries = options.maxRetries ?? MAX_RETRIES;
55
+ const baseDelayMs = options.baseDelayMs ?? BASE_DELAY_MS;
56
+ /** The sorted key attribute names of each request, and its identity. */
57
+ const keyNames = requests.map((request) => Object.keys(request.key).sort());
58
+ const identities = requests.map((request, i) => identity(request.tableName, keyNames[i], request.key));
59
+ /**
60
+ * The item each key of a sent request reads, in request order, named by
61
+ * its position (a repeated key's occurrences by successive positions).
62
+ */
63
+ const repeatTargets = (sentItems) => {
64
+ const seen = new Map();
65
+ return Object.entries(sentItems).flatMap(([tableName, entry]) => (entry.Keys ?? []).map((key) => {
66
+ const names = Object.keys(key).sort();
67
+ const id = identity(tableName, names, key);
68
+ const occurrence = seen.get(id) ?? 0;
69
+ seen.set(id, occurrence + 1);
70
+ const positions = identities.flatMap((candidate, i) => (candidate === id ? [i] : []));
71
+ const position = positions[Math.min(occurrence, positions.length - 1)];
72
+ const described = position === undefined
73
+ ? { entityType: "unknown", source: "a request" }
74
+ : (options.describe?.(position) ?? {
75
+ entityType: "unknown",
76
+ source: `request ${position}`,
77
+ });
78
+ return transactItemTarget({ Get: { TableName: tableName, Key: key } }, tableName, names, described.entityType, described.source);
79
+ }));
80
+ };
81
+ /** Fetch the requests at `positions`, filling `results`. */
82
+ const fetch = (positions, consistentRead) => Effect.gen(function* () {
83
+ for (let start = 0; start < positions.length; start += MAX_BATCH_GET) {
84
+ const chunk = positions.slice(start, start + MAX_BATCH_GET);
85
+ const pending = new Map();
86
+ /** Per table: the distinct key-name lists its keys use. */
87
+ const tableKeyNames = new Map();
88
+ let requestItems = {};
89
+ for (const position of chunk) {
90
+ const request = requests[position];
91
+ const id = identities[position];
92
+ // A repeated key is still sent: DynamoDB rejects a request whose
93
+ // keys repeat ("Provided list of item keys contains duplicates"),
94
+ // and that rejection passes through — the helper does not quietly
95
+ // de-duplicate. The positions are grouped only for matching.
96
+ const waiting = pending.get(id);
97
+ if (waiting !== undefined)
98
+ waiting.push(position);
99
+ else
100
+ pending.set(id, [position]);
101
+ const names = keyNames[position];
102
+ let lists = tableKeyNames.get(request.tableName);
103
+ if (lists === undefined) {
104
+ lists = new Map();
105
+ tableKeyNames.set(request.tableName, lists);
106
+ }
107
+ lists.set(names.join("\u0000"), names);
108
+ let entry = requestItems[request.tableName];
109
+ if (entry === undefined) {
110
+ entry = {
111
+ Keys: [],
112
+ ...(consistentRead ? { ConsistentRead: true } : {}),
113
+ ...(options.projection === undefined
114
+ ? {}
115
+ : {
116
+ ProjectionExpression: options.projection.expression,
117
+ ExpressionAttributeNames: options.projection.names,
118
+ }),
119
+ };
120
+ requestItems[request.tableName] = entry;
121
+ }
122
+ entry.Keys.push(request.key);
123
+ }
124
+ let retries = 0;
125
+ while (Object.keys(requestItems).length > 0) {
126
+ const sentItems = requestItems;
127
+ const response = yield* client.batchGetItem({ RequestItems: sentItems }).pipe(
128
+ // A key repeated in one request (#144): DynamoDB's rejection,
129
+ // confirmed and named by the positions that read it.
130
+ diagnoseFailure({
131
+ sent: () => ({ _tag: "BatchGet", targets: () => repeatTargets(sentItems) }),
132
+ only: ["RepeatedItem"],
133
+ rewrite: (diagnosis, original) => diagnosis._tag !== "RepeatedItem"
134
+ ? original
135
+ : new DynamoError({
136
+ operation: "BatchGetItem",
137
+ cause: withCause(`BatchGetItem reads one item more than once — ` +
138
+ `${diagnosis.first.source} and ${diagnosis.second.source} both ` +
139
+ `read the item at ${diagnosis.second.key}. DynamoDB allows each key ` +
140
+ "once in a request, and rejected it. Read the item once.", original),
141
+ }),
142
+ }));
143
+ for (const [tableName, items] of Object.entries(response.Responses ?? {})) {
144
+ const lists = tableKeyNames.get(tableName);
145
+ if (lists === undefined)
146
+ continue;
147
+ for (const item of items) {
148
+ for (const names of lists.values()) {
149
+ const matched = pending.get(identity(tableName, names, item));
150
+ if (matched === undefined)
151
+ continue;
152
+ for (const position of matched)
153
+ results[position] = item;
154
+ break;
155
+ }
156
+ }
157
+ }
158
+ const unprocessed = {};
159
+ for (const [tableName, entry] of Object.entries(response.UnprocessedKeys ?? {})) {
160
+ if (entry.Keys !== undefined && entry.Keys.length > 0) {
161
+ // Keep what the original request asked for (consistency,
162
+ // projection) — only the keys change.
163
+ unprocessed[tableName] = { ...requestItems[tableName], Keys: entry.Keys };
164
+ }
165
+ }
166
+ if (Object.keys(unprocessed).length === 0)
167
+ break;
168
+ retries++;
169
+ if (retries > maxRetries) {
170
+ return yield* new DynamoError({
171
+ operation: "BatchGetItem",
172
+ cause: new Error(`Unprocessed keys remain after ${maxRetries} retries`),
173
+ });
174
+ }
175
+ yield* Effect.sleep(`${baseDelayMs * 2 ** (retries - 1)} millis`);
176
+ requestItems = unprocessed;
177
+ }
178
+ }
179
+ });
180
+ yield* fetch(requests.map((_, i) => i), false);
181
+ if (options.rereadMissing === true) {
182
+ const missing = [];
183
+ for (let i = 0; i < results.length; i++)
184
+ if (results[i] === undefined)
185
+ missing.push(i);
186
+ if (missing.length > 0)
187
+ yield* fetch(missing, true);
188
+ }
189
+ return results;
190
+ });
191
+ //# sourceMappingURL=Hydrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Hydrate.js","sourceRoot":"","sources":["../../src/internal/Hydrate.ts"],"names":[],"mappings":"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"}
@@ -1,38 +1,74 @@
1
1
  /**
2
- * @internal Item sizes by DynamoDB's item-size rules, shared by `Batch.write`'s
3
- * versioned transactions (chunked by size) and the client-side size check of
4
- * `Transaction.transactWrite` and `EventStore.append` (#133).
2
+ * @internal Exact sizes by DynamoDB's own accounting (#144), the one measure
3
+ * the library uses: `Batch.write` chunks its versioned-put transactions by
4
+ * it, and the failure-time diagnosis of DynamoDB's write limits
5
+ * (`internal/WriteDiagnosis.ts`) names the item at fault by it. Nothing here
6
+ * refuses a write: DynamoDB's own limits are never pre-checked.
7
+ *
8
+ * The rules were measured on DynamoDB Local from the `Payload Size` its 4 MB
9
+ * rejection reports, and confirmed at the exact boundaries: an item of
10
+ * 409,600 bytes is accepted and 409,601 rejected; a transaction of 4,194,304
11
+ * bytes is accepted and 4,194,305 rejected.
12
+ *
13
+ * - An item is the sum over its attributes of `utf8(name) + size(value)`, with
14
+ * no per-item or per-attribute overhead.
15
+ * - `S`: UTF-8 bytes. `B`: byte length. `BOOL`, `NULL`: 1.
16
+ * - `N`: see {@link numberBytes} (at most 21 bytes, a negative one included).
17
+ * - `SS` / `NS` / `BS`: the sum of the elements' sizes, no overhead.
18
+ * - `L`: `3 + Σ (size(element) + 1)`. `M`: `3 + Σ (utf8(name) + size(value) + 1)`.
19
+ * - A transaction action: its item (a Put) or its key (any other action), plus
20
+ * each of its expressions — see {@link transactItemBytes}.
5
21
  */
6
22
  import type { AttributeValue, TransactWriteItem } from "@aws-sdk/client-dynamodb";
7
23
  /**
8
- * DynamoDB's limit on the aggregate size of the items in one
9
- * `TransactWriteItems` request: 4 MB, in the binary megabytes DynamoDB uses
10
- * for every size limit (an item's 400 KB is 409,600 bytes).
24
+ * DynamoDB's limit on the size of one `TransactWriteItems` request: 4 MB, in
25
+ * the binary megabytes DynamoDB uses for every size limit — 4,194,304 bytes,
26
+ * measured by {@link transactItemBytes}.
11
27
  */
12
28
  export declare const TRANSACT_WRITE_MAX_BYTES: number;
29
+ /** DynamoDB's limit on the size of one item: 400 KB, which is 409,600 bytes. */
30
+ export declare const ITEM_MAX_BYTES: number;
13
31
  export declare const utf8Bytes: (text: string) => number;
14
32
  /**
15
- * Which way a size errs. DynamoDB documents its sizes as approximate, so:
33
+ * A number's size as DynamoDB stores it. Zero is 1 byte. Otherwise: 1, plus
34
+ * one byte per base-100 digit pair of the magnitude — pairs aligned to the
35
+ * decimal point, all-zero pairs trimmed at both ends — plus 1 if negative,
36
+ * except when the magnitude takes the maximum 20 pairs: a number is never
37
+ * more than 21 bytes.
16
38
  *
17
- * - `"lower"` never counts more than DynamoDB does — a refusal on it never
18
- * refuses what DynamoDB would accept (the transaction check). Numbers count
19
- * as DynamoDB stores them: a byte per two significant digits (leading and
20
- * trailing zeros trimmed), plus one; list and map overheads aren't counted.
21
- * - `"upper"` never counts less — a budget on it never overfills (`Batch.write`
22
- * chunking). Numbers count by their characters plus one, and lists and maps
23
- * carry three bytes plus one per element.
39
+ * Measured: `1`, `10`, `99`, `100`, `1200`, `1e10`, `0.5`, `0.05`, `0.0012`,
40
+ * `9.9E+125` → 2; `101`, `120`, `1234`, `1.5`, `12.34`, `10.01` → 3;
41
+ * `12345`, `1.234`, `-123` → 4; `-1` → 3; a 38-digit integer → 20;
42
+ * `-123456789012345678901234567890123456.78` (19 pairs) → 21;
43
+ * `-9.9999999999999999999999999999999999999` and
44
+ * `-1.2345678901234567890123456789012345678` (20 pairs) → 21.
24
45
  */
25
- export type SizeBound = "lower" | "upper";
26
- /** An attribute value's size toward its item's, erring the way `bound` says. */
27
- export declare const attributeBytes: (value: AttributeValue, bound?: SizeBound) => number;
28
- /** An item's size: its attribute names plus their values. */
29
- export declare const itemBytes: (item: Record<string, AttributeValue>, bound?: SizeBound) => number;
46
+ export declare const numberBytes: (n: string) => number;
47
+ /** An attribute value's size, by the rules in this module's header. */
48
+ export declare const attributeBytes: (value: AttributeValue) => number;
49
+ /** An item's size: its attribute names plus their values. What the 400 KB limit measures. */
50
+ export declare const itemBytes: (item: Record<string, AttributeValue>) => number;
30
51
  /**
31
- * A lower bound on what one transact entry contributes to its transaction's
32
- * size, as far as the request shows it: a Put's whole item; a Delete's,
33
- * ConditionCheck's or Update's key. (An Update's values aren't counted: some
34
- * may be its condition's, and the item it writes is the stored one updated,
35
- * which the request does not carry.)
52
+ * An expression's contribution to a transaction's size: its UTF-8 length as
53
+ * written, plus, for every placeholder **occurrence**, the substituted name's
54
+ * UTF-8 bytes (`#name`) or value's size (`:value`). A placeholder the maps do
55
+ * not define adds nothing (DynamoDB rejects such a request anyway).
56
+ *
57
+ * Expressions count toward the 4 MB transaction limit, never toward an item's
58
+ * 400 KB.
59
+ */
60
+ export declare const expressionBytes: (expression: string | undefined, names: Record<string, string> | undefined, values: Record<string, AttributeValue> | undefined) => number;
61
+ /**
62
+ * One action's contribution to its `TransactWriteItems` request's size:
63
+ *
64
+ * - a Put's item, or an Update's, Delete's or ConditionCheck's key — never the
65
+ * stored item, nor the item an Update produces;
66
+ * - plus each of its expressions (`ConditionExpression`, an Update's
67
+ * `UpdateExpression`) by {@link expressionBytes}.
68
+ *
69
+ * `TableName` and `ReturnValuesOnConditionCheckFailure` add nothing.
36
70
  */
37
71
  export declare const transactItemBytes: (item: TransactWriteItem) => number;
72
+ /** A `TransactWriteItems` request's size: the sum of its actions' contributions. */
73
+ export declare const transactionBytes: (items: ReadonlyArray<TransactWriteItem>) => number;
38
74
  //# sourceMappingURL=ItemSize.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ItemSize.d.ts","sourceRoot":"","sources":["../../src/internal/ItemSize.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAEjF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,QAAkB,CAAA;AAEvD,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,KAAG,MAA+C,CAAA;AAExF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAA;AAgBzC,gFAAgF;AAChF,eAAO,MAAM,cAAc,GAAI,OAAO,cAAc,EAAE,QAAO,SAAmB,KAAG,MAgBlF,CAAA;AAED,6DAA6D;AAC7D,eAAO,MAAM,SAAS,GACpB,MAAM,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EACpC,QAAO,SAAmB,KACzB,MAIA,CAAA;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,iBAAiB,KAAG,MAG3D,CAAA"}
1
+ {"version":3,"file":"ItemSize.d.ts","sourceRoot":"","sources":["../../src/internal/ItemSize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAEjF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,QAAkB,CAAA;AAEvD,gFAAgF;AAChF,eAAO,MAAM,cAAc,QAAa,CAAA;AAIxC,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,KAAG,MAAqC,CAAA;AAE9E;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,WAAW,GAAI,GAAG,MAAM,KAAG,MAkBvC,CAAA;AAED,uEAAuE;AACvE,eAAO,MAAM,cAAc,GAAI,OAAO,cAAc,KAAG,MAgBtD,CAAA;AAED,6FAA6F;AAC7F,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,KAAG,MAI9D,CAAA;AAIH;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAC1B,YAAY,MAAM,GAAG,SAAS,EAC9B,OAAO,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACzC,QAAQ,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,SAAS,KACjD,MAaF,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,iBAAiB,KAAG,MAc3D,CAAA;AAED,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,GAAI,OAAO,aAAa,CAAC,iBAAiB,CAAC,KAAG,MACZ,CAAA"}
@@ -1,62 +1,145 @@
1
1
  /**
2
- * @internal Item sizes by DynamoDB's item-size rules, shared by `Batch.write`'s
3
- * versioned transactions (chunked by size) and the client-side size check of
4
- * `Transaction.transactWrite` and `EventStore.append` (#133).
2
+ * @internal Exact sizes by DynamoDB's own accounting (#144), the one measure
3
+ * the library uses: `Batch.write` chunks its versioned-put transactions by
4
+ * it, and the failure-time diagnosis of DynamoDB's write limits
5
+ * (`internal/WriteDiagnosis.ts`) names the item at fault by it. Nothing here
6
+ * refuses a write: DynamoDB's own limits are never pre-checked.
7
+ *
8
+ * The rules were measured on DynamoDB Local from the `Payload Size` its 4 MB
9
+ * rejection reports, and confirmed at the exact boundaries: an item of
10
+ * 409,600 bytes is accepted and 409,601 rejected; a transaction of 4,194,304
11
+ * bytes is accepted and 4,194,305 rejected.
12
+ *
13
+ * - An item is the sum over its attributes of `utf8(name) + size(value)`, with
14
+ * no per-item or per-attribute overhead.
15
+ * - `S`: UTF-8 bytes. `B`: byte length. `BOOL`, `NULL`: 1.
16
+ * - `N`: see {@link numberBytes} (at most 21 bytes, a negative one included).
17
+ * - `SS` / `NS` / `BS`: the sum of the elements' sizes, no overhead.
18
+ * - `L`: `3 + Σ (size(element) + 1)`. `M`: `3 + Σ (utf8(name) + size(value) + 1)`.
19
+ * - A transaction action: its item (a Put) or its key (any other action), plus
20
+ * each of its expressions — see {@link transactItemBytes}.
5
21
  */
6
22
  /**
7
- * DynamoDB's limit on the aggregate size of the items in one
8
- * `TransactWriteItems` request: 4 MB, in the binary megabytes DynamoDB uses
9
- * for every size limit (an item's 400 KB is 409,600 bytes).
23
+ * DynamoDB's limit on the size of one `TransactWriteItems` request: 4 MB, in
24
+ * the binary megabytes DynamoDB uses for every size limit — 4,194,304 bytes,
25
+ * measured by {@link transactItemBytes}.
10
26
  */
11
27
  export const TRANSACT_WRITE_MAX_BYTES = 4 * 1024 * 1024;
12
- export const utf8Bytes = (text) => new TextEncoder().encode(text).length;
13
- /** A number's significant digits: sign, point and exponent dropped, zeros trimmed. */
14
- const significantDigits = (n) => {
15
- const mantissa = n.split(/[eE]/)[0] ?? "";
16
- const digits = mantissa.replace(/[-+.]/g, "").replace(/^0+/, "").replace(/0+$/, "");
17
- return digits.length;
18
- };
19
- const numberBytes = (n, bound) => {
20
- if (bound === "upper")
21
- return n.length + 1;
22
- // Zero has no significant digits, and is stored in one byte.
23
- const digits = significantDigits(n);
24
- return digits === 0 ? 1 : Math.ceil(digits / 2) + 1;
28
+ /** DynamoDB's limit on the size of one item: 400 KB, which is 409,600 bytes. */
29
+ export const ITEM_MAX_BYTES = 400 * 1024;
30
+ const encoder = new TextEncoder();
31
+ export const utf8Bytes = (text) => encoder.encode(text).length;
32
+ /**
33
+ * A number's size as DynamoDB stores it. Zero is 1 byte. Otherwise: 1, plus
34
+ * one byte per base-100 digit pair of the magnitude — pairs aligned to the
35
+ * decimal point, all-zero pairs trimmed at both ends — plus 1 if negative,
36
+ * except when the magnitude takes the maximum 20 pairs: a number is never
37
+ * more than 21 bytes.
38
+ *
39
+ * Measured: `1`, `10`, `99`, `100`, `1200`, `1e10`, `0.5`, `0.05`, `0.0012`,
40
+ * `9.9E+125` → 2; `101`, `120`, `1234`, `1.5`, `12.34`, `10.01` → 3;
41
+ * `12345`, `1.234`, `-123` → 4; `-1` → 3; a 38-digit integer → 20;
42
+ * `-123456789012345678901234567890123456.78` (19 pairs) → 21;
43
+ * `-9.9999999999999999999999999999999999999` and
44
+ * `-1.2345678901234567890123456789012345678` (20 pairs) → 21.
45
+ */
46
+ export const numberBytes = (n) => {
47
+ let text = n.trim();
48
+ const negative = text.startsWith("-");
49
+ if (negative || text.startsWith("+"))
50
+ text = text.slice(1);
51
+ const [mantissa = "", exponent] = text.split(/[eE]/);
52
+ const [whole = "", fraction = ""] = mantissa.split(".");
53
+ const all = whole + fraction;
54
+ const leading = /^0*/.exec(all)[0].length;
55
+ const digits = all.slice(leading).replace(/0+$/, "");
56
+ if (digits.length === 0)
57
+ return 1;
58
+ // How many significant digits sit before the decimal point (negative: the
59
+ // first one sits that many places after it). Pairs are aligned to the point,
60
+ // so an odd count leaves the first digit alone in its pair.
61
+ const beforePoint = whole.length + Number(exponent ?? 0) - leading;
62
+ const aligned = (Math.abs(beforePoint) % 2 === 1 ? 1 : 0) + digits.length;
63
+ const pairs = Math.ceil(aligned / 2);
64
+ // The sign byte is left off at the maximum 20 pairs (measured).
65
+ return 1 + pairs + (negative && pairs < 20 ? 1 : 0);
25
66
  };
26
- /** An attribute value's size toward its item's, erring the way `bound` says. */
27
- export const attributeBytes = (value, bound = "lower") => {
67
+ /** An attribute value's size, by the rules in this module's header. */
68
+ export const attributeBytes = (value) => {
28
69
  if (value.S !== undefined)
29
70
  return utf8Bytes(value.S);
30
71
  if (value.N !== undefined)
31
- return numberBytes(value.N, bound);
72
+ return numberBytes(value.N);
32
73
  if (value.B !== undefined)
33
74
  return value.B.byteLength;
75
+ if (value.BOOL !== undefined || value.NULL !== undefined)
76
+ return 1;
34
77
  if (value.SS !== undefined)
35
78
  return value.SS.reduce((sum, v) => sum + utf8Bytes(v), 0);
36
79
  if (value.NS !== undefined)
37
- return value.NS.reduce((sum, v) => sum + numberBytes(v, bound), 0);
80
+ return value.NS.reduce((sum, v) => sum + numberBytes(v), 0);
38
81
  if (value.BS !== undefined)
39
82
  return value.BS.reduce((sum, v) => sum + v.byteLength, 0);
40
- const overhead = bound === "upper";
41
- if (value.L !== undefined) {
42
- return value.L.reduce((sum, v) => sum + attributeBytes(v, bound) + (overhead ? 1 : 0), overhead ? 3 : 0);
83
+ if (value.L !== undefined)
84
+ return value.L.reduce((sum, v) => sum + attributeBytes(v) + 1, 3);
85
+ if (value.M !== undefined) {
86
+ return Object.entries(value.M).reduce((sum, [name, v]) => sum + utf8Bytes(name) + attributeBytes(v) + 1, 3);
87
+ }
88
+ return 0;
89
+ };
90
+ /** An item's size: its attribute names plus their values. What the 400 KB limit measures. */
91
+ export const itemBytes = (item) => Object.entries(item).reduce((sum, [name, value]) => sum + utf8Bytes(name) + attributeBytes(value), 0);
92
+ const PLACEHOLDER = /[#:][A-Za-z0-9_]+/g;
93
+ /**
94
+ * An expression's contribution to a transaction's size: its UTF-8 length as
95
+ * written, plus, for every placeholder **occurrence**, the substituted name's
96
+ * UTF-8 bytes (`#name`) or value's size (`:value`). A placeholder the maps do
97
+ * not define adds nothing (DynamoDB rejects such a request anyway).
98
+ *
99
+ * Expressions count toward the 4 MB transaction limit, never toward an item's
100
+ * 400 KB.
101
+ */
102
+ export const expressionBytes = (expression, names, values) => {
103
+ if (expression === undefined)
104
+ return 0;
105
+ let bytes = utf8Bytes(expression);
106
+ for (const [placeholder] of expression.matchAll(PLACEHOLDER)) {
107
+ if (placeholder.startsWith("#")) {
108
+ const name = names?.[placeholder];
109
+ if (name !== undefined)
110
+ bytes += utf8Bytes(name);
111
+ }
112
+ else {
113
+ const value = values?.[placeholder];
114
+ if (value !== undefined)
115
+ bytes += attributeBytes(value);
116
+ }
43
117
  }
44
- if (value.M !== undefined)
45
- return itemBytes(value.M, bound) + (overhead ? 3 : 0);
46
- return 1;
118
+ return bytes;
47
119
  };
48
- /** An item's size: its attribute names plus their values. */
49
- export const itemBytes = (item, bound = "lower") => Object.entries(item).reduce((sum, [name, value]) => sum + utf8Bytes(name) + attributeBytes(value, bound), 0);
50
120
  /**
51
- * A lower bound on what one transact entry contributes to its transaction's
52
- * size, as far as the request shows it: a Put's whole item; a Delete's,
53
- * ConditionCheck's or Update's key. (An Update's values aren't counted: some
54
- * may be its condition's, and the item it writes is the stored one updated,
55
- * which the request does not carry.)
121
+ * One action's contribution to its `TransactWriteItems` request's size:
122
+ *
123
+ * - a Put's item, or an Update's, Delete's or ConditionCheck's key — never the
124
+ * stored item, nor the item an Update produces;
125
+ * - plus each of its expressions (`ConditionExpression`, an Update's
126
+ * `UpdateExpression`) by {@link expressionBytes}.
127
+ *
128
+ * `TableName` and `ReturnValuesOnConditionCheckFailure` add nothing.
56
129
  */
57
130
  export const transactItemBytes = (item) => {
58
- if (item.Put !== undefined)
59
- return itemBytes(item.Put.Item ?? {});
60
- return itemBytes(item.Delete?.Key ?? item.Update?.Key ?? item.ConditionCheck?.Key ?? {});
131
+ const action = item.Put ?? item.Update ?? item.Delete ?? item.ConditionCheck;
132
+ if (action === undefined)
133
+ return 0;
134
+ const names = action.ExpressionAttributeNames;
135
+ const values = action.ExpressionAttributeValues;
136
+ const base = item.Put !== undefined
137
+ ? itemBytes(item.Put.Item ?? {})
138
+ : itemBytes((item.Update ?? item.Delete ?? item.ConditionCheck)?.Key ?? {});
139
+ return (base +
140
+ expressionBytes(action.ConditionExpression, names, values) +
141
+ expressionBytes(item.Update?.UpdateExpression, names, values));
61
142
  };
143
+ /** A `TransactWriteItems` request's size: the sum of its actions' contributions. */
144
+ export const transactionBytes = (items) => items.reduce((sum, item) => sum + transactItemBytes(item), 0);
62
145
  //# sourceMappingURL=ItemSize.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ItemSize.js","sourceRoot":"","sources":["../../src/internal/ItemSize.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ItemSize.js","sourceRoot":"","sources":["../../src/internal/ItemSize.ts"],"names":[],"mappings":"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"}