Task Management Hooks

2 vues Markdown

The eight hooks where an operator reaches into scheduled work by hand: running a task, switching one off, cleaning the queue and the kill switch.

Overview

Unlike the hooks in the previous article these fire from the panel: an operator is there and reads your message.

Two of them weigh heavily. The kill switch turns every automation off, and the queue cleanup deletes history so you can no longer see what ran when.

Reference

Following a run by hand

actioncron.task_run_now
AdminAutomation the job was queued

Runs after an operator triggered a task by hand. The task is on the queue at this point, not running yet.

Parameters 2
$taskstringThe name of the task triggered.
$job_idintThe id of the queued job. For the outcome, listen to the queue hook; this one says only that it joined the queue.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:cron.task_run_now', 10, function ($task, $job_id) {
    // The job JOINED the queue and has not run: watch job.processed for the outcome.
    Audit::manualRun($task, (int) $job_id);
});

Following a task switched on or off

actioncron.task_status_changed
AdminAutomation a single task

Runs after a single task was switched on or off.

Parameters 2
$taskstringThe name of the task whose status changed.
$enabledboolThe new state. A task switched off stops quietly and may go unnoticed.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:cron.task_status_changed', 10, function ($task, $enabled) {
    // A task switched off stops quietly: record the critical ones.
    if (!$enabled && Acme::criticalTask($task)) Ops::alert('task-off', $task);
});

Blocking the kill switch

gatecron.kill_switch_disable
AdminAutomation it stops everything

Runs before all automation is switched off. This hook fires on the off direction only.

Parameters 2
$enabledboolThe target state. On this hook it is always false: it fires when switching off, never on.
$pending_countintHow many jobs are waiting. A high number means switching off holds them all; weigh that before deciding.
Return 1
stringA non-empty string stops the action; the text is shown to the operator as the error.
Listener
Hook::add('gate:cron.kill_switch_disable', 10, function ($enabled, $pending_count) {
    // Switching off with many jobs waiting only grows the backlog.
    if ($pending_count > 500)
        return 'Too many jobs are waiting; let the queue drain first.';

    return null;
});

Stopping a queue cleanup

gatecron.cleanup_run
AdminAutomation it deletes history

Runs before the queue history is deleted. The retention days are separate per status.

Parameters 3
$completed_daysintRetention days for completed jobs.
$cancelled_daysintRetention days for cancelled jobs.
$failed_daysintRetention days for failed jobs. Keeping this low deletes the evidence of a problem.
Return 1
stringA non-empty string stops the action; the text is shown to the operator as the error.
Listener
Hook::add('gate:cron.cleanup_run', 10,
    function ($completed_days, $cancelled_days, $failed_days) {
        // Deleting failures early destroys the evidence of a problem.
        if ($failed_days < 30) return 'Failed records want keeping for 30 days.';

        return null;
    });

Following what a cleanup removed

actioncron.queue_cleaned
AdminAutomation a breakdown by status

Runs after the queue cleanup finished.

Parameters 2
$deletedintHow many records went in total.
$breakdownarrayThe breakdown by status: completed, cancelled, failed. A high failed count means what went was the trace of a problem.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:cron.queue_cleaned', 10, function ($deleted, $breakdown) {
    // Many failed records removed means a problem's trace has gone.
    if ((int) ($breakdown['failed'] ?? 0) > 100)
        Ops::warn('cron-failures-purged', (int) $breakdown['failed']);
});

Following a job intervention

actioncron.job_intervened
AdminAutomation four separate actions

Runs after an operator reached into a queued job by hand.

Parameters 3
$actionstringThe kind: retry, cancel, force_reclaim, delete. The four differ greatly; do not react without reading which.
$queuestringThe queue key: cron, module, notification. There are three queues and all pass this hook.
$idintThe id of the job that was touched.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:cron.job_intervened', 10, function ($action, $queue, $id) {
    // force_reclaim takes a stuck job back, which means it runs again.
    if ($action === 'force_reclaim') Ops::note('job-reclaimed', $queue, (int) $id);
});

Catching a return after downtime

actioncron.restore.detected
cron.php a long gap

Runs where the system noticed the tasks had not run for a long while.

Parameters 2
$restoreInfoarrayThe gap details: gap_hours, gap_seconds, last_seen. A long gap means the renewals, suspensions and invoices of that period are late.
$workerIdstringThe id of the worker that noticed.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:cron.restore.detected', 10, function ($restoreInfo, $workerId) {
    // Renewals and suspensions are late across the gap: check the backlog.
    Ops::alert('cron-gap', (float) ($restoreInfo['gap_hours'] ?? 0));
});

Changing the task list

filtercron.task_overview
AdminAutomation the panel cards

Runs before the task overview is shown in the panel.

Parameters 1
$tasksarrayrefThe task card rows. Adding your own here shows it in the list without running it: use the registration hook for that.
Return 1
voidThe value changes by reference; the return is not read.
Listener
Hook::add('filter:cron.task_overview', 10, function (&$tasks) {
    // Adding to the list does NOT run a task; registration is register:cronjobs.
    $tasks = array_filter($tasks, fn ($t) => !Acme::hidden($t['key'] ?? ''));
});

Pitfalls

Running by hand is not running

The manual trigger hook hands you a queue id: the job joined the queue and has not run. Waiting for an outcome here is pointless; what the job actually did is told by the processed hook.

A cleanup cannot be undone

The cleanup also removes failed records, and those are the only trace of a problem. Shortening retention leaves tomorrow's "why did it not run?" unanswerable. Guard the failed retention at the gate.

The intervention hook carries four different actions

Retrying, cancelling, reclaiming and deleting pass one hook and their outcomes are opposites. A listener written without reading the kind can take a cancelled job for a restarted one. There are also three queues; the second parameter says which you are in.

Adding to the list does not run a task

The task list filter changes what shows in the panel and nothing more. Your own task does not run for being added there; it wants making known through the registration hook. Mixing the two leaves a card that sits in the panel and never runs.

Cet article vous a-t-il été utile ?

Merci pour votre retour !

Besoin d'aide supplémentaire ?

Notre équipe d'assistance est disponible 24h/24 pour tout ce que vous ne trouvez pas ci-dessus.