Passed
Pull Request — master (#2)
by Kevin
02:04
created

WithoutOverlappingExtension   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 53
Duplicated Lines 0 %

Test Coverage

Coverage 95.45%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 10
eloc 17
c 1
b 0
f 0
dl 0
loc 53
rs 10
ccs 21
cts 22
cp 0.9545

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getLockFactory() 0 3 2
A filterTask() 0 4 2
A createLocalStore() 0 7 2
A __construct() 0 4 1
A afterTask() 0 3 1
A setLockFactory() 0 5 1
A __toString() 0 3 1
1
<?php
2
3
namespace Zenstruck\ScheduleBundle\Schedule\Extension;
4
5
use Symfony\Component\Lock\LockFactory;
6
use Symfony\Component\Lock\PersistingStoreInterface;
7
use Symfony\Component\Lock\Store\FlockStore;
8
use Symfony\Component\Lock\Store\SemaphoreStore;
9
use Zenstruck\ScheduleBundle\Event\AfterTaskEvent;
10
use Zenstruck\ScheduleBundle\Event\BeforeTaskEvent;
11
use Zenstruck\ScheduleBundle\Schedule\Exception\SkipTask;
12
13
/**
14
 * @author Kevin Bond <[email protected]>
15
 */
16
final class WithoutOverlappingExtension extends SelfHandlingExtension
17
{
18
    public const DEFAULT_TTL = 86400;
19
20
    private $ttl;
21
    private $lock;
22
    private $lockFactory;
23
24
    /**
25
     * @param int $ttl Maximum expected lock duration in seconds
26
     */
27 3
    public function __construct(int $ttl = self::DEFAULT_TTL)
28
    {
29 3
        $this->ttl = $ttl;
30 3
        $this->lock = new Lock(self::class);
31 3
    }
32
33 1
    public function __toString(): string
34
    {
35 1
        return 'Without overlapping';
36
    }
37
38 2
    public function filterTask(BeforeTaskEvent $event): void
39
    {
40 2
        if (!$this->lock->aquire($this->getLockFactory(), $event->getTask()->getId(), $this->ttl)) {
41 1
            throw new SkipTask('Task running in another process.');
42
        }
43 2
    }
44
45 1
    public function afterTask(AfterTaskEvent $event): void
46
    {
47 1
        $this->lock->release();
48 1
    }
49
50 1
    public function setLockFactory(LockFactory $lockFactory): self
51
    {
52 1
        $this->lockFactory = $lockFactory;
53
54 1
        return $this;
55
    }
56
57 2
    private function getLockFactory(): LockFactory
58
    {
59 2
        return $this->lockFactory ?: $this->lockFactory = new LockFactory(self::createLocalStore());
60
    }
61
62 1
    private static function createLocalStore(): PersistingStoreInterface
63
    {
64 1
        if (SemaphoreStore::isSupported()) {
65 1
            return new SemaphoreStore();
66
        }
67
68
        return new FlockStore();
69
    }
70
}
71