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

Laravel Fuse Laravel Package

harris21/laravel-fuse

Laravel Fuse adds fuzzy search to Eloquent models and collections, helping users find results despite typos. Configure searchable fields and thresholds, then run simple fluent queries for fast, relevant matches without external search services.

View on GitHub
Deep Wiki
Context7

Getting Started

Fuse is a circuit breaker for the calls your jobs make to flaky external services. The mental model is: a service (Stripe, an SMTP relay, an internal API) accumulates job failures; when it crosses a threshold the circuit opens and jobs touching it are released back onto the queue instead of hammering a dead dependency; after an open timeout a single probe job is let through, and success closes the circuit again.

Minimal path to first use:

  1. composer require harris21/laravel-fuse and publish the config (php artisan vendor:publish --tag=fuse-config). Read config/fuse.php before anything else — the shape of the services array and the cache block tells you most of what the package does.
  2. Register each external dependency under services, keyed by the name you'll reference from jobs. If you want to observe before you enforce, set a deliberately high threshold first and watch traffic on the status page.
  3. Attach the Fuse job middleware to the jobs that make the call. This is the whole integration: no changes to the call site itself.
  4. Set $tries = 0 on those jobs (see Gotchas — this is not optional).
  5. Visit /fuse to confirm the service shows up and is reporting LIVE MONITORING.

The first use case worth wiring is a single job class calling one third-party API, with a listener on CircuitBreakerOpened that pings your alerting channel. That gives you the full loop — trip, alert, probe, recover — on one code path before you roll it out across the codebase.

Implementation Patterns

Job middleware as the enforcement point. Enforcement lives in the middleware, not in your job's handle(). Keep the actual API call in the job as normal; let middleware decide whether it runs. This is what makes Fuse cheap to adopt incrementally and cheap to remove if you change your mind.

Release-and-retry as the backpressure mechanism. When the circuit is open, the job is released with its configured release delay rather than failed. Size the release delay against how long you actually expect the dependency to be down — a 5-second release on a 20-minute outage burns 240 queue round-trips per job. For slow-moving outages, prefer a longer release plus a $maxExceptions/$tries budget that lets the job eventually give up rather than spin.

Per-service tuning. Services are configured independently, and as of v0.11.0 dotted names such as payments.stripe get their own config block instead of silently falling through to global defaults. Use the dotted form liberally — grouping by payments.stripe, payments.adyen, email.smtp keeps blast radius small and makes the status page readable.

Threshold strategy. default_threshold applies all day to services without a threshold. If your traffic is diurnal, set peak_hours_threshold and a peak_hours_start/peak_hours_end window rather than a flat number; windows may now cross midnight (22 → 6 covers 22:00–06:59), so night-batch windows are expressible.

Listeners for observability, not control flow. CircuitBreakerOpened / CircuitBreakerClosed are for metrics, Slack pings, and log lines. Since v0.11.0 a throwing listener is reported, not rethrown — which is exactly what you want for a notifier, but means listeners can no longer be used to abort work.

Status page as an operations surface. Put status_page.middleware behind auth and give on-call a bookmark. If several apps share one cache, set a distinct fuse.cache.prefix per app so their state histories don't interleave. Poll /fuse/data from your own dashboards if you'd rather not embed the page.

Testing half-open transitions. Fuse now reads time through Carbon everywhere, so $this->travel(60)->seconds() or Carbon::setTestNow() advances the open timeout. Tests that previously needed a real sleep() or a hand-written opened_at in the cache can be rewritten — do that pass, it's the single biggest test-suite speedup this release offers.

Custom recovery strategies let you shape what "may this job run" means beyond the default probe. Treat them as advanced: an exception from one now causes the job to be released rather than failed, so a strategy that threw as a deliberate veto no longer stops anything.

Gotchas and Tips

Keep $tries = 0 on jobs behind Fuse. A release still counts as an attempt. With a conventional $tries = 3 the queue gives up on a job during an outage and you lose the work — the exact opposite of the intent. This is called out in the README and again in the v0.11.0 upgrade notes because it is the most common misconfiguration.

Outcome fidelity on the failure path. Cache errors no longer rewrite job outcomes: a successful job stays successful even if the counter increment fails, and a failed job's own exception survives into failed_jobs instead of being replaced by a cache error. If you had defensive try/catch around cache-touching listener code to work around this, it can go.

Cache errors during the run decision now release the job. A cache timeout while Fuse decides whether a job may run reports the error and releases the job with its delay — previously it counted as the job's own exception, so $tries = 0 + $maxExceptions = 3 would permanently fail a job while the dependency was perfectly healthy. The exception is the sync driver (including dispatchSync()), where the error is still thrown, because releasing there would silently drop the job. If you test Fuse behaviour with sync, expect different semantics than production.

Listener exceptions are swallowed. Useful, but it means a broken listener fails silently apart from the report. Assert on listener side effects in tests rather than assuming a throw will surface.

Threshold semantics changed in v0.11.0. A service that sets other options but no threshold now uses default_threshold all day; it used to fall back to a hard-coded 50, or 60 during 09:00–17:59 via a peak window it never configured. If you were relying on the business-hours 60, set peak_hours_threshold explicitly — otherwise you'll trip more eagerly than before, and the change is silent.

Custom cache prefixes reset status history once. After upgrading, an app with fuse.cache.prefix set starts with empty state history. Expected, one-time, no action needed — but don't page anyone over it.

Disabled status page now 404s with custom middleware. Previously a custom status_page.middleware could bypass the enabled check. Behind auth, unauthenticated users still hit the 401/login redirect first, so the 404 is only visible to authenticated users.

Cache outage handling. When Fuse can't read its cache the page renders DATA UNAVAILABLE in red instead of LIVE MONITORING, /fuse/data returns 503, and the page recovers on the first successful poll — it no longer 500s or silently shows stale state. If you published the status view earlier, republish with --tag=fuse-views to pick up the new label.

Debugging checklist when a circuit behaves unexpectedly, in order: confirm the service key resolves to the block you think it does (dotted names — check you're on ≥ 0.11.0); inspect the raw cache keys under your fuse.cache.prefix to see opened_at and the probe lock; check whether a probe lock is still held (a throwing CircuitBreakerOpened listener used to strand it until TTL — no longer, but stale locks from before the upgrade can linger); and confirm the queue driver, since sync diverges.

Cache store choice matters. State needs atomic increments and shared visibility — Redis or Memcached. The array store is fine for a single test but gives you a fresh circuit per request.

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.
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle