Skip to content

Commit

Permalink
D1: using new polling endpoint for larger exports
Browse files Browse the repository at this point in the history
  • Loading branch information
geelen committed Apr 11, 2024
1 parent cd03d1d commit 4bd789b
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 22 deletions.
10 changes: 9 additions & 1 deletion packages/wrangler/src/d1/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
export const DEFAULT_MIGRATION_PATH = "./migrations";
export const DEFAULT_MIGRATION_TABLE = "d1_migrations";
export const LOCATION_CHOICES = ["weur", "eeur", "apac", "wnam", "enam"];
export const LOCATION_CHOICES = [
"weur",
"eeur",
"apac",
"wnam",
"enam",
"oc",
"eagle",
];
// Max number of statements to send in a single /execute call
export const DEFAULT_BATCH_SIZE = 10_000;
111 changes: 90 additions & 21 deletions packages/wrangler/src/d1/export.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import fs from "node:fs/promises";
import chalk from "chalk";
import { fetch } from "undici";
import { printWranglerBanner } from "..";
import { fetchResult } from "../cfetch";
import { performApiFetch } from "../cfetch/internal";
import { readConfig } from "../config";
import { UserError } from "../errors";
import { logger } from "../logger";
Expand Down Expand Up @@ -80,8 +82,22 @@ export const Handler = async (args: HandlerOptions): Promise<void> => {
return result;
};

type ExportMetadata = {
signedUrl: string;
type PollingResponse = {
success: true;
result: {
type: "export";
at_bookmark: string;
messages: string[];
errors: string[];
} & (
| {
status: "active" | "error";
}
| {
status: "complete";
result: { filename: string; signedUrl: string };
}
);
};

async function exportRemotely(
Expand All @@ -101,26 +117,79 @@ async function exportRemotely(

logger.log(`🌀 Executing on remote database ${name} (${db.uuid}):`);
logger.log(`🌀 Creating export...`);
const metadata = await fetchResult<ExportMetadata>(
`/accounts/${accountId}/d1/database/${db.uuid}/export`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
outputFormat: "file",
dumpOptions: {
noSchema,
noData,
tables,
},
}),
}
);
const dumpOptions = {
noSchema,
noData,
tables,
};

const { result } = await pollExport(accountId, db, dumpOptions, undefined);

logger.log(`🌀 Downloading SQL to ${output}`);
const contents = await fetch(metadata.signedUrl);
if (result.status !== "complete")
throw new Error(`Error: D1 reset before export completed!`);

logger.log(`🌀 Downloading SQL to ${output}...`);
logger.log(
chalk.gray(
`If this download fails, you can retry downloading the following URL manually. It is valid for 1 hour: ${result.result.signedUrl}`
)
);
const contents = await fetch(result.result.signedUrl);
await fs.writeFile(output, contents.body || "");
logger.log(`Done!`);
}

async function pollExport(
accountId: string,
db: Database,
dumpOptions: {
tables: string[];
noSchema?: boolean;
noData?: boolean;
},
currentBookmark: string | undefined,
num_parts_uploaded: number = 0
): Promise<PollingResponse> {
const response = await fetchResult<
PollingResponse | { success: false; error: string }
>(`/accounts/${accountId}/d1/database/${db.uuid}/export`, {
method: "POST",
headers: {
"x-d1-internal-env": "staging",
},
body: JSON.stringify({
outputFormat: "polling",
dumpOptions: {
...dumpOptions,
limit: 790000,
},
currentBookmark,
}),
});

if (!response.success) throw new Error(response.error);

response.result.messages.forEach((line) => {
if (line.startsWith(`Uploaded part`)) {
// Part numbers can be reported as complete out-of-order which looks confusing to a user. But their ID has no
// special meaning, so just make them sequential.
console.log(`🌀 Uploaded part ${++num_parts_uploaded}`);
} else {
console.log(`🌀 ${line}`);
}
});

if (response.result.status === "complete") {
return response;
} else if (response.result.status === "error") {
throw new Error(response.result.errors.join("\n"));
} else {
return await pollExport(
accountId,
db,
dumpOptions,
response.result.at_bookmark,
num_parts_uploaded
);
}
}

0 comments on commit 4bd789b

Please sign in to comment.