@extends('layouts.admin')
@section('style')
@parent
@include('admin.system._style')
@endsection
@section('content')
@php
$statusLook = [
\romanzipp\QueueMonitor\Enums\MonitorStatus::RUNNING => ['Running', 'is-live'],
\romanzipp\QueueMonitor\Enums\MonitorStatus::SUCCEEDED => ['Done', 'is-good'],
\romanzipp\QueueMonitor\Enums\MonitorStatus::FAILED => ['Failed', 'is-bad'],
\romanzipp\QueueMonitor\Enums\MonitorStatus::STALE => ['Stale', 'is-warn'],
\romanzipp\QueueMonitor\Enums\MonitorStatus::QUEUED => ['Waiting', 'is-quiet'],
];
$tabLabels = ['failed' => 'Failed', 'running' => 'Running', 'waiting' => 'Waiting', 'done' => 'Done', 'stale' => 'Stale'];
$tabStatuses = \App\Http\Controllers\Admin\SystemController::STATUS_TABS;
$age = fn ($seconds) => \Carbon\CarbonInterval::seconds(max(1, (int) $seconds))->cascade()->forHumans(['short' => true, 'parts' => 2]);
$took = function ($s) {
if ($s < 1) return round($s * 1000) . ' ms';
if ($s < 60) return number_format($s, 1) . ' s';
return \Carbon\CarbonInterval::seconds((int) $s)->cascade()->forHumans(['short' => true, 'parts' => 2]);
};
$tabUrl = fn ($key) => route('admin.system.queue', array_merge(
['channel' => $channel],
array_filter(['queue' => $filters['queue'] ?? null, 'job' => $filters['job'] ?? null]),
$key ? ['status' => $key] : []
), false);
$active = $filters['status'] ?? null;
$stuck = $backlog ? $backlog->where('due', '>', 0)->where('waited', '>=', $stuckAfter)->sortByDesc('waited')->first() : null;
$waiting = $backlog ? $backlog->sum('due') : 0;
$running = $backlog ? $backlog->sum('running') : 0;
@endphp
Queue monitor
Background jobs for every channel: blasts, template syncs and integrations.
@if(session('system_status'))
{{ session('system_status') }}
@endif
@if(session('system_error'))
{{ session('system_error') }}
@endif
@if($backlog !== null)
@if($stuck)
{{ number_format($stuck->due) }} {{ \Illuminate\Support\Str::plural('job', $stuck->due) }}
on “{{ $stuck->queue }}” {{ $stuck->due === 1 ? 'has' : 'have' }} waited {{ \Carbon\CarbonInterval::seconds($stuck->waited)->cascade()->forHumans(['parts' => 1]) }}.
Nothing is picking them up. Check that the queue worker is running.
@elseif($waiting + $running > 0)
Jobs are moving.
{{ number_format($waiting) }} waiting and {{ number_format($running) }} running right now.
@else
Nothing waiting.
Every job that was due has been picked up.
@endif
@if($backlog->isNotEmpty())
QueueWaitingRunningScheduledOldest waiting
@foreach($backlog as $lane)
{{ $lane->queue }}
{{ number_format($lane->due) }}
{{ number_format($lane->running) }}
{{ number_format($lane->scheduled) }}
{{ $lane->due ? $age($lane->waited) : 'None' }}
@endforeach
@endif
@endif
Last 14 days
{{ number_format($stats->ran ?? 0) }} jobs finished
{{ number_format($stats->failed ?? 0) }} failed
@if($stats && $stats->avg_seconds !== null)
{{ $took((float) $stats->avg_seconds) }} average run time
@endif
@if($jobs->isEmpty())
@if($active || ($filters['queue'] ?? null) || ($filters['job'] ?? null))
No jobs match these filters
@else
No jobs recorded yet
Jobs show up here as soon as one is queued or starts running.
@endif
@else
JobQueueStatusStartedTook
@foreach($jobs as $job)
@php
[$statusLabel, $statusClass] = $statusLook[(int) $job->status] ?? ['Unknown', 'is-quiet'];
$failed = (int) $job->status === \romanzipp\QueueMonitor\Enums\MonitorStatus::FAILED;
$when = $job->started_at ?? $job->queued_at;
$namespace = \Illuminate\Support\Str::beforeLast($job->name, '\\');
$meta = collect([
$namespace !== $job->name ? $namespace : null,
$job->attempt > 1 ? "attempt {$job->attempt}" : null,
])->filter()->implode(', ');
@endphp
{{ $job->getBasename() }}
{{ $meta }}
{{ $job->queue }}
{{ $statusLabel }}
{{-- Waiting rows say "Queued …" in the value itself, so no mobile label to repeat it. --}}
started_at) data-label="Started" @endif @if($when) title="{{ $when->toDayDateTimeString() }}" @endif>
{{ $when ? ($job->started_at ? '' : 'Queued ') . $when->diffForHumans() : '' }}
@if($job->started_at && $job->finished_at)
{{ $took($job->getElapsedInterval()->totalSeconds) }}
@else
@endif
@if($job->canBeRetried())
@elseif($failed && $job->retried)
Retried
@else
@endif
@if($failed && $job->exception_message)
@if($job->exception_class)
{{ class_basename($job->exception_class) }}
@endif
{{ $job->exception_message }}
@if($job->exception)
Stack trace
{{ $job->exception }}
@endif
@endif
@endforeach
@endif
@include('admin.system._pager', ['p' => $jobs])
@endsection