Skip to content

Commit f3082aa

Browse files
authored
Merge pull request #17 from aternosorg/relative-refresh-threshold
Make refreshThreshold relative to refreshTime
2 parents 169c82b + f76209f commit f3082aa

File tree

3 files changed

+63
-23
lines changed

3 files changed

+63
-23
lines changed

src/AbstractLock.php

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ public static function setDefaultIdentifier(?string $defaultIdentifier = null):
6262
* @param int $waitTime Time in seconds to wait for existing locks to be released.
6363
* @param int|null $refreshTime Duration in seconds the timeout should be set to when refreshing the lock.
6464
* If null the initial timeout will be used.
65-
* @param int $refreshThreshold Maximum duration in seconds the existing lock may be valid for to be refreshed.
66-
* If the lock is valid for longer than this time, the lock will not be refreshed.
65+
* @param float $refreshThreshold Maximum percentage of the refreshTime the existing lock may still be valid for
66+
* to be refreshed. If the lock is valid for longer than this time, it won't be refreshed.
6767
* @param bool $breakOnDestruct Automatically try to break the lock on destruct if possible
6868
*/
6969
public function __construct(
@@ -73,7 +73,7 @@ public function __construct(
7373
protected int $time = 120,
7474
protected int $waitTime = 300,
7575
protected ?int $refreshTime = null,
76-
protected int $refreshThreshold = 30,
76+
protected float $refreshThreshold = 0.5,
7777
protected bool $breakOnDestruct = true,
7878
)
7979
{
@@ -185,6 +185,16 @@ public function getRefreshTime(): ?int
185185
return $this->refreshTime;
186186
}
187187

188+
/**
189+
* Duration in seconds the timeout should be set to when refreshing the lock.
190+
* Same as {@link AbstractLock::getRefreshTime()} except that the lock time is used if the refresh time was not set.
191+
* @return int
192+
*/
193+
public function getEffectiveRefreshTime(): int
194+
{
195+
return $this->refreshTime ?? $this->time;
196+
}
197+
188198
/**
189199
* Duration in seconds the timeout should be set to when refreshing the lock.
190200
* If null the initial timeout will be used.
@@ -198,22 +208,22 @@ public function setRefreshTime(?int $refreshTime): static
198208
}
199209

200210
/**
201-
* Maximum duration in seconds the existing lock may be valid for to be refreshed. If the lock is valid for longer
202-
* than this time, the lock will not be refreshed.
203-
* @return int
211+
* Maximum percentage of the refreshTime the existing lock may still be valid for to be refreshed. If the lock is
212+
* valid for longer than this time, it won't be refreshed.
213+
* @return float
204214
*/
205-
public function getRefreshThreshold(): int
215+
public function getRefreshThreshold(): float
206216
{
207217
return $this->refreshThreshold;
208218
}
209219

210220
/**
211-
* Maximum duration in seconds the existing lock may be valid for to be refreshed. If the lock is valid for longer
212-
* than this time, the lock will not be refreshed.
213-
* @param int $refreshThreshold
221+
* Maximum percentage of the refreshTime the existing lock may still be valid for to be refreshed. If the lock is
222+
* valid for longer than this time, it won't be refreshed.
223+
* @param float $refreshThreshold
214224
* @return $this
215225
*/
216-
public function setRefreshThreshold(int $refreshThreshold): static
226+
public function setRefreshThreshold(float $refreshThreshold): static
217227
{
218228
$this->refreshThreshold = $refreshThreshold;
219229
return $this;

src/Lock.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,8 @@ public static function setDelayPerUnavailableRetry(int $delayPerRetry): void
190190
* @param int $waitTime Time in seconds to wait for existing locks to be released.
191191
* @param int|null $refreshTime Duration in seconds the timeout should be set to when refreshing the lock.
192192
* If null the initial timeout will be used.
193-
* @param int $refreshThreshold Maximum duration in seconds the existing lock may be valid for to be refreshed.
194-
* If the lock is valid for longer than this time, the lock will not be refreshed.
193+
* @param float $refreshThreshold Maximum percentage of the refreshTime the existing lock may still be valid for
194+
* to be refreshed. If the lock is valid for longer than this time, it won't be refreshed.
195195
* @param bool $breakOnDestruct Automatically try to break the lock on destruct if possible
196196
*/
197197
public function __construct(
@@ -201,7 +201,7 @@ public function __construct(
201201
int $time = 120,
202202
int $waitTime = 300,
203203
?int $refreshTime = null,
204-
int $refreshThreshold = 30,
204+
float $refreshThreshold = 0.5,
205205
bool $breakOnDestruct = true,
206206
)
207207
{
@@ -280,7 +280,7 @@ public function getRemainingLockDuration(): int
280280
*/
281281
public function refresh(): bool
282282
{
283-
if ($this->refreshThreshold > 0 && $this->getRemainingLockDuration() > $this->refreshThreshold) {
283+
if (!$this->shouldRefresh()) {
284284
return true;
285285
}
286286

@@ -292,7 +292,7 @@ public function refresh(): bool
292292
return false;
293293
}
294294

295-
$retry = !$this->addOrUpdateLock($this->refreshTime ?? $this->time);
295+
$retry = !$this->addOrUpdateLock($this->getEffectiveRefreshTime());
296296
} while ($retry);
297297
return true;
298298
}
@@ -327,6 +327,21 @@ protected function generateLock(): LockEntry
327327
return new LockEntry($this->identifier, time() + $this->time, $this->exclusive);
328328
}
329329

330+
/**
331+
* Returns true, if the remaining lock duration is less than the refresh threshold.
332+
* @return bool
333+
*/
334+
protected function shouldRefresh(): bool
335+
{
336+
if ($this->refreshThreshold <= 0) {
337+
return true;
338+
}
339+
340+
$remaining = $this->getRemainingLockDuration();
341+
$threshold = $this->refreshThreshold * $this->getEffectiveRefreshTime();
342+
return $remaining < $threshold;
343+
}
344+
330345
/**
331346
* Remove a lock from the locking array and save the locks
332347
*

test/LockTest.php

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,30 +113,45 @@ public function testGetRefreshTime(): void
113113
$this->assertEquals(5, $lock->getRefreshTime());
114114
}
115115

116+
public function testGetEffectiveRefreshTime(): void
117+
{
118+
$lock = new Lock("key");
119+
$this->assertEquals(120, $lock->getEffectiveRefreshTime());
120+
121+
$lock = new Lock("key", time: 10);
122+
$this->assertEquals(10, $lock->getEffectiveRefreshTime());
123+
124+
$lock = new Lock("key", "identifier", false, 10, 0, 5);
125+
$this->assertEquals(5, $lock->getEffectiveRefreshTime());
126+
}
127+
116128
public function testSetRefreshTime(): void
117129
{
118130
$lock = new Lock("key");
119131
$this->assertEquals(null, $lock->getRefreshTime());
132+
$this->assertEquals(120, $lock->getEffectiveRefreshTime());
120133
$lock->setRefreshTime(5);
121134
$this->assertEquals(5, $lock->getRefreshTime());
135+
$this->assertEquals(5, $lock->getEffectiveRefreshTime());
122136
$lock->setRefreshTime(null);
123137
$this->assertEquals(null, $lock->getRefreshTime());
138+
$this->assertEquals(120, $lock->getEffectiveRefreshTime());
124139
}
125140

126141
public function testGetRefreshThreshold(): void
127142
{
128143
$lock = new Lock("key");
129-
$this->assertEquals(30, $lock->getRefreshThreshold());
130-
$lock = new Lock("key", "identifier", false, 10, 0, 5, 2);
131-
$this->assertEquals(2, $lock->getRefreshThreshold());
144+
$this->assertEquals(0.5, $lock->getRefreshThreshold());
145+
$lock = new Lock("key", "identifier", false, 10, 0, 5, 0.25);
146+
$this->assertEquals(0.25, $lock->getRefreshThreshold());
132147
}
133148

134149
public function testSetRefreshThreshold(): void
135150
{
136151
$lock = new Lock("key");
137-
$this->assertEquals(30, $lock->getRefreshThreshold());
138-
$lock->setRefreshThreshold(5);
139-
$this->assertEquals(5, $lock->getRefreshThreshold());
152+
$this->assertEquals(0.5, $lock->getRefreshThreshold());
153+
$lock->setRefreshThreshold(0.25);
154+
$this->assertEquals(0.25, $lock->getRefreshThreshold());
140155
}
141156

142157
public function testShouldBreakOnDestruct(): void
@@ -248,7 +263,7 @@ public function testRefreshLockThreshold(): void
248263
$key = $this->getRandomString();
249264
$identifier = $this->getRandomString();
250265

251-
$lock = new Lock($key, $identifier, false, 10, 0, refreshThreshold: 5);
266+
$lock = new Lock($key, $identifier, false, 10, 0, refreshThreshold: 0.5);
252267
$lock->lock();
253268
$this->assertTrue($lock->isLocked());
254269
sleep(3);

0 commit comments

Comments
 (0)