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

Lock Laravel Package

roadrunner-php/lock

PHP integration for the RoadRunner Lock plugin, enabling fast, lightweight distributed lock management in high-traffic apps and microservices. Acquire, release, and manage locks with optional blocking waits via a simple RPC-based API. Requires PHP 8.1+.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install via Composer: composer require roadrunner/lock

    ⚠️ Package renamed in 1.2.0. The old name roadrunner-php/lock is superseded by roadrunner/lock. Existing projects must run composer remove roadrunner-php/lock and composer require roadrunner/lock. Update any require entries and lockfile accordingly.

  2. Ensure RoadRunner v3 is running with the lock plugin enabled. Version 1.2.0 requires RoadRunner v3 and uses v3's flat, versioned config layout (no services: wrapper, plugins are top-level):

    version: '3'
    
    rpc:
      listen: tcp://127.0.0.1:6001
    
    lock:
      driver: redis
      redis:
        addr: "127.0.0.1:6379"
    

    💡 The default driver is memory (per-worker isolation). For true distributed locking across workers, use redis or memcached. If you are migrating from RRv2, the whole YAML needs the version: '3' header and plugins promoted out of services: — the package won't talk to an RRv2 server.

  3. First use case: Protect a shared resource (e.g. updating a counter) inside a long-running RoadRunner worker:

    use RoadRunner\Lock\Lock;
    
    $lock = app(Lock::class); // bound via DI/factory, see below
    $key = 'update_counter';
    
    $lock->lock($key);
    try {
        $counter = (int) file_get_contents('counter.txt');
        file_put_contents('counter.txt', $counter + 1);
    } finally {
        $lock->unlock($key);
    }
    

Implementation Patterns

  • Use wrap() for atomic blocks:

    $lock->wrap($key, fn() => $this->expensiveOperation());
    

    Guarantees unlock() runs even on exceptions — the safest default for critical sections.

  • Bind a singleton in a service provider so the client is shared and injectable:

    // AppServiceProvider::register()
    $this->app->singleton(\RoadRunner\Lock\Lock::class, function ($app) {
        return new \RoadRunner\Lock\Lock(
            $app->make(\RoadRunner\Lock\LockServiceInterface::class)
        );
    });
    

    The RoadRunner\Lock\* namespaces are consistent under the v3 SDK. Make sure you're resolving the v3 client interface — mixing v2 (Spiral\RoadRunner\...) and v3 (RoadRunner\...) classes in the same project will fail.

  • Per-operation key naming — namespace your keys so they're observable and collision-free:

    $key = sprintf('order:process:%d', $orderId);
    
  • Non-blocking acquisition with a timeout via tryLock():

    if ($lock->tryLock($key, $timeout = 1.5)) {
        try {
            // critical section
        } finally {
            $lock->unlock($key);
        }
    } else {
        // busy — retry later or enqueue
    }
    
  • Coordinating queued jobs across workers — guard against duplicate processing when the same job ID can be picked up concurrently:

    if ($lock->tryLock("job:{$jobId}")) {
        try {
            // process once
        } finally {
            $lock->unlock("job:{$jobId}");
        }
    }
    

Gotchas and Tips

  • 🚨 v1.2.0 is a breaking release. Two changes bite migrations: the package rename (roadrunner-php/lock → roadrunner/lock) and RoadRunner v3 requirement (config format change). Verify both before rolling out.
  • 🔁 v2 → v3 config migration: remove the services: { ... } nesting, add version: '3' at the top, and confirm the rpc listener is still reachable from your worker. RRv3 changed several backend config key names — copy the example from the v3 docs rather than reusing v2 snippets.
  • ⚠️ memory driver is worker-local — locks won't coordinate across separate worker processes. For real distributed guarantees, use Redis or Memcached.
  • ⚠️ Deadlock risk: never call lock() inside another locked section without a consistent ordering. Prefer wrap() for exception-safe scoping.
  • 🔍 Debugging contention: log lock keys and worker PIDs to spot hot locks:
    $logger->info('Acquired lock', ['key' => $key, 'worker' => getmypid()]);
    
  • 🌐 Redis timeouts: set connect_timeout / timeout in the Redis block of .rr.yaml to avoid hung workers when the backend is degraded.
  • 🛠 Extensibility: LockServiceInterface can be implemented in userland if you need a custom backend (DynamoDB, external lock HTTP service, etc.). Prefer doing this against the v3 interface.
  • 🔄 Long-running operations: make sure backend TTL exceeds the longest critical section. Under Redis, avoid KEYS * in monitoring — use SCAN, INFO, or CLUSTER commands.
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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels