fix(teams): the two defects the phase 9 rig walk found
Walked against real MariaDB, the real app, and a fake standing in for Discord
that mounts the bot's real internal routes — everything up to the Discord API
call was production code. 47 assertions, and it found two things every unit
test in the phase had passed over.
1. **Every query failed: two result columns named `team_id`.** `desiredTeams`
and `holdersWithoutClaim` both select `t.id AS team_id`, and the shared
column list added `i.team_id` beside it. The `mariadb` driver refuses a
result set with a repeated field name outright, so the pass died at its
first query with "Error in results, duplicate field name `team_id`" — on the
one code path every unit test stubs.
It was also the wrong column: `desiredTeams` LEFT JOINs, so `i.team_id` is
NULL for exactly the Teams that have no channel yet, which is the create
case. The two queries that do not join `teams` now ask for it by name.
The regression test checks the INTERPOLATED sql captured from a fake
`query`, not the source text — in the source the shared list is still a
`${COLUMNS}` placeholder, and a first attempt that read the file passed
happily with the bug reintroduced.
2. **"Sync now" said "Nothing was done" while it was doing it.** Saving the
settings with voice switched on asks for a pass. An operator who then
presses Sync now — the obvious next thing — hit `running` and got back
`ran: false, reason: "a pass is already running"`, which the panel renders
as nothing having happened, while the pass they triggered was busy creating
their channels. A pass in flight is now JOINED and its real outcome
returned, the same choice `teamSync.reconcileNow` makes for the same reason.
Tests: 1162 server (+2), 53 bot, 284 client.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -46,6 +46,9 @@ const DEBOUNCE_MS = 30_000
|
||||
|
||||
let running = false
|
||||
let rerun = false
|
||||
// The promise of the pass currently in flight, so a second caller can await the
|
||||
// same work rather than be told there is none.
|
||||
let inFlight = null
|
||||
let lastRunAt = 0
|
||||
let debounceTimer = null
|
||||
|
||||
@@ -311,12 +314,36 @@ async function runOnce(reason) {
|
||||
return summary
|
||||
}
|
||||
|
||||
/** Run now, awaited, with the lock held. The admin "sync now" button uses this. */
|
||||
/**
|
||||
* Run now, awaited. The admin "Sync now" button uses this.
|
||||
*
|
||||
* **A pass already in flight is JOINED, not refused**, the same choice
|
||||
* `teamSync.reconcileNow` makes and for the same reason: the caller wants "Discord
|
||||
* now matches", and a pass that started a moment ago delivers exactly that.
|
||||
*
|
||||
* Refusing was the first thing written here and it was wrong in a way only the rig
|
||||
* showed. Saving the settings with voice switched on asks for a pass; an operator
|
||||
* who then presses Sync now — which is the obvious next thing to do — got
|
||||
* `ran: false, reason: "a pass is already running"`, and the panel dutifully told
|
||||
* them **"Nothing was done"** while the pass they had just triggered was busy
|
||||
* creating their channels.
|
||||
*/
|
||||
async function passNow(reason = 'manual') {
|
||||
if (running) {
|
||||
rerun = true
|
||||
return { ran: false, reason: 'a pass is already running', joined: true }
|
||||
if (inFlight) return inFlight
|
||||
inFlight = execute(reason)
|
||||
try {
|
||||
return await inFlight
|
||||
} finally {
|
||||
inFlight = null
|
||||
if (rerun) {
|
||||
rerun = false
|
||||
request({ reason: 'continuation' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** The body `passNow` guards. Never throws — see the file header. */
|
||||
async function execute(reason) {
|
||||
running = true
|
||||
try {
|
||||
const result = await runOnce(reason)
|
||||
@@ -329,10 +356,6 @@ async function passNow(reason = 'manual') {
|
||||
return { ran: false, reason: err.message }
|
||||
} finally {
|
||||
running = false
|
||||
if (rerun) {
|
||||
rerun = false
|
||||
request({ reason: 'continuation' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,6 +410,7 @@ function _reset() {
|
||||
stop()
|
||||
running = false
|
||||
rerun = false
|
||||
inFlight = null
|
||||
lastRunAt = 0
|
||||
lastPassResult = { at: null, ran: false, reason: 'no pass has run yet' }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user