/** * Discover users from relays and backfill their records from PDS. * * Usage: * pnpm sync # local D1 * pnpm sync:remote # prod D1 */ import { Contrail } from '@atmo-dev/contrail'; import { config } from '../src/lib/contrail/config'; import { getPlatformProxy } from 'wrangler'; function elapsed(start: number): string { const ms = Date.now() - start; if (ms < 1000) return `${ms}ms`; if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`; const mins = Math.floor(ms / 60_000); const secs = ((ms % 60_000) / 1000).toFixed(0); return `${mins}m ${secs}s`; } async function main() { const remote = process.argv.includes('--remote'); const syncStart = Date.now(); console.log(`=== Sync (${remote ? 'remote/prod' : 'local'} D1) ===\n`); const { env, dispose } = await getPlatformProxy<{ DB: D1Database }>({ environment: remote ? 'production' : undefined }); const contrail = new Contrail({ ...config, db: env.DB }); try { await contrail.init(); console.log('--- Discovery ---'); const discoveryStart = Date.now(); const discovered = await contrail.discover(); console.log(` Done: ${discovered.length} users in ${elapsed(discoveryStart)}\n`); console.log('--- Backfill ---'); const backfillStart = Date.now(); const total = await contrail.backfill({ concurrency: 100, onProgress: ({ records, usersComplete, usersTotal, usersFailed }) => { const secs = (Date.now() - backfillStart) / 1000; const rate = secs > 0 ? Math.round(records / secs) : 0; const failStr = usersFailed > 0 ? ` | ${usersFailed} failed` : ''; process.stdout.write( `\r ${records} records | ${usersComplete}/${usersTotal} users | ${rate}/s | ${elapsed(backfillStart)}${failStr} ` ); } }); process.stdout.write('\n'); console.log(` Done: ${total} records in ${elapsed(backfillStart)}\n`); console.log(`=== Finished in ${elapsed(syncStart)} ===`); console.log(` Discovered: ${discovered.length} users`); console.log(` Backfilled: ${total} records`); } finally { await dispose(); } } main().catch((err) => { console.error(err); process.exit(1); });