Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Horizon Laravel Package

fof/horizon

Brings Laravel Horizon's queue monitoring dashboard into Flarum's admin area, letting administrators inspect Redis-backed queues, recent jobs, throughput, and worker status. Requires Redis and proper Horizon setup, making it best suited to advanced or high-traffic forums.

View on GitHub
Deep Wiki
Context7

Getting Started

fof/horizon is a Flarum extension that wires Laravel Horizon into a Flarum installation, so the Horizon dashboard (queues, throughput, wait times, failed jobs, retries, metrics) is available inside the Flarum admin panel instead of as a standalone Laravel app. You are effectively running Laravel's queue stack under Flarum's bootstrap, so everything you know about Horizon carries over — with Flarum's config conventions on top.

Minimal steps:

composer require fof/horizon
php flarum extension:enable fof/horizon
php flarum cache:clear

Prerequisites before you enable it:

  • Redis (Horizon only supports the Redis queue driver — database/sync will not work).
  • ext-pcntl and ext-posix if you run Horizon supervisors on Linux.
  • Flarum's queue pointed at Redis. In Flarum 1.x this lives in config.php (or the env vars it reads), e.g. 'queue' => ['driver' => 'redis', ...] with a valid redis connection block.
  • Replace whatever is running php flarum queue:work in your process manager with Horizon's supervisor.

Where to look first:

  1. The dashboard — after enabling, log in as an admin and open the Horizon route the extension registers (typically /admin/horizon). Confirm it renders and that "Processes" shows a supervisor.
  2. vendor/fof/horizon/src/ — the service provider is where the extension merges Horizon's config, registers the route, and (likely) gates access to admins. Read this before changing anything; it tells you which config keys are actually honored.
  3. vendor/laravel/horizon/config/horizon.php — the canonical defaults for environments, waits, balance, trim, and metrics. Any override the extension supports will be layered on top of this.

First use case: run one real job through it — a queued notification or an email from another extension — then watch it appear in the "Recent Jobs" list and confirm it's tagged and completed. That single round trip proves wiring, supervisor, and Redis connectivity at once.

Implementation Patterns

Run Horizon as the queue worker, not alongside it. The whole point is that php flarum horizon becomes your single supervisor process; remove any queue:work cron or systemd unit. Running both means two consumers competing for the same queues and confusing metrics.

[program:flarum-horizon]
command=php /var/www/flarum/flarum horizon
directory=/var/www/flarum
autostart=true
autorestart=true
user=www-data
numprocs=1
stopwaitsecs=3600

Design jobs around Horizon's visibility. Any job implementing ShouldQueue shows up automatically, but you get far more out of it if you:

class SendDigest implements ShouldQueue
{
    public $queue = 'notifications';
    public $tries = 3;
    public $backoff = [30, 120, 300];

    public function tags(): array
    {
        return ['digest', 'user:'.$this->user->id];
    }
}

Tags are what make the "search by tag" and per-user filtering useful when a batch of queued notifications goes sideways.

Keep queue names in sync with environments. Horizon only supervises queues listed in the active environment's config. A job pushed ->onQueue('reports') when reports isn't in the supervisor config will sit invisible forever. Pick a small, explicit set of queue names (e.g. default, notifications, exports) and put them in both the job and the Horizon environment block.

Snapshot on a cron. Horizon's metrics graphs are populated by horizon:snapshot, and Flarum has no scheduler to do it for you. Add:

*/5 * * * * cd /var/www/flarum && php flarum horizon:snapshot >> /dev/null 2>&1

Without it the "Metrics" tab stays empty and you'll waste an afternoon assuming the extension is broken.

Terminate on deploy. Horizon supervisors hold your job code in memory. After every composer install / git pull, run:

php flarum horizon:terminate

Horizon's master process respawns workers with fresh code. Put this at the end of your deploy script next to php flarum cache:clear (order matters: clear the Flarum cache first, terminate second).

Use Horizon's own commands for triage rather than digging in Redis by hand:

php flarum horizon:status       # is a master running?
php flarum horizon:list         # supervisors and queue assignments
php flarum horizon:clear --queue=notifications
php flarum horizon:retry <id>

Isolate slow work. Anything doing HTTP calls or PDF generation belongs on its own queue with its own waits tolerance, otherwise a slow export blocks notification delivery and the dashboard's wait-time graph becomes meaningless.

Gotchas and Tips

  • Redis is not optional. Horizon speaks Redis directly and ignores Flarum's database queue driver. If you're on a shared host without Redis, this package can't help you; if you're on Redis but Flarum's config.php still says database, jobs never reach Horizon.
  • Config precedence is the #1 source of confusion. The extension merges its own Horizon config over laravel/horizon's defaults. If you edit vendor/laravel/horizon/config/horizon.php directly, your changes survive until the next composer update — put overrides wherever the FoF provider reads them (inspect the provider to know exactly) and re-run php flarum cache:clear after every change, since Flarum caches config.php.
  • Failed-job handling overlaps with Flarum's. Flarum has its own queue:failed / queue:retry commands operating on the failed_jobs table, while Horizon keeps failures in Redis. Depending on config you can end up with two failure stores and two retry paths. Pick Horizon as the source of truth once enabled and don't script Flarum's failure commands against the same queue.
  • Dashboard access is admin-gated by the extension, not by Horizon. Horizon's native Horizon::auth() gate isn't the thing protecting this route — the extension registers it under Flarum's admin middleware. Don't expose the route publicly by weakening that middleware; if non-admins need visibility, give them read-only metrics rather than dashboard access.
  • horizon:status returning "inactive" while jobs still process usually means an orphaned queue:work from before the migration. Kill it and confirm only the Horizon master is consuming.
  • Supervisor memory drift. Set memory limits and maxTime per worker in the supervisor config; Flarum jobs that pull large Eloquent graphs leak over time and an unbounded worker will OOM the box. horizon:terminate on a nightly cron is a cheap safety net.
  • Stale metrics after a restart are normal — Horizon loses in-flight metric data on terminate. Don't chase a "missing throughput" bug immediately after a deploy.
  • Adoption risk. This package has a single-digit star count and no dependents, so battle-tested patterns are thin and version compatibility with future Flarum releases is unproven. Pin it in composer.json, read the source of the service provider (it's small), and have a fallback plan: uninstalling it and reverting to queue:work plus queue:failed is a valid exit strategy if a Flarum upgrade breaks it.
  • Extension point worth knowing: Horizon's JobProcessing / JobProcessed events still fire under Flarum, so if you want to pipe queue telemetry into an external APM, listen there rather than patching the extension.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin