Skip to content

Commit 2315f47

Browse files
fix: limit bulk put API requests to batches of 5,000
The `kv:bulk put` command now batches up put requests in groups of 5,000, displaying progress for each request.
1 parent 05282e9 commit 2315f47

File tree

4 files changed

+65
-11
lines changed

4 files changed

+65
-11
lines changed

.changeset/angry-countries-matter.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
fix: limit bulk put API requests to batches of 5,000
6+
7+
The `kv:bulk put` command now batches up put requests in groups of 5,000,
8+
displaying progress for each request.

packages/wrangler/src/__tests__/kv.test.ts

+29-2
Original file line numberDiff line numberDiff line change
@@ -1130,7 +1130,12 @@ describe("wrangler", () => {
11301130
requests.count++;
11311131
expect(accountId).toEqual("some-account-id");
11321132
expect(namespaceId).toEqual(expectedNamespaceId);
1133-
expect(JSON.parse(body as string)).toEqual(expectedKeyValues);
1133+
expect(JSON.parse(body as string)).toEqual(
1134+
expectedKeyValues.slice(
1135+
(requests.count - 1) * 5000,
1136+
requests.count * 5000
1137+
)
1138+
);
11341139
return null;
11351140
}
11361141
);
@@ -1150,7 +1155,29 @@ describe("wrangler", () => {
11501155
`kv:bulk put --namespace-id some-namespace-id keys.json`
11511156
);
11521157
expect(requests.count).toEqual(1);
1153-
expect(std.out).toMatchInlineSnapshot(`""`);
1158+
expect(std.out).toMatchInlineSnapshot(`"Success!"`);
1159+
expect(std.warn).toMatchInlineSnapshot(`""`);
1160+
expect(std.err).toMatchInlineSnapshot(`""`);
1161+
});
1162+
1163+
it("should put the key-values in batches of 5000 parsed from a file", async () => {
1164+
const keyValues: KeyValue[] = new Array(12000).fill({
1165+
key: "someKey1",
1166+
value: "someValue1",
1167+
});
1168+
writeFileSync("./keys.json", JSON.stringify(keyValues));
1169+
const requests = mockPutRequest("some-namespace-id", keyValues);
1170+
await runWrangler(
1171+
`kv:bulk put --namespace-id some-namespace-id keys.json`
1172+
);
1173+
expect(requests.count).toEqual(3);
1174+
expect(std.out).toMatchInlineSnapshot(`
1175+
"Uploaded 0 of 12000.
1176+
Uploaded 5000 of 12000.
1177+
Uploaded 10000 of 12000.
1178+
Uploaded 12000 of 12000.
1179+
Success!"
1180+
`);
11541181
expect(std.warn).toMatchInlineSnapshot(`""`);
11551182
expect(std.err).toMatchInlineSnapshot(`""`);
11561183
});

packages/wrangler/src/index.tsx

+10-1
Original file line numberDiff line numberDiff line change
@@ -2234,7 +2234,16 @@ export async function main(argv: string[]): Promise<void> {
22342234
}
22352235
}
22362236
// -- snip, end --
2237-
await putBulkKeyValue(config.account_id, namespaceId, content);
2237+
await putBulkKeyValue(
2238+
config.account_id,
2239+
namespaceId,
2240+
content,
2241+
(index, total) => {
2242+
console.log(`Uploaded ${index} of ${total}.`);
2243+
}
2244+
);
2245+
2246+
console.log("Success!");
22382247
}
22392248
)
22402249
.command(

packages/wrangler/src/kv.tsx

+18-8
Original file line numberDiff line numberDiff line change
@@ -169,16 +169,26 @@ export async function getKeyValue(
169169
export async function putBulkKeyValue(
170170
accountId: string,
171171
namespaceId: string,
172-
keyValues: KeyValue[]
172+
keyValues: KeyValue[],
173+
progressCallback: (index: number, total: number) => void
173174
) {
174-
return await fetchResult(
175-
`/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/bulk`,
176-
{
177-
method: "PUT",
178-
body: JSON.stringify(keyValues),
179-
headers: { "Content-Type": "application/json" },
175+
for (let index = 0; index < keyValues.length; index += BATCH_KEY_MAX) {
176+
if (progressCallback && keyValues.length > BATCH_KEY_MAX) {
177+
progressCallback(index, keyValues.length);
180178
}
181-
);
179+
180+
await fetchResult(
181+
`/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/bulk`,
182+
{
183+
method: "PUT",
184+
body: JSON.stringify(keyValues.slice(index, index + BATCH_KEY_MAX)),
185+
headers: { "Content-Type": "application/json" },
186+
}
187+
);
188+
}
189+
if (progressCallback && keyValues.length > BATCH_KEY_MAX) {
190+
progressCallback(keyValues.length, keyValues.length);
191+
}
182192
}
183193

184194
export async function deleteBulkKeyValue(

0 commit comments

Comments
 (0)