Skip to content

Commit 5462ead

Browse files
geelenRamIdeasCarmenPopoviciu
authored
D1 export api change (#6203)
* Adding staging header for export * Switched to snake_case for all D1 import/export actions * Update .changeset/lovely-teachers-breathe.md Co-authored-by: Carmen Popoviciu <[email protected]> * fix: mock export API should expect current_bookmark not currentBookmark * add small delay in recursive poll to avoid OOM within reasonable time periods --------- Co-authored-by: Rahul Sethi <[email protected]> Co-authored-by: Carmen Popoviciu <[email protected]>
1 parent fa42d7c commit 5462ead

File tree

5 files changed

+44
-30
lines changed

5 files changed

+44
-30
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
fix: Updating to match new D1 import/export API format

packages/wrangler/src/__tests__/d1/export.test.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import fs from "fs";
2+
import { setTimeout } from "node:timers/promises";
23
import { http, HttpResponse } from "msw";
34
import { mockAccountId, mockApiToken } from "../helpers/mock-account-id";
45
import { mockConsoleMethods } from "../helpers/mock-console";
@@ -9,7 +10,7 @@ import { runInTempDir } from "../helpers/run-in-tmp";
910
import { runWrangler } from "../helpers/run-wrangler";
1011
import writeWranglerToml from "../helpers/write-wrangler-toml";
1112

12-
describe("execute", () => {
13+
describe("export", () => {
1314
mockAccountId({ accountId: null });
1415
mockApiToken();
1516
mockConsoleMethods();
@@ -117,10 +118,16 @@ describe("execute", () => {
117118
http.post(
118119
"*/accounts/:accountId/d1/database/:databaseId/export",
119120
async ({ request }) => {
121+
// This endpoint is polled recursively. If we respond immediately,
122+
// the callstack builds up quickly leading to a hard-to-debug OOM error.
123+
// This timeout ensures that if the endpoint is accidently polled infinitely
124+
// the test will timeout before breaching available memory
125+
await setTimeout(10);
126+
120127
const body = (await request.json()) as Record<string, unknown>;
121128

122129
// First request, initiates a new task
123-
if (!body.currentBookmark) {
130+
if (!body.current_bookmark) {
124131
return HttpResponse.json(
125132
{
126133
success: true,
@@ -151,7 +158,7 @@ describe("execute", () => {
151158
status: "complete",
152159
result: {
153160
filename: "xxxx-yyyy.sql",
154-
signedUrl: "https://example.com/xxxx-yyyy.sql",
161+
signed_url: "https://example.com/xxxx-yyyy.sql",
155162
},
156163
messages: [
157164
"Uploaded part 3",

packages/wrangler/src/d1/execute.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -400,10 +400,10 @@ async function executeRemotely({
400400
startMessage: "Checking if file needs uploading",
401401
});
402402

403-
// An init response usually returns a {filename, uploadUrl} pair, except if we've detected that file
403+
// An init response usually returns a {filename, upload_url} pair, except if we've detected that file
404404
// already exists and is valid, to save people reuploading. In which case `initResponse` has already
405405
// kicked the import process off.
406-
const uploadRequired = "uploadUrl" in initResponse;
406+
const uploadRequired = "upload_url" in initResponse;
407407
if (!uploadRequired) {
408408
logger.log(`🌀 File already uploaded. Processing.`);
409409
}
@@ -432,29 +432,29 @@ async function executeRemotely({
432432
}
433433

434434
const {
435-
result: { numQueries, finalBookmark, meta },
435+
result: { num_queries, final_bookmark, meta },
436436
} = finalResponse;
437437
logger.log(
438-
`🚣 Executed ${numQueries} queries in ${(meta.duration / 1000).toFixed(
438+
`🚣 Executed ${num_queries} queries in ${(meta.duration / 1000).toFixed(
439439
2
440440
)} seconds (${meta.rows_read} rows read, ${
441441
meta.rows_written
442442
} rows written)\n` +
443-
chalk.gray(` Database is currently at bookmark ${finalBookmark}.`)
443+
chalk.gray(` Database is currently at bookmark ${final_bookmark}.`)
444444
);
445445

446446
return [
447447
{
448448
results: [
449449
{
450-
"Total queries executed": numQueries,
450+
"Total queries executed": num_queries,
451451
"Rows read": meta.rows_read,
452452
"Rows written": meta.rows_written,
453453
"Database size (MB)": (meta.size_after / 1_000_000).toFixed(2),
454454
},
455455
],
456456
success: true,
457-
finalBookmark,
457+
finalBookmark: final_bookmark,
458458
meta,
459459
},
460460
];
@@ -474,12 +474,12 @@ async function uploadAndBeginIngestion(
474474
etag: string,
475475
initResponse: ImportInitResponse
476476
) {
477-
const { uploadUrl, filename } = initResponse;
477+
const { upload_url, filename } = initResponse;
478478

479479
const { size } = await fs.stat(file);
480480

481481
const uploadResponse = await spinnerWhile({
482-
promise: fetch(uploadUrl, {
482+
promise: fetch(upload_url, {
483483
method: "PUT",
484484
headers: {
485485
"Content-length": `${size}`,
@@ -542,7 +542,7 @@ async function pollUntilComplete(
542542
"import",
543543
{
544544
action: "poll",
545-
currentBookmark: response.at_bookmark,
545+
current_bookmark: response.at_bookmark,
546546
}
547547
);
548548
return await pollUntilComplete(newResponse, accountId, db);

packages/wrangler/src/d1/export.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ async function exportRemotely(
171171

172172
logger.log(`🌀 Executing on remote database ${name} (${db.uuid}):`);
173173
const dumpOptions = {
174-
noSchema,
175-
noData,
174+
no_schema: noSchema,
175+
no_data: noData,
176176
tables,
177177
};
178178

@@ -189,14 +189,14 @@ async function exportRemotely(
189189

190190
logger.log(
191191
chalk.gray(
192-
`You can also download your export from the following URL manually. This link will be valid for one hour: ${finalResponse.result.signedUrl}`
192+
`You can also download your export from the following URL manually. This link will be valid for one hour: ${finalResponse.result.signed_url}`
193193
)
194194
);
195195

196196
await spinnerWhile({
197197
startMessage: `Downloading SQL to ${output}`,
198198
async promise() {
199-
const contents = await fetch(finalResponse.result.signedUrl);
199+
const contents = await fetch(finalResponse.result.signed_url);
200200
await fs.writeFile(output, contents.body || "");
201201
},
202202
});
@@ -209,8 +209,8 @@ async function pollExport(
209209
db: Database,
210210
dumpOptions: {
211211
tables: string[];
212-
noSchema?: boolean;
213-
noData?: boolean;
212+
no_schema?: boolean;
213+
no_data?: boolean;
214214
},
215215
currentBookmark: string | undefined,
216216
num_parts_uploaded = 0
@@ -219,10 +219,14 @@ async function pollExport(
219219
`/accounts/${accountId}/d1/database/${db.uuid}/export`,
220220
{
221221
method: "POST",
222+
headers: {
223+
...(db.internal_env ? { "x-d1-internal-env": db.internal_env } : {}),
224+
"content-type": "application/json",
225+
},
222226
body: JSON.stringify({
223-
outputFormat: "polling",
224-
dumpOptions,
225-
currentBookmark,
227+
output_format: "polling",
228+
dump_options: dumpOptions,
229+
current_bookmark: currentBookmark,
226230
}),
227231
}
228232
);
@@ -245,7 +249,7 @@ async function pollExport(
245249
return response;
246250
} else if (response.status === "error") {
247251
throw new APIError({
248-
text: response.errors.join("\n"),
252+
text: response.error,
249253
notes: response.messages.map((text) => ({ text })),
250254
});
251255
} else {

packages/wrangler/src/d1/types.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,8 @@ export interface D1QueriesGraphQLResponse {
106106
}
107107

108108
export type ImportInitResponse = {
109-
success: true;
110109
filename: string;
111-
uploadUrl: string;
110+
upload_url: string;
112111
};
113112
export type ImportPollingResponse = {
114113
success: true;
@@ -123,9 +122,8 @@ export type ImportPollingResponse = {
123122
| {
124123
status: "complete";
125124
result: {
126-
success: boolean;
127-
finalBookmark: string;
128-
numQueries: number;
125+
final_bookmark: string;
126+
num_queries: number;
129127
meta: {
130128
served_by: string;
131129
duration: number;
@@ -145,14 +143,14 @@ export type ExportPollingResponse = {
145143
type: "export";
146144
at_bookmark: string;
147145
messages: string[];
148-
errors: string[];
146+
error: string;
149147
} & (
150148
| {
151149
status: "active" | "error";
152150
}
153151
| {
154152
status: "complete";
155-
result: { filename: string; signedUrl: string };
153+
result: { filename: string; signed_url: string };
156154
}
157155
);
158156

0 commit comments

Comments
 (0)