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

Filament Ops Notify Laravel Package

spokospace/filament-ops-notify

spokospace/filament-ops-notify is a Laravel/Filament package that adds operational notifications to admin panels, helping teams surface alerts, status updates, and system events directly in the dashboard so issues are noticed, triaged, and handled faster without leaving the panel.

View on GitHub
Deep Wiki
Context7

Getting Started

This is an ops-alerting package: it gives you a single OpsMessage::send() entry point, an ops notification channel, a burst guard for noisy events, and a digest job that batches suppressed alerts. Alerts land in chat destinations (channels/topics) and optionally in the database for the in-app panel.

Start in src/ in this order:

  1. OpsMessage — the facade/entry point. Read send() first; that is the call you will use 95% of the time.
  2. BurstGuard — the dedupe/burst logic. This is where the subtle behaviour lives (TTL, held counts, digest handoff).
  3. The ops notification channel — only needed if you route alerts through Notifiable models rather than OpsMessage directly.
  4. The panel + ops-notify:test command — your day-one debugging tools.

Minimum viable use, from anywhere in the app (controller, job, listener):

use OpsMessage;

OpsMessage::send('Deploy finished', event: 'deploy.finished');
OpsMessage::send(
    'Invoice sync failed',
    event: 'billing.sync.failed',
    destination: 'ops-alerts',
);

Two rules to internalise before you wire it up:

  • Pick the cache store deliberately. Dedupe, burst windows and digest dedupe all ride on the cache. In production it must be a shared store (Redis, database, memcached) — the array driver gives every PHP process its own counters.
  • Call it from the request/job that already happened. Since v1.3.1 send() is genuinely non-throwing: an unreachable cache logs and sends anyway, so a duplicate beats a lost alert. You no longer need to wrap every call site in try/catch or dispatch a ShouldQueue job just to protect the host request. Saving an inquiry will not 500 because Redis blinked.

First real use case: replace your ad-hoc Slack::send(...) / Log::critical(...) pairs at the top of the funnel (build failures, payment errors, contact-form submissions) with one OpsMessage::send() per event and let the burst guard handle the noise.

Implementation Patterns

Fire-and-forget from the happy path. Because delivery failures are swallowed and logged, put the call inline in the action that matters — after the inquiry is persisted, at the end of a failed deploy job, in the failed() hook of a queue job. Don't fan it out to a separate queue just for safety.

Burst guard for noisy events. Use the guard for anything that can fire in clusters (a flapping integration, a queue backlog, a broken webhook):

OpsMessage::send('Webhook rejected', event: 'webhook.rejected', destination: 'integrations');

The guard suppresses beyond the window; suppressed rows are held and rolled into a digest. Two behaviours to rely on after this release:

  • The window TTL is re-armed whenever a revived counter is picked up, so a counter can no longer survive forever and silently swallow an event with no digest.
  • The held count is preserved until the digest is actually queued (with retries), so a failed digest job reports the real number rather than zero.

One destination per logical stream. The burst key now includes the destination, so the same event sent to two chats/topics gets two independent counters and two correct digests. Previously these shared a counter and could send the digest to the wrong place. If you previously worked around that by suffixing the event name, drop the workaround.

Notification channel for per-user routing. Use the ops channel when the recipient is a Notifiable (an on-call user, a team model). It now shares the same cache guard as OpsMessage, so a dead cache no longer aborts Laravel's loop over notifiables and drops database/mail for everyone after the first recipient. In practice: keep ops in via() alongside database and mail, and trust that a cache outage degrades to "no chat ping" rather than "no notification at all".

Digests as a first-class workflow. Treat the digest as the low-priority, aggregated counterpart to the immediate alert. Titles in the digest are matched against the truncated event name, filtered by destination, and bounded to the window — so long event names list correctly, and a digest that runs late does not pull rows from the next window. If you use long, descriptive event names, keep them stable; they are the join key.

Panel resend as an operational tool. Resend now only reports "Queued" when something was actually queued. A burst-held or failed resend keeps the row Failed with its Resend button live — which means the panel is trustworthy as a status board during an incident, not just a "click and hope" button.

CI / deploy smoke test. Wire ops-notify:test --queue into a post-deploy check. It exits non-zero when nothing was queued, so it fails the step instead of printing a false success.

Gotchas and Tips

  • The cache store is the silent dependency. Nothing throws now, which is the point — but it also means silent degradation. If dedupe or digest behaviour looks wrong (every alert duplicated, or no digest at all), check the cache before the package. Add an alert on your log channel for the "cache unavailable" path so a degraded guard is visible to you.
  • Duplicate on cache outage is by design. With the dedupe check now inside the guard's error handling, a Redis outage means alerts are sent anyway. Expect a burst of duplicates during a cache incident; don't "fix" it by wrapping send() in your own try/catch and dropping the alert.
  • Burst keys changed shape. Keys now include the destination, so counters that were live across the upgrade are simply not found. Effect after deploy: a short window where a previously suppressed event may fire once more. Harmless, but don't page on it.
  • Digest ordering was fixed; don't reintroduce it. The digest is scheduled before the suppressed row is logged, and the held count is only cleared once the digest is queued. If you extend this flow, keep that order — scheduling after the insert is exactly the bug that swallowed digests on a DB hiccup.
  • Long event names and late digests. Titles are matched against the truncated event name and bounded to the window. Two consequences: don't build tooling that matches on the untruncated name, and don't assume a digest that runs late will include overflow rows from the next window (it deliberately won't).
  • Chat discovery holds a lock for the whole paged scan (~100 s worst case, previously a fixed 60 s). If you trigger discovery from a request or a short-timeout job, give it real headroom or move it to a scheduled command. If a second discovery appears to do nothing, it's waiting on that lock — correct behaviour, not a bug.
  • Horizon status is memoised per request. A render now checks it once instead of twice. If you're asserting on Horizon calls in tests, expect one call, not two.
  • Internal API change: BurstGuard::pullHeld() is gone, replaced by heldCount() + clearHeld(). Only relevant if you subclass or call BurstGuard directly — normal use is unaffected. No config changes, no migrations, nothing to run on upgrade.
  • Upgrade confidence is high. 285 tests at Larastan level 8, and the whole release is a src/ reliability pass with no breaking surface for normal use. Schedule it normally; the only thing worth watching post-deploy is whether your cache outage log starts talking.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource