Skip to content

Instantly share code, notes, and snippets.

@mikedfunk
Last active January 24, 2019 05:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikedfunk/870f08a904a8da3f6c55493a9fe8d478 to your computer and use it in GitHub Desktop.
Save mikedfunk/870f08a904a8da3f6c55493a9fe8d478 to your computer and use it in GitHub Desktop.
<?php declare(strict_types=1);
namespace MyApp\Adapter\Repository\Couchbase;
use MyApp\Exception\DocumentIsLockedException;
class LockHandler
{
// ...
/**
* Wait for a lock to be released, acquire a lock, and return lock data.
*
* @throws \MyApp\Exception\DocumentIsLockedException if we waited too
* long and the lock has still not been released
*
* @param callable $attemptToAcquireLock This is passed in as a callable so
* the LockHandler can remain generic and not have to know how to try to
* obtain a lock. You just pass in a method that returns lock data or
* falsey and this handles the waiting, tracking, exceptions, and logging.
*
* @return array whatever the $attemptToAcquireLock callable returns
*/
public function waitAndAcquire(
string $docKey,
callable $attemptToAcquireLock
): array {
$currentAttempt = 1;
// loop until we reach max number of attemps
$maxLockCheckAttempts = $this->config['max_lock_check_attempts'];
while ($currentAttempt != $maxLockCheckAttempts) {
if ($currentAttempt == 10) {
Log::warning("Unusually long lock of doc keys: {$docKey}");
}
$lock = $attemptToAcquireLock(
$docKey,
$this->config['max_lock_time_in_seconds']
);
if ($lock) {
$this->lockTracker->track($docKey, $lock);
return $lock;
}
// keep retrying to access lock key if doc is locked
$currentAttempt++;
\usleep($this->config['sleep_time_in_microseconds']);
}
$message = "Document {$docKey} is locked for too long!";
throw new DocumentIsLockedException($message);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment