Skip to content

Commit 23ab3a4

Browse files
committed
Better error handling for user_otp_email table
1 parent 18d1f8e commit 23ab3a4

File tree

1 file changed

+47
-7
lines changed

1 file changed

+47
-7
lines changed

legacy_migrate/src/migrate.ts

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,7 +1254,9 @@ async function migrateUserSsoLogin() {
12541254

12551255
async function migrateUserOtpEmail() {
12561256
console.log('→ user_otp_email');
1257-
let skip = 0, total = 0;
1257+
let skip = 0,
1258+
total = 0,
1259+
failures = 0;
12581260
while (true) {
12591261
const batch: Rows<typeof sourceIdentity.user_otp_email.findMany> =
12601262
await sourceIdentity.user_otp_email.findMany(
@@ -1270,7 +1272,7 @@ async function migrateUserOtpEmail() {
12701272
);
12711273
if (batch.length === 0) break;
12721274

1273-
await target.$transaction(
1275+
const results = await Promise.allSettled(
12741276
batch.map((r: any) =>
12751277
target.user_otp_email.upsert({
12761278
where: { id: r.id },
@@ -1292,14 +1294,52 @@ async function migrateUserOtpEmail() {
12921294
fail_count: r.fail_count ?? 0,
12931295
},
12941296
})
1295-
),
1296-
{ timeout: 120_000 }
1297+
)
12971298
);
12981299

1299-
total += batch.length; skip += batch.length;
1300-
console.log(` … ${total}`);
1300+
results.forEach((result, idx) => {
1301+
if (result.status === 'fulfilled') {
1302+
total += 1;
1303+
return;
1304+
}
1305+
1306+
const err: any = result.reason;
1307+
const record = batch[idx];
1308+
failures += 1;
1309+
1310+
if (err?.code === 'P2003' && err?.meta?.constraint === 'user_otp_email_user_id_fkey') {
1311+
appendNdjson('bad-user-otp-email.ndjson', {
1312+
reason: 'foreign key violation: user missing',
1313+
id: record.id,
1314+
user_id: record.user_id,
1315+
mode: record.mode,
1316+
otp: record.otp,
1317+
expire_at: record.expire_at,
1318+
resend: record.resend ?? null,
1319+
fail_count: record.fail_count ?? null,
1320+
error: err.message,
1321+
});
1322+
} else {
1323+
appendNdjson('bad-user-otp-email.ndjson', {
1324+
reason: 'unexpected error',
1325+
id: record.id,
1326+
user_id: record.user_id,
1327+
mode: record.mode,
1328+
otp: record.otp,
1329+
expire_at: record.expire_at,
1330+
resend: record.resend ?? null,
1331+
fail_count: record.fail_count ?? null,
1332+
error: err?.message ?? String(err),
1333+
});
1334+
}
1335+
});
1336+
1337+
skip += batch.length;
1338+
console.log(` … imported=${total} (failed=${failures} so far)`);
13011339
}
1302-
console.log(`✓ user_otp_email: ${total}`);
1340+
const summarySuffix =
1341+
failures > 0 ? `, failed=${failures}. See logs/bad-user-otp-email.ndjson` : '';
1342+
console.log(`✓ user_otp_email: imported=${total}${summarySuffix}`);
13031343
}
13041344

13051345
async function migrateUserStatusLu() {

0 commit comments

Comments
 (0)