Skip to content

Commit 2e54349

Browse files
Add handling for delayed message to redis transport
1 parent 7f39f36 commit 2e54349

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class Connection
3737

3838
private $connection;
3939
private $stream;
40+
private $queue;
4041
private $group;
4142
private $consumer;
4243
private $autoSetup;
@@ -52,6 +53,7 @@ public function __construct(array $configuration, array $connectionCredentials =
5253
$this->connection->connect($connectionCredentials['host'] ?? '127.0.0.1', $connectionCredentials['port'] ?? 6379);
5354
$this->connection->setOption(\Redis::OPT_SERIALIZER, $redisOptions['serializer'] ?? \Redis::SERIALIZER_PHP);
5455
$this->stream = $configuration['stream'] ?? self::DEFAULT_OPTIONS['stream'];
56+
$this->queue = $this->stream.'_queue';
5557
$this->group = $configuration['group'] ?? self::DEFAULT_OPTIONS['group'];
5658
$this->consumer = $configuration['consumer'] ?? self::DEFAULT_OPTIONS['consumer'];
5759
$this->autoSetup = $configuration['auto_setup'] ?? self::DEFAULT_OPTIONS['auto_setup'];
@@ -93,6 +95,18 @@ public function get(): ?array
9395
$this->setup();
9496
}
9597

98+
$queuedMessageCount = $this->connection->zcount($this->queue, 0, time());
99+
100+
if ($queuedMessageCount) {
101+
foreach ($this->connection->zpopmin($this->queue, $queuedMessageCount) as $queuedMessage => $time) {
102+
$queuedMessage = json_encode($queuedMessage, true);
103+
// if a futured placed message is actually popped because of a race condition with
104+
// another running message consumer, the message is readded to the queue by add function
105+
// else its just added stream and will be available for all stream consumers
106+
$this->add($queuedMessage['body'], $queuedMessage['headers'], (time() - $time) * 1000);
107+
}
108+
}
109+
96110
$messageId = '>'; // will receive new messages
97111

98112
if ($this->couldHavePendingMessages) {
@@ -163,17 +177,26 @@ public function reject(string $id): void
163177
}
164178
}
165179

166-
public function add(string $body, array $headers): void
180+
/**
181+
* @param int $delay The delay in milliseconds
182+
*/
183+
public function add(string $body, array $headers, int $delay = 0): void
167184
{
168185
if ($this->autoSetup) {
169186
$this->setup();
170187
}
171188

172189
$e = null;
173190
try {
174-
$added = $this->connection->xadd($this->stream, '*', ['message' => json_encode(
175-
['body' => $body, 'headers' => $headers]
176-
)]);
191+
$message = json_encode(['body' => $body, 'headers' => $headers]);
192+
193+
if ($delay > 0) { // the delay could be smaller 0 in a queued message
194+
$added = $this->connection->zadd($this->queue, ['NX'], time() + ($delay / 1000), $message);
195+
} else {
196+
$added = $this->connection->xadd($this->stream, '*', [
197+
'message' => $message,
198+
]);
199+
}
177200
} catch (\RedisException $e) {
178201
}
179202

src/Symfony/Component/Messenger/Transport/RedisExt/RedisSender.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Messenger\Transport\RedisExt;
1313

1414
use Symfony\Component\Messenger\Envelope;
15+
use Symfony\Component\Messenger\Stamp\DelayStamp;
1516
use Symfony\Component\Messenger\Transport\Sender\SenderInterface;
1617
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
1718

@@ -39,7 +40,11 @@ public function send(Envelope $envelope): Envelope
3940
{
4041
$encodedMessage = $this->serializer->encode($envelope);
4142

42-
$this->connection->add($encodedMessage['body'], $encodedMessage['headers'] ?? []);
43+
/** @var DelayStamp|null $delayStamp */
44+
$delayStamp = $envelope->last(DelayStamp::class);
45+
$delay = null !== $delayStamp ? $delayStamp->getDelay() : 0;
46+
47+
$this->connection->add($encodedMessage['body'], $encodedMessage['headers'] ?? [], $delay);
4348

4449
return $envelope;
4550
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy