Giter Site home page Giter Site logo

lockerroom's Introduction

Locker Room

Acquire mutually exclusive locks in WordPress, using an underlying Memcache object cache.

Created by Ryan McCue (@rmccue) and Theo Savage (@tcrsavage), at Human Made Limited (@humanmade).

Requirements

Using Locker Room

Locking involves three main steps: before starting a task, you acquire a lock; next, you run the task; once you're finished, you release the lock. We call this the acquire-run-release cycle.

Here's how that looks with Locker Room (test):

// Attempt to **acquire** the lock
if ( ! HM\Locker_Room\acquire( 'my_test_hook' ) ) {
    // Someone else is already performing this action, skip for now
    return true;
}

// **Run** a long-running request
$error = download_internet( '/tmp/internet-copy' );

// **Release** the lock as soon as possible
HM\Locker_Room\release( 'my_test_hook' );

// Return error if we have one
if ( is_wp_error( $error ) ) {
    return $error;
}

return true;

More complicated examples are available in example.php, included with the plugin.

Bonus Features

Locker Room ships with a few niceties that can aid you in using locks correctly:

  • Autoreleasing

    Typically, lock acquisition follows the acquire-run-release cycle. However, it's possible to accidentally exit or fatal error during the run phase. Locker Room includes the ability to autorelease, which automatically releases the lock when your script exits.

    This feature is not enabled by default, due to the "magical" nature of it, so you need to be explicit about using it:

    $lock_opts = array(
        'autorelease' => true,
    );
    $lock = HM\Locker_Room\acquire( 'my_test_hook', $lock_opts );
  • Expiration

    Even when using autoreleasing, it's still possible for locks to never be released (such as segfaults in PHP). Typically, you don't want this to stop your system from running permanently. Locker Room lets you set an expiration for locks (using memcached's expiration time), allowing these locks to be released after a reasonable time.

    This feature is enabled by default, with a timeout of 15 minutes. You can change this by passing the expiration in seconds:

    $lock_opts = array(
        'expiration' => 30 * MINUTE_IN_SECONDS,
    );
    $lock = HM\Locker_Room\acquire( 'my_test_hook', $lock_opts );

    You can pass an expiration of 0 seconds to disable expiration. The hm_lockerroom_default_expiration filter can be used to change the default expiration.

    Important note: Memcache treats expiration times larger than 30 days as Unix timestamps. If you want to set the expiration to e.g. 60 days, you need to specify this as a Unix timestamp instead (that is, add it to the current time):

    $lock_opts = array(
        'expiration' => time() + ( 60 * DAY_IN_SECONDS ),
    );
    $lock = HM\Locker_Room\acquire( 'my_test_hook', $lock_opts );
  • Cache Groups

    Locker Room allows specifying custom object cache groups.

    By default, hm_lockerroom_locks is used as the cache group, however this can be overridden by passing a group parameter:

    $lock_opts = array(
        'group' => 'my_custom_group',
    );
    $lock = HM\Locker_Room\acquire( 'my_test_hook', $lock_opts );

    For installations with multisite enabled, these locking groups are per-site. If you want to use locks globally, you need to use a custom group, and register that group with WordPress as global:

    wp_cache_add_global_groups( 'global_locks' );

    You can then use this group as you would any other:

    $lock_opts = array(
        'group' => 'global_locks',
    );
    $lock = HM\Locker_Room\acquire( 'my_test_hook', $lock_opts );
    

Best Practices

  • Enable autorelease and expiration

    As a safe-guard against crashing requests, you should always activate both autorelease and expiration. Expiration should be set at roughly double your average task run time; that is, if your task typically takes 5 minutes to run, set the expiration to 10 minutes. This allows your task ample room for edge cases, but ensures that your system does not wait around forever.

    Autorelease should almost always be enabled, except when you need to set locks that persist after a request. This is a rare use case, however, autoreleasing is disabled by default due to the magic of the behind-the-scenes work.

  • Tighten the acquire-run-release cycle

    Typically, you should acquire and release the lock as close as possible to the actual run phase as possible. That means that you should avoid acquiring before you do any other checks.

    For example, a cache-busting endpoint may want to ensure that only one cache-bust request is sent to the upstream server at a time. In this case, any extra HTTP parameters should be checked before acquiring the lock, and error reporting or response building should be done after releasing the lock.

    This ensures that your tasks can run as frequently as possible, and that only the truly conflicting part of the task needs to be locked out.

    (Obviously, for long-running/slow tasks, the run phase should include these expensive requests. That is to say, don't over-tighten your cycle.)

How It Works

In a nutshell, this plugin relies on the Memcache backend supporting an atomic command: add. This command creates the key and returns successfully, but only if the key does not already exist.

Check the source of plugin.php for more documentation on the specifics of using the command.

License

Backdrop is licensed under the GPL version 2.

Copyright 2014 Human Made Limited

lockerroom's People

Contributors

rmccue avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.