@@ -1254,7 +1254,9 @@ async function migrateUserSsoLogin() {
12541254
12551255async 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
13051345async function migrateUserStatusLu ( ) {
0 commit comments