Skip to content

Commit

Permalink
[9.x] Make sure the lock_connection is used for schedule's withoutOve…
Browse files Browse the repository at this point in the history
…rlapping() (#45963)

* use the lock functionality of the cache store (if possible)

* fix style

* formatting

---------

Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
johanrosenson and taylorotwell authored Feb 7, 2023
1 parent 395f305 commit e2e979f
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/Illuminate/Console/Scheduling/CacheEventMutex.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Illuminate\Console\Scheduling;

use Illuminate\Contracts\Cache\Factory as Cache;
use Illuminate\Contracts\Cache\LockProvider;

class CacheEventMutex implements EventMutex, CacheAware
{
Expand Down Expand Up @@ -39,6 +40,12 @@ public function __construct(Cache $cache)
*/
public function create(Event $event)
{
if ($this->cache->store($this->store)->getStore() instanceof LockProvider) {
return $this->cache->store($this->store)->getStore()
->lock($event->mutexName(), $event->expiresAt * 60)
->acquire();
}

return $this->cache->store($this->store)->add(
$event->mutexName(), true, $event->expiresAt * 60
);
Expand All @@ -52,6 +59,12 @@ public function create(Event $event)
*/
public function exists(Event $event)
{
if ($this->cache->store($this->store)->getStore() instanceof LockProvider) {
return ! $this->cache->store($this->store)->getStore()
->lock($event->mutexName(), $event->expiresAt * 60)
->get(fn () => true);
}

return $this->cache->store($this->store)->has($event->mutexName());
}

Expand All @@ -63,6 +76,14 @@ public function exists(Event $event)
*/
public function forget(Event $event)
{
if ($this->cache->store($this->store)->getStore() instanceof LockProvider) {
$this->cache->store($this->store)->getStore()
->lock($event->mutexName(), $event->expiresAt * 60)
->forceRelease();

return;
}

$this->cache->store($this->store)->forget($event->mutexName());
}

Expand Down
51 changes: 51 additions & 0 deletions tests/Console/Scheduling/CacheEventMutexTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Illuminate\Tests\Console\Scheduling;

use Illuminate\Cache\ArrayStore;
use Illuminate\Console\Scheduling\CacheEventMutex;
use Illuminate\Console\Scheduling\Event;
use Illuminate\Contracts\Cache\Factory;
Expand Down Expand Up @@ -44,13 +45,15 @@ protected function setUp(): void

public function testPreventOverlap()
{
$this->cacheRepository->shouldReceive('getStore')->andReturn(new \stdClass);
$this->cacheRepository->shouldReceive('add')->once();

$this->cacheMutex->create($this->event);
}

public function testCustomConnection()
{
$this->cacheRepository->shouldReceive('getStore')->andReturn(new \stdClass);
$this->cacheFactory->shouldReceive('store')->with('test')->andReturn($this->cacheRepository);
$this->cacheRepository->shouldReceive('add')->once();
$this->cacheMutex->useStore('test');
Expand All @@ -60,29 +63,77 @@ public function testCustomConnection()

public function testPreventOverlapFails()
{
$this->cacheRepository->shouldReceive('getStore')->andReturn(new \stdClass);
$this->cacheRepository->shouldReceive('add')->once()->andReturn(false);

$this->assertFalse($this->cacheMutex->create($this->event));
}

public function testOverlapsForNonRunningTask()
{
$this->cacheRepository->shouldReceive('getStore')->andReturn(new \stdClass);
$this->cacheRepository->shouldReceive('has')->once()->andReturn(false);

$this->assertFalse($this->cacheMutex->exists($this->event));
}

public function testOverlapsForRunningTask()
{
$this->cacheRepository->shouldReceive('getStore')->andReturn(new \stdClass);
$this->cacheRepository->shouldReceive('has')->once()->andReturn(true);

$this->assertTrue($this->cacheMutex->exists($this->event));
}

public function testResetOverlap()
{
$this->cacheRepository->shouldReceive('getStore')->andReturn(new \stdClass);
$this->cacheRepository->shouldReceive('forget')->once();

$this->cacheMutex->forget($this->event);
}

public function testPreventOverlapWithLockProvider()
{
$this->cacheRepository->shouldReceive('getStore')->andReturn(new ArrayStore);

$this->assertTrue($this->cacheMutex->create($this->event));
}

public function testPreventOverlapFailsWithLockProvider()
{
$this->cacheRepository->shouldReceive('getStore')->andReturn(new ArrayStore);

// first create the lock, so we can test that the next call fails.
$this->cacheMutex->create($this->event);

$this->assertFalse($this->cacheMutex->create($this->event));
}

public function testOverlapsForNonRunningTaskWithLockProvider()
{
$this->cacheRepository->shouldReceive('getStore')->andReturn(new ArrayStore);

$this->assertFalse($this->cacheMutex->exists($this->event));
}

public function testOverlapsForRunningTaskWithLockProvider()
{
$this->cacheRepository->shouldReceive('getStore')->andReturn(new ArrayStore);

$this->cacheMutex->create($this->event);

$this->assertTrue($this->cacheMutex->exists($this->event));
}

public function testResetOverlapWithLockProvider()
{
$this->cacheRepository->shouldReceive('getStore')->andReturn(new ArrayStore);

$this->cacheMutex->create($this->event);

$this->cacheMutex->forget($this->event);

$this->assertFalse($this->cacheMutex->exists($this->event));
}
}

0 comments on commit e2e979f

Please sign in to comment.