-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathCacheCommandMutex.php
141 lines (119 loc) · 3.59 KB
/
CacheCommandMutex.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<?php
namespace Illuminate\Console;
use Carbon\CarbonInterval;
use Illuminate\Cache\DynamoDbStore;
use Illuminate\Contracts\Cache\Factory as Cache;
use Illuminate\Contracts\Cache\LockProvider;
use Illuminate\Support\InteractsWithTime;
class CacheCommandMutex implements CommandMutex
{
use InteractsWithTime;
/**
* The cache factory implementation.
*
* @var \Illuminate\Contracts\Cache\Factory
*/
public $cache;
/**
* The cache store that should be used.
*
* @var string|null
*/
public $store = null;
/**
* Create a new command mutex.
*
* @param \Illuminate\Contracts\Cache\Factory $cache
*/
public function __construct(Cache $cache)
{
$this->cache = $cache;
}
/**
* Attempt to obtain a command mutex for the given command.
*
* @param \Illuminate\Console\Command $command
* @return bool
*/
public function create($command)
{
$store = $this->cache->store($this->store);
$expiresAt = method_exists($command, 'isolationLockExpiresAt')
? $command->isolationLockExpiresAt()
: CarbonInterval::hour();
if ($this->shouldUseLocks($store->getStore())) {
return $store->getStore()->lock(
$this->commandMutexName($command),
$this->secondsUntil($expiresAt)
)->get();
}
return $store->add($this->commandMutexName($command), true, $expiresAt);
}
/**
* Determine if a command mutex exists for the given command.
*
* @param \Illuminate\Console\Command $command
* @return bool
*/
public function exists($command)
{
$store = $this->cache->store($this->store);
if ($this->shouldUseLocks($store->getStore())) {
$lock = $store->getStore()->lock($this->commandMutexName($command));
return tap(! $lock->get(), function ($exists) use ($lock) {
if ($exists) {
$lock->release();
}
});
}
return $this->cache->store($this->store)->has($this->commandMutexName($command));
}
/**
* Release the mutex for the given command.
*
* @param \Illuminate\Console\Command $command
* @return bool
*/
public function forget($command)
{
$store = $this->cache->store($this->store);
if ($this->shouldUseLocks($store->getStore())) {
return $store->getStore()->lock($this->commandMutexName($command))->forceRelease();
}
return $this->cache->store($this->store)->forget($this->commandMutexName($command));
}
/**
* Get the isolatable command mutex name.
*
* @param \Illuminate\Console\Command $command
* @return string
*/
protected function commandMutexName($command)
{
$baseName = 'framework'.DIRECTORY_SEPARATOR.'command-'.$command->getName();
return method_exists($command, 'isolatableId')
? $baseName.'-'.$command->isolatableId()
: $baseName;
}
/**
* Specify the cache store that should be used.
*
* @param string|null $store
* @return $this
*/
public function useStore($store)
{
$this->store = $store;
return $this;
}
/**
* Determine if the given store should use locks for command mutexes.
*
* @param \Illuminate\Contracts\Cache\Store $store
* @return bool
*/
protected function shouldUseLocks($store)
{
return $store instanceof LockProvider && ! $store instanceof DynamoDbStore;
}
}