Permalink
Browse files

MongoLock agreement between wait() and acquire()

When wait() returns it is guaranteed the previous lock has expires
(still it could have been acquired by someone else)
  • Loading branch information...
1 parent 92fcdbc commit d7af1a37a5ae2c17e77a9545006c6abeb8cf95e3 Giorgio Sironi committed Mar 11, 2016
Showing with 20 additions and 5 deletions.
  1. +18 −1 spec/Onebip/Concurrency/MongoLockTest.php
  2. +2 −4 src/Onebip/Concurrency/MongoLock.php
@@ -152,11 +152,28 @@ public function testALockShouldNotBeWaitedUponForever()
$this->fail("Should fail after 60 seconds");
} catch (LockNotAvailableException $e) {
$this->assertEquals(
- "I have been waiting up until 2014-01-01T00:01:00+0100 for the lock windows_defrag (60 seconds), but it is still not available.",
+ "I have been waiting up until 2014-01-01T00:01:00+0100 for the lock windows_defrag (60 seconds polling every 30 seconds), but it is still not available (now is 2014-01-01T00:01:00+0000).",
$e->getMessage()
);
}
+ }
+
+ public function testALockWaitedUponCanBeImmediatelyReacquired()
+ {
+ $allCalls = Phake::when($this->clock)->current()
+ ->thenReturn(new DateTime('2014-01-01T00:00:00Z'))
+ ->thenReturn(new DateTime('2014-01-01T00:00:30Z'))
+ ->thenReturn(new DateTime('2014-01-01T00:00:30Z'))
+ ->thenReturn(new DateTime('2014-01-01T00:00:30Z'))
+ ->thenReturn(new DateTime('2014-01-01T00:00:31Z'))
+ ->thenReturn(new DateTime('2014-01-01T00:00:31Z'))
+ ;
+ $first = new MongoLock($this->lockCollection, 'windows_defrag', 'ws-a-25:42', $this->clock);
+ $first->acquire(30);
+ $second = new MongoLock($this->lockCollection, 'windows_defrag', 'ws-a-25:42', $this->clock, $this->sleep);
+ $second->wait($polling = 1);
+ $second->acquire();
}
public function testAnAlreadyAcquiredLockCanBeRefreshed()
@@ -114,20 +114,18 @@ public function release($force = false)
*/
public function wait($polling = 30, $maximumWaitingTime = 3600)
{
- $i = 0;
$timeLimit = $this->clock->current()->add(new DateInterval("PT{$maximumWaitingTime}S"));
while (true) {
$now = $this->clock->current();
$result = $this->collection->count($query = [
'program' => $this->programName,
- 'expires_at' => ['$gt' => new MongoDate($now->getTimestamp())],
+ 'expires_at' => ['$gte' => new MongoDate($now->getTimestamp())],
]);
- $i++;
if ($result) {
if ($now > $timeLimit) {
throw new LockNotAvailableException(
- "I have been waiting up until {$timeLimit->format(DateTime::ISO8601)} for the lock $this->programName ($maximumWaitingTime seconds), but it is still not available."
+ "I have been waiting up until {$timeLimit->format(DateTime::ISO8601)} for the lock $this->programName ($maximumWaitingTime seconds polling every $polling seconds), but it is still not available (now is {$now->format(DateTime::ISO8601)})."
);
}
call_user_func($this->sleep, $polling);

0 comments on commit d7af1a3

Please sign in to comment.