#2980: ticketing:auto-close is scheduled by this snap-in, not by the shell
A spawn of [dashboard-shell] #2965. The shell's routes/console.php carried Schedule::command('ticketing:auto-close') ->dailyAt(ScheduleStagger::dailyAt('ticketing:auto-close')); for a command only this repository defines, and two repositories deploy at different moments. On 2026-09-26 01:10 PDT production met the other end of that: `Command "admissions:remind-unconfirmed-links" is not defined`, exit 1, every tick for nine and a half hours, with nothing an operator could press — the code the schedule named was not on the box yet. TicketingServiceProvider::boot() now registers the event itself, beside the $this->commands() call that defines AutoCloseTickets. A box has both or neither, because they arrive in the same commit; a shell without this snap-in gets no row in `schedule:list` rather than a nightly failure about one. WHAT DID NOT MOVE. The time: ScheduleStagger is the shell's one place a start time is chosen — a bare ->daily() is 00:00:00, where the hourly and quarter-hourly maps already meet ([dashboard-shell] #1910) — so the provider asks dailyAt() and the job stays at 00:12 exactly. And the absence of a lock: the shell's line carried no withoutOverlapping() and this adds none, because a mutex grown in passing is a behaviour change wearing a move's clothes. PAIRED with the shell half on card/2980: the console line, the TheShellSchedulesNoSnapInCommandTest::BASELINE entry and the ScheduledJobCatalog::NOT_A_REGISTERED_JOB excuse all go in the same round as this lands, and tests/Feature/Ops/TicketingSchedulesItsOwnAutoCloseTest asserts both ends at once. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Dashboard\Ticketing;
|
namespace Dashboard\Ticketing;
|
||||||
|
|
||||||
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
class TicketingServiceProvider extends ServiceProvider
|
class TicketingServiceProvider extends ServiceProvider
|
||||||
@@ -29,5 +30,46 @@ class TicketingServiceProvider extends ServiceProvider
|
|||||||
\Dashboard\Ticketing\Console\Commands\RepairMergedTickets::class,
|
\Dashboard\Ticketing\Console\Commands\RepairMergedTickets::class,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->scheduleAutoClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* THE NIGHTLY AUTO-CLOSE IS SCHEDULED HERE, BESIDE THE COMMAND IT NAMES
|
||||||
|
* ([central-ticketing] #2980, a spawn of [dashboard-shell] #2965).
|
||||||
|
*
|
||||||
|
* It used to be one line in the shell's routes/console.php — a file that
|
||||||
|
* names commands other repositories define. On 2026-09-26 01:10 PDT that
|
||||||
|
* arrangement cost production a php process a day whose entire output was
|
||||||
|
* *Command "admissions:remind-unconfirmed-links" is not defined*, exit 1: a
|
||||||
|
* schedule had reached a box nine and a half hours ahead of the code it
|
||||||
|
* scheduled, and nothing an operator could press would have fixed it,
|
||||||
|
* because the code was not there to fix.
|
||||||
|
*
|
||||||
|
* Registered from this provider, that is not expressible. The event exists
|
||||||
|
* on exactly the boxes where `AutoCloseTickets` is registered above,
|
||||||
|
* because the same `boot()` does both and both arrive in the same commit.
|
||||||
|
* A shell without central-ticketing simply has no such row in
|
||||||
|
* `schedule:list`, rather than a nightly failure about one.
|
||||||
|
*
|
||||||
|
* ── THE MINUTE IS STILL THE SHELL'S TO DECIDE ──────────────────────────
|
||||||
|
*
|
||||||
|
* `ScheduleStagger` is the one place a start time is chosen, and that is
|
||||||
|
* the whole point of it: a bare `->daily()` is 00:00:00, where every hourly
|
||||||
|
* and every quarter-hourly task on the platform already boots its own PHP
|
||||||
|
* inside the scheduler's one cgroup ([dashboard-shell] #1910). A time typed
|
||||||
|
* in this repository could not know that. Asking `dailyAt()` keeps this job
|
||||||
|
* at 00:12 — exactly where routes/console.php had it — and keeps the shell's
|
||||||
|
* map the single account of the night even for a job it no longer schedules.
|
||||||
|
*
|
||||||
|
* No `withoutOverlapping()`, and deliberately not added here: the shell's
|
||||||
|
* line carried none, and a lock is a behaviour change rather than a move.
|
||||||
|
*/
|
||||||
|
private function scheduleAutoClose(): void
|
||||||
|
{
|
||||||
|
$this->callAfterResolving(Schedule::class, function (Schedule $schedule) {
|
||||||
|
$schedule->command('ticketing:auto-close')
|
||||||
|
->dailyAt(\App\Support\Ops\ScheduleStagger::dailyAt('ticketing:auto-close'));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user