Skip to content

Commit 9e1c6d3

Browse files
authored
Merge pull request #5 from nsumbadze/feat/job-queue-controls
Feat/job queue controls
2 parents bf03b05 + 6b4dcea commit 9e1c6d3

26 files changed

Lines changed: 1542 additions & 69 deletions

README.md

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ Under a row of queue KPIs, the workspace is organised into four areas:
2424
- **Insights** — an incident timeline (long waits, job failures, supervisor deployments), monitored tags, and recent batches.
2525
- **Horizon controls** — pause and continue the master supervisors or an individual supervisor.
2626

27+
Selecting a Redis queue in the Inspector also exposes queue pause/resume controls and safe cancellation actions for its pending or running jobs.
28+
2729
The active workspace, graph/table mode, time window, queue filter, and selected node are reflected in the query string, so operational views can be shared directly.
2830

2931
To explore without a live queue, run `composer serve:demo`. This boots the workbench application with generated demo data and seeds a handful of failed jobs you can open and retry.
@@ -54,11 +56,14 @@ Live-flow behaviour is configured via `config/horizonxflow.php`:
5456
| `GET /horizon/api/flow/queue-jobs` | Recent jobs + job-classes for a single queue (`?key=driver:connection:name`). |
5557
| `GET /horizon/api/flow/events` | Activity stream. Pass `?since=<unix ts>` for incremental polling. |
5658
| `GET /horizon/api/flow/incidents` | Recent incidents (long waits, job failures, supervisor deployments) for the Insights timeline. |
59+
| `POST /horizon/api/flow/queues/pause` | Pause one Redis queue while retaining pending and newly dispatched jobs. |
60+
| `POST /horizon/api/flow/queues/resume` | Resume processing one paused Redis queue. |
61+
| `POST /horizon/api/jobs/{id}/cancel` | Cancel a pending job or request cooperative cancellation of a running job. |
5762

5863
### Abilities
5964

6065
- `viewHorizon` — required to enter the dashboard (existing Horizon gate).
61-
- `controlHorizon` — required for mutation endpoints (`POST /jobs/retry/{id}`, `POST /masters/{action}`, `POST /supervisors/{name}/{action}`) and for `GET /jobs/failed/{id}/parameters`, which backs retrying with edited parameters. When the gate is undefined, mutations are only allowed in `local` and `testing` environments; everywhere else, define the gate in `HorizonApplicationServiceProvider::gate()` to enable destructive actions for a trusted subset of users.
66+
- `controlHorizon` — required for mutation endpoints (`POST /jobs/retry/{id}`, `POST /jobs/{id}/cancel`, `POST /flow/queues/{action}`, `POST /masters/{action}`, `POST /supervisors/{name}/{action}`) and for `GET /jobs/failed/{id}/parameters`, which backs retrying with edited parameters. When the gate is undefined, mutations are only allowed in `local` and `testing` environments; everywhere else, define the gate in `HorizonApplicationServiceProvider::gate()` to enable destructive actions for a trusted subset of users.
6267

6368
### Environment Variables
6469

@@ -70,6 +75,50 @@ Live-flow behaviour is configured via `config/horizonxflow.php`:
7075
- `HORIZONXFLOW_DISCOVER_DATABASE_QUEUES` — overrides `flow.database.discover_connections`.
7176
- `QUEUE_FAILED_TABLE` — overrides `flow.database.failed_table`.
7277

78+
## Job and Queue Controls
79+
80+
The Live Flow Inspector can pause an individual Redis queue and cancel one pending or running job. These controls deliberately preserve Laravel's queue safety boundaries:
81+
82+
- Pausing a queue does not reject dispatches or kill workers. A job already running finishes, while pending and newly dispatched jobs remain queued until the queue is resumed.
83+
- Cancelling a pending job atomically removes its exact payload from the ready list or delayed set. If a worker reserves it first, HorizonXFlow records a cooperative cancellation request instead of reporting a false success.
84+
- A running worker process is never force-killed. Side effects already performed by a job cannot be rolled back by HorizonXFlow.
85+
- Cancelled jobs remain visible in the Inspector with their cancellation time and operator identifier. Repeated requests are idempotent, and completed or failed jobs return `409 Conflict`.
86+
87+
Mutation routes use the `controlHorizon` ability described above. Queue connection and queue names are validated server-side, raw job payloads are never accepted from or returned to the control UI, and every destructive action has an explicit confirmation step.
88+
89+
### Cooperative cancellation checkpoints
90+
91+
A running job must opt in before it can stop between units of work. Add `InteractsWithCancellation` and return from `handle()` when a checkpoint acknowledges the request:
92+
93+
```php
94+
use Illuminate\Contracts\Queue\ShouldQueue;
95+
use Illuminate\Foundation\Queue\InteractsWithQueue;
96+
use Laravel\Horizon\Concerns\InteractsWithCancellation;
97+
98+
class SendCampaignMail implements ShouldQueue
99+
{
100+
use InteractsWithQueue;
101+
use InteractsWithCancellation;
102+
103+
public function handle(): void
104+
{
105+
foreach ($this->recipients as $recipient) {
106+
if ($this->cancelIfRequested()) {
107+
return;
108+
}
109+
110+
$this->sendTo($recipient);
111+
}
112+
}
113+
}
114+
```
115+
116+
Place checkpoints before idempotent units of work. A cancellation requested while a single non-interruptible call is executing—for example, an SMTP hand-off—takes effect only after that call returns and the next checkpoint is reached.
117+
118+
Queue and job controls currently support Redis queues. Database queues remain observable in Live Flow but do not expose these mutation controls.
119+
120+
When `flow.source` is `mock`, the Inspector exposes the same controls as a session-only visual simulation. Pausing, cancelling, and retrying update only the browser state and never call a mutation endpoint or change Redis. Mock failures are available from Live Flow's queue Inspector and Activity workspace; Horizon's separate Failed Jobs page continues to show only real failed jobs.
121+
73122
## Retry With Parameters
74123

75124
A failed job usually fails because of what it was handed: a wrong path, a batch size that was too large, a flag left on. Horizon can only push that same job back onto the queue unchanged, so the normal fix is a tinker session or a one-off command. HorizonXFlow lets you change the arguments and retry from the dashboard instead.

dist/app.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/app.js

Lines changed: 34 additions & 34 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)