db.ts
@file Interaction idempotency and the /build cooldown.
Overview
@file Interaction idempotency and the /build cooldown.
The hardware registry itself lives in rigs.ts, against the rigs table.
This file is what is left once that moved: the two tables that exist to stop
a command running twice rather than to remember anything about hardware.
Nothing outside this file and rigs.ts writes SQL, and neither builds SQL by
concatenation. Each query is a constant with bound parameters, so a value
arriving from a Discord field cannot become syntax.
depends on rigs.ts · used by build.ts help-me.ts
flowchart TD checkAndStartCooldown --> need
API
Fexport async function claimInteraction(db: D1Database | undefined, interactionId: string): Promise<boolean>
Claim an interaction ID, once. True means this caller owns it and should do the work. False means a previous delivery already did: Discord retries, and a retry must not open a second thread. Throws RegistryUnavailable when D1 is not reachable, and the caller is expected to proceed anyway. Losing deduplication costs a duplicate thread; refusing to act costs the report entirely, and the second is worse.
handler, onModalSubmit · calls needFexport async function checkAndStartCooldown(db: D1Database | undefined, userId: string, cooldownMs: number, now: number): Promise<CooldownCheck>
Check a user's /build cooldown and, if it has expired, start a new one atomically in the same statement.
handler · calls needUndocumented (1)
need