@@ -37,6 +37,7 @@ class Connection
37
37
38
38
private $ connection ;
39
39
private $ stream ;
40
+ private $ queue ;
40
41
private $ group ;
41
42
private $ consumer ;
42
43
private $ autoSetup ;
@@ -52,6 +53,7 @@ public function __construct(array $configuration, array $connectionCredentials =
52
53
$ this ->connection ->connect ($ connectionCredentials ['host ' ] ?? '127.0.0.1 ' , $ connectionCredentials ['port ' ] ?? 6379 );
53
54
$ this ->connection ->setOption (\Redis::OPT_SERIALIZER , $ redisOptions ['serializer ' ] ?? \Redis::SERIALIZER_PHP );
54
55
$ this ->stream = $ configuration ['stream ' ] ?? self ::DEFAULT_OPTIONS ['stream ' ];
56
+ $ this ->queue = $ this ->stream .'_queue ' ;
55
57
$ this ->group = $ configuration ['group ' ] ?? self ::DEFAULT_OPTIONS ['group ' ];
56
58
$ this ->consumer = $ configuration ['consumer ' ] ?? self ::DEFAULT_OPTIONS ['consumer ' ];
57
59
$ this ->autoSetup = $ configuration ['auto_setup ' ] ?? self ::DEFAULT_OPTIONS ['auto_setup ' ];
@@ -93,6 +95,18 @@ public function get(): ?array
93
95
$ this ->setup ();
94
96
}
95
97
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
+
96
110
$ messageId = '> ' ; // will receive new messages
97
111
98
112
if ($ this ->couldHavePendingMessages ) {
@@ -163,17 +177,26 @@ public function reject(string $id): void
163
177
}
164
178
}
165
179
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
167
184
{
168
185
if ($ this ->autoSetup ) {
169
186
$ this ->setup ();
170
187
}
171
188
172
189
$ e = null ;
173
190
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
+ }
177
200
} catch (\RedisException $ e ) {
178
201
}
179
202
0 commit comments