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

Ops Laravel Laravel Package

phattarachai/ops-laravel

Operational tooling for Laravel apps: health checks, maintenance commands, and deployment helpers to keep production running smoothly. Lightweight and config-driven, it drops into any Laravel project with minimal setup and clear, sensible defaults.

View on GitHub
Deep Wiki
Context7

Getting Started

phattarachai/ops-laravel is a small pre-1.0 (v0.1.x) operations helper package for Laravel. Based on the v0.1.2 changelog, its core surface area is lock and mutex lifetime management around Laravel's scheduler and cache lock primitives — i.e. the plumbing you reach for when scheduled work runs on more than one node and you need to guarantee that a crashed or hung process cannot leave a permanent lock behind.

Minimal setup:

composer require phattarachai/ops-laravel

Then, in order:

  1. Read the README first — at v0.1.2 the public API is still settling, so treat the repo's README and the src/ tree as the source of truth over any blog post or older example.
  2. Check for a publishable config (php artisan vendor:publish --tag=ops-config or similar) before wiring anything into routes/console.php. Any TTL bounds introduced in this release will almost certainly be config-driven.
  3. Confirm your cache store supports atomic locks. Anything mutex-related requires redis, memcached, database, dynamodb, or file (Laravel 10+). The array driver silently gives you per-process locks, which will make your multi-node tests pass while production double-runs.

First use case: take your most fragile scheduled command — the one that overlaps on deploy, or the one that got stuck behind a stale withoutOverlapping lock and stopped running for a week — and move it onto the package's mutex handling. That single migration is the fastest way to validate whether the package earns its place in your stack.

Implementation Patterns

Bound every lock you create. The headline of v0.1.2 is that scheduler mutexes and flexible-cache locks now get bounded expiries. Lean into that: never create a lock without an explicit TTL, and set the TTL from a config value rather than a magic number in the command.

// config/ops.php (shape inferred — verify against the README)
return [
    'locks' => [
        'max_ttl' => env('OPS_LOCK_MAX_TTL', 900),
    ],
];

Pair with Laravel's native scheduler guards rather than replacing them. withoutOverlapping() and onOneServer() already use cache locks; the value this package adds is the bound. Keep the native calls and let the package clamp the expiry:

Schedule::command('reports:generate')
    ->dailyAt('02:00')
    ->onOneServer()
    ->withoutOverlapping(10); // minutes — must exceed worst-case runtime

Treat TTL as a function of runtime, not a guess. A good working rule: ttl = p95_runtime * 3, capped by the package's bound. If the bound in v0.1.2 is lower than your longest legitimate job, you have introduced a correctness bug — two overlapping runs — in exchange for faster recovery from stale locks. Measure first.

Wrap critical sections, not whole commands, where possible. Narrow locks mean shorter TTLs mean less exposure to the bound:

$lock = Cache::lock("invoice-batch:{$batch->id}", ttl: 120);

if (! $lock->get()) {
    return; // another node owns this batch
}

try {
    $batch->process();
} finally {
    $lock->release();
}

Test the failure path explicitly. A lock library that is only tested on the happy path is untested. Write a test that acquires a lock, simulates abandonment, and asserts the next attempt succeeds after the bound — using Redis or database as the store, not array.

Integration tip: if you deploy multiple environments against a shared Redis, namespace your locks (APP_ENV prefix). Staging and production colliding on a mutex name is a genuinely confusing class of bug that looks like "the scheduler randomly didn't run."

Gotchas and Tips

  • Pre-1.0 semver. v0.1.2 is a patch release, but in a 0.x package the maintainer is not obligated to preserve API compatibility on minors. Pin with composer require phattarachai/ops-laravel:0.1.* and read the diff of PR #3 before upgrading.
  • "Bounded" is a behavior change, even as a patch. If you were relying on long or effectively-infinite lock expiries, v0.1.2 may now release your lock while your job is still running. Audit every withoutOverlapping() duration and every explicit Cache::lock() TTL against your actual job runtimes after upgrading. This is the single most likely way this release breaks you.
  • Scheduler mutex naming collisions. Laravel derives mutex names from the command string and arguments; two schedule entries that differ only in a closure will collide. Give distinct names via ->description() or the mutex name argument when using closures.
  • Clock skew across nodes will make bounded expiries behave unpredictably. Keep NTP healthy; if you cannot, prefer a single TTL authority (one cache store) over per-node computation.
  • Debugging a lock that won't release: inspect the store directly (redis-cli KEYS 'laravel_cache:*lock*', or the cache_locks table) before reaching for logs. Laravel's lock keys are opaque but the pattern is predictable. Cache::lock($name)->get() returning false tells you someone holds it; only the store tells you who and for how long.
  • Extension point: if you need custom recovery semantics, the natural seam is the config TTL bound plus a wrapper around your command's handle(). Avoid monkey-patching the package's internals — at 0.1.x they will move.
  • Missing observability. As of this release there is no indication of built-in metrics or events for lock acquisition failures. Add your own logging on the ! $lock->get() branch early; without it, "the cron didn't run" investigations start from zero every time.

Verdict: a narrow, useful fix in a young package. Adopt for the bounded-mutex behavior specifically, pin the version, and re-check your TTLs against real runtimes on every upgrade.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource