Skip to content

Commit a74fd5b

Browse files
committed
feat: prompt y/c/N when create-db-dump would wipe existing in-progress data
1 parent 8b98a0e commit a74fd5b

1 file changed

Lines changed: 57 additions & 5 deletions

File tree

scripts/create-db-dump.ts

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as fs from 'fs'
55
import { createServer } from 'net'
66
import * as path from 'path'
77
import { Pool } from 'pg'
8+
import { createInterface } from 'readline'
89
import { setTimeout as delay } from 'timers/promises'
910
import { createPublicClient, http } from 'viem'
1011

@@ -22,13 +23,14 @@ type ProcessorName =
2223
function parseArgs() {
2324
const args = process.argv.slice(2)
2425
if (args.length === 0) {
25-
console.error('Usage: tsx create-db-dump.ts <processor-name> [--profile <aws-profile>] [--continue]')
26+
console.error('Usage: tsx create-db-dump.ts <processor-name> [--profile <aws-profile>] [--continue] [-y|--yes]')
2627
process.exit(1)
2728
}
2829

2930
const processorName = args[0] as ProcessorName
3031
let awsProfile: string | undefined
3132
let continueRun = false
33+
let assumeYes = false
3234

3335
for (let i = 1; i < args.length; i++) {
3436
const arg = args[i]
@@ -40,9 +42,12 @@ function parseArgs() {
4042
if (arg === '--continue') {
4143
continueRun = true
4244
}
45+
if (arg === '-y' || arg === '--yes') {
46+
assumeYes = true
47+
}
4348
}
4449

45-
return { processorName, awsProfile, continueRun }
50+
return { processorName, awsProfile, continueRun, assumeYes }
4651
}
4752

4853
function getProcessorAlias(processorName: ProcessorName): string {
@@ -131,6 +136,23 @@ async function findFreePort(preferredStart = 24000, preferredEnd = 65000): Promi
131136
throw new Error('No free port found')
132137
}
133138

139+
async function promptYNC(message: string): Promise<'y' | 'n' | 'c'> {
140+
if (!process.stdin.isTTY) {
141+
console.error('Non-interactive shell: refusing to wipe existing data. Re-run with --continue or use -y.')
142+
process.exit(1)
143+
}
144+
const rl = createInterface({ input: process.stdin, output: process.stdout })
145+
try {
146+
const answer: string = await new Promise((resolve) => rl.question(message, resolve))
147+
const a = answer.trim().toLowerCase()
148+
if (a === 'y' || a === 'yes') return 'y'
149+
if (a === 'c' || a === 'continue') return 'c'
150+
return 'n'
151+
} finally {
152+
rl.close()
153+
}
154+
}
155+
134156
async function getExistingDbPort(composeProject: string): Promise<number | null> {
135157
try {
136158
const { stdout } = await runCmd(`docker ps --filter "name=^\/${composeProject}-db-1$" --format "{{.Ports}}"`, {
@@ -227,7 +249,9 @@ async function main() {
227249
dotenv.config({ path: devEnvPath, override: false })
228250
}
229251

230-
const { processorName, awsProfile, continueRun } = parseArgs()
252+
const parsed = parseArgs()
253+
const { processorName, awsProfile, assumeYes } = parsed
254+
let continueRun = parsed.continueRun
231255
const alias = getProcessorAlias(processorName)
232256

233257
// Determine RPC URL for the chain
@@ -255,13 +279,41 @@ async function main() {
255279
const composeProject = `squid_${alias}`
256280
let DB_PORT = 0
257281
let startedCompose = false
282+
const existingPort = await getExistingDbPort(composeProject)
283+
284+
// Guard against the common mistake: forgetting --continue, which would wipe the in-progress dump.
285+
if (existingPort && !continueRun && !assumeYes) {
286+
console.warn(``)
287+
console.warn(`Existing dockerized Postgres found for '${processorName}'`)
288+
console.warn(` compose project: ${composeProject}`)
289+
console.warn(` port: ${existingPort}`)
290+
console.warn(``)
291+
console.warn(`Running without --continue would WIPE this data (--volumes) and restart from scratch.`)
292+
console.warn(`Each full reprocess takes hours — this is almost certainly NOT what you want.`)
293+
console.warn(``)
294+
console.warn(` [y] yes, wipe and start over from scratch`)
295+
console.warn(` [c] continue from existing data (acts as if --continue was passed)`)
296+
console.warn(` [n] no, abort (default)`)
297+
console.warn(``)
298+
const choice = await promptYNC(`choice [y/c/N]: `)
299+
if (choice === 'n') {
300+
console.log('Aborted.')
301+
process.exit(0)
302+
}
303+
if (choice === 'c') {
304+
console.log(`→ continuing from existing data`)
305+
continueRun = true
306+
} else {
307+
console.log(`→ wiping existing data and starting over`)
308+
}
309+
}
310+
258311
if (continueRun) {
259-
const existingPort = await getExistingDbPort(composeProject)
260312
if (existingPort) {
261313
DB_PORT = existingPort
262314
console.log(`Reusing existing dockerized Postgres at port ${DB_PORT} (project ${composeProject})...`)
263315
} else {
264-
console.log(`No existing Postgres found.`)
316+
console.log(`No existing Postgres found; --continue requires existing data. Aborting.`)
265317
process.exit(1)
266318
}
267319
} else {

0 commit comments

Comments
 (0)