8000 Another implementation · symfony/symfony@b48b5bb · GitHub
[go: up one dir, main page]

Skip to content

Commit b48b5bb

Browse files
Another implementation
1 parent 3a78fe0 commit b48b5bb

File tree

3 files changed

+102
-20
lines changed

3 files changed

+102
-20
lines changed

src/Symfony/Component/Messenger/Middleware/LockMiddleware.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope
2929
}
3030

3131
if (!$envelope->last(ReceivedStamp::class)) {
32-
$lock = $this->lockFactory->createLockFromKey($stamp->getKey(), $stamp->getTtl(), autoRelease: false);
33-
34-
$blocking = $stamp->getMode() === LockStamp::MODE_BLOCK;
35-
if (!$lock->acquire($blocking)) {
36-
return $envelope;
32+
if ($stamp->shouldDiscardDuplicate()) {
33+
$lock = $this->lockFactory->createLockFromKey($stamp->getKey(), $stamp->getTtl(), autoRelease: false);
34+
if (!$lock->acquire()) {
35+
return $envelope;
36+
}
3737
}
38+
} elseif ($stamp->shouldBlockDuplicateInProcess()) {
39+
$lock = $this->lockFactory->createLockFromKey($stamp->getKey(), $stamp->getTtl(), autoRelease: false);
40+
$lock->acquire(true);
3841
} elseif ($stamp->shouldBeReleasedBeforeHandlerCall()) {
3942
$this->lockFactory->createLockFromKey($stamp->getKey())->release();
4043
}

src/Symfony/Component/Messenger/Stamp/LockStamp.php

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,18 @@
1212
namespace Symfony\Component\Messenger\Stamp;
1313

1414
use Symfony\Component\Lock\Key;
15-
use Symfony\Component\Messenger\Exception\InvalidArgumentException;
1615

1716
final class LockStamp implements StampInterface
1817
{
19-
public const MODE_DISCARD = 0;
20-
public const MODE_BLOCK = 1;
18+
public const MODE_DISCARD_DUPLICATE_IN_QUEUE = 0;
19+
public const MODE_DISCARD_DUPLICATE_IN_QUEUE_OR_PROCESS = 1;
20+
public const MODE_BLOCK_DUPLICATE_IN_PROCESS = 2;
21+
22+
private const MODES = [
23+
self::MODE_DISCARD_DUPLICATE_IN_QUEUE,
24+
self::MODE_DISCARD_DUPLICATE_IN_QUEUE_OR_PROCESS,
25+
self::MODE_BLOCK_DUPLICATE_IN_PROCESS,
26+
];
2127

2228
private Key $key;
2329

@@ -28,10 +34,9 @@ public function __construct(
2834
private int $mode,
2935
string $key,
3036
private ?float $ttl = 300.0,
31-
private bool $shouldBeReleasedBeforeHandlerCall = false,
3237
) {
33-
if (!\in_array($this->mode, [self::MODE_DISCARD, self::MODE_BLOCK])) {
34-
throw new InvalidArgumentException(\sprintf('Supported modes are "%s".', implode('", "', [self::MODE_DISCARD, self::MODE_BLOCK])));
38+
if (!\in_array($this->mode, self::MODES)) {
39+
throw new InvalidArgumentException(\sprintf('Supported modes are "%s".', implode('", "', self::MODES)));
3540
}
3641

3742
$this->key = new Key($key);
@@ -45,18 +50,31 @@ public function getMode(): int
4550
return $this->mode;
4651
}
4752

48-
public function getKey(): Key
53+
public function shouldDiscardDuplicate(): bool
4954
{
50-
return $this->key;
55+
return \in_array($this->mode, [
56+
self::MODE_DISCARD_DUPLICATE_IN_QUEUE,
57+
self::MODE_DISCARD_DUPLICATE_IN_QUEUE_OR_PROCESS,
58+
]);
5159
}
5260

53-
public function getTtl(): ?float
61+
public function shouldBlockDuplicateInProcess(): bool
5462
{
55-
return $this->ttl;
63+
return self::MODE_BLOCK_DUPLICATE_IN_PROCESS === $this->mode;
5664
}
5765

5866
public function shouldBeReleasedBeforeHandlerCall(): bool
5967
{
60-
return $this->shouldBeReleasedBeforeHandlerCall;
68+
return self::MODE_DISCARD_DUPLICATE_IN_QUEUE === $this->mode;
69+
}
70+
71+
public function getKey(): Key
72+
{
73+
return $this->key;
74+
}
75+
76+
public function getTtl(): ?float
77+
{
78+
return $this->ttl;
6179
}
6280
}

src/Symfony/Component/Messenger/Tests/Middleware/LockMiddlewareTest.php

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ public function testLockMiddlewareIgnoreIfMessageIsNotLockable()
3636
$decorator->handle($envelope, $this->getStackMock(true));
3737
}
3838

39-
public function testLockMiddlewareIfMessageHasKey()
39+
public function testLockMiddlewareIfMessageHasKeyWithFirstMode()
4040
{
4141
$message = new DummyMessage('Hello');
42-
$envelope = new Envelope($message, [new LockStamp(LockStamp::MODE_DISCARD, 'id')]);
42+
$envelope = new Envelope($message, [new LockStamp(LockStamp::MODE_DISCARD_DUPLICATE_IN_QUEUE, 'id')]);
4343

4444
if (SemaphoreStore::isSupported()) {
4545
$store = new SemaphoreStore();
@@ -53,7 +53,7 @@ public function testLockMiddlewareIfMessageHasKey()
5353
$this->assertNotNull($envelope->last(LockStamp::class));
5454

5555
$message2 = new DummyMessage('Hello');
56-
$envelope2 = new Envelope($message2, [new LockStamp(LockStamp::MODE_DISCARD, 'id')]);
56+
$envelope2 = new Envelope($message2, [new LockStamp(LockStamp::MODE_DISCARD_DUPLICATE_IN_QUEUE, 'id')]);
5757

5858
$decorator->handle($envelope2, $this->getStackMock(false));
5959

@@ -62,7 +62,68 @@ public function testLockMiddlewareIfMessageHasKey()
6262
$decorator->handle($envelope, $this->getStackMock(true));
6363

6464
$message3 = new DummyMessage('Hello');
65-
$envelope3 = new Envelope($message3, [new LockStamp(LockStamp::MODE_DISCARD, 'id')]);
65+
$envelope3 = new Envelope($message3, [new LockStamp(LockStamp::MODE_DISCARD_DUPLICATE_IN_QUEUE, 'id')]);
66+
$decorator->handle($envelope3, $this->getStackMock(true));
67+
}
68+
69+
public function testLockMiddlewareIfMessageHasKeyWithSecondMode()
70+
{
71+
$message = new DummyMessage('Hello');
72+
$envelope = new Envelope($message, [new LockStamp(LockStamp::MODE_DISCARD_DUPLICATE_IN_QUEUE_OR_PROCESS, 'id')]);
73+
74+
if (SemaphoreStore::isSupported()) {
75+
$store = new SemaphoreStore();
76+
} else {
77+
$store = new FlockStore();
78+
}
79+
80+
$decorator = new LockMiddleware(new LockFactory($store));
81+
82+
$envelope = $decorator->handle($envelope, $this->getStackMock(true));
83+
$this->assertNotNull($envelope->last(LockStamp::class));
84+
85+
$message2 = new DummyMessage('Hello');
86+
$envelope2 = new Envelope($message2, [new LockStamp(LockStamp::MODE_DISCARD_DUPLICATE_IN_QUEUE_OR_PROCESS, 'id')]);
87+
88+
$decorator->handle($envelope2, $this->getStackMock(false));
89+
90+
// Simulate receiving the first message
91+
$envelope = $envelope->with(new ReceivedStamp('transport'));
92+
$decorator->handle($envelope, $this->getStackMock(true));
93+
94+
$message3 = new DummyMessage('Hello');
95+
$envelope3 = new Envelope($message3, [new LockStamp(LockStamp::MODE_DISCARD_DUPLICATE_IN_QUEUE_OR_PROCESS, 'id')]);
96+
$decorator->handle($envelope3, $this->getStackMock(true));
97+
}
98+
99+
public function testLockMiddlewareIfMessageHasKeyWithThirdMode()
100+
{
101+
$message = new DummyMessage('Hello');
102+
$envelope = new Envelope($message, [new LockStamp(LockStamp::MODE_BLOCK_DUPLICATE_IN_PROCESS, 'id')]);
103+
104+
if (SemaphoreStore::isSupported()) {
105+
$store = new SemaphoreStore();
106+
} else {
107+
$store = new FlockStore();
108+
}
109+
110+
$decorator = new LockMiddleware(new LockFactory($store));
111+
112+
$envelope = $decorator->handle($envelope, $this->getStackMock(true));
113+
$this->assertNotNull($envelope->last(LockStamp::class));
114+
115+
$message2 = new DummyMessage('Hello');
116+
$envelope2 = new Envelope($message2, [new LockStamp(LockStamp::MODE_BLOCK_DUPLICATE_IN_PROCESS, 'id')]);
117+
118+
// Not blocking when adding the message in the queue.
119+
$decorator->handle($envelope2, $this->getStackMock(true));
120+
121+
// Simulate receiving the first message
122+
$envelope = $envelope->with(new ReceivedStamp('transport'));
123+
$decorator->handle($envelope, $this->getStackMock(true));
124+
125+
$message3 = new DummyMessage('Hello');
126+
$envelope3 = new Envelope($message3, [new LockStamp(LockStamp::MODE_BLOCK_DUPLICATE_IN_PROCESS, 'id')]);
66127
$decorator->handle($envelope3, $this->getStackMock(true));
67128
}
68129
}

0 commit comments

Comments
 (0)
0