@@ -120,39 +120,55 @@ public static function pop($queue)
120
120
return json_decode ($ item , true );
121
121
}
122
122
123
- /**
124
- * Pop an item off the end of the specified queues, using blocking list pop,
125
- * decode it and return it.
126
- *
127
- * @param array $queues
128
- * @param int $timeout
129
- * @return null|array Decoded item from the queue.
130
- */
131
- public static function blpop (array $ queues , $ timeout )
132
- {
133
- $ list = array ();
134
- foreach ($ queues AS $ queue ) {
135
- $ list [] = 'queue: ' . $ queue ;
136
- }
137
-
138
- $ item = self ::redis ()->blpop ($ list , (int )$ timeout );
139
-
140
- if (!$ item ) {
141
- return ;
142
- }
143
-
144
- /**
145
- * Normally the Resque_Redis class returns queue names without the prefix
146
- * But the blpop is a bit different. It returns the name as prefix:queue:name
147
- * So we need to strip off the prefix:queue: part
148
- */
149
- $ queue = substr ($ item [0 ], strlen (self ::redis ()->getPrefix () . 'queue: ' ));
150
-
151
- return array (
152
- 'queue ' => $ queue ,
153
- 'payload ' => json_decode ($ item [1 ], true )
154
- );
155
- }
123
+ /**
124
+ * Remove items of the specified queue
125
+ *
126
+ * @param string $queue The name of the queue to fetch an item from.
127
+ * @param array $items
128
+ * @return integer number of deleted items
129
+ */
130
+ public static function dequeue ($ queue , $ items = Array ())
131
+ {
132
+ if (count ($ items ) > 0 ) {
133
+ return self ::removeItems ($ queue , $ items );
134
+ } else {
135
+ return self ::removeList ($ queue );
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Pop an item off the end of the specified queues, using blocking list pop,
141
+ * decode it and return it.
142
+ *
143
+ * @param array $queues
144
+ * @param int $timeout
145
+ * @return null|array Decoded item from the queue.
146
+ */
147
+ public static function blpop (array $ queues , $ timeout )
148
+ {
149
+ $ list = array ();
150
+ foreach ($ queues AS $ queue ) {
151
+ $ list [] = 'queue: ' . $ queue ;
152
+ }
153
+
154
+ $ item = self ::redis ()->blpop ($ list , (int )$ timeout );
155
+
156
+ if (!$ item ) {
157
+ return ;
158
+ }
159
+
160
+ /**
161
+ * Normally the Resque_Redis class returns queue names without the prefix
162
+ * But the blpop is a bit different. It returns the name as prefix:queue:name
163
+ * So we need to strip off the prefix:queue: part
164
+ */
165
+ $ queue = substr ($ item [0 ], strlen (self ::redis ()->getPrefix () . 'queue: ' ));
166
+
167
+ return array (
168
+ 'queue ' => $ queue ,
169
+ 'payload ' => json_decode ($ item [1 ], true )
170
+ );
171
+ }
156
172
157
173
/**
158
174
* Return the size (number of pending jobs) of the specified queue.
@@ -215,4 +231,72 @@ public static function queues()
215
231
}
216
232
return $ queues ;
217
233
}
234
+
235
+ /**
236
+ * Remove Items from the queue
237
+ * Safely moving each item to a temporary queue before processing it
238
+ * If the Job matches, counts otherwise puts it in a requeue_queue
239
+ * which at the end eventually be copied back into the original queue
240
+ *
241
+ * @private
242
+ *
243
+ * @param string $queue The name of the queue
244
+ * @param array $items
245
+ * @return integer number of deleted items
246
+ */
247
+ private static function removeItems ($ queue , $ items = Array ())
248
+ {
249
+ $ counter = 0 ;
250
+ $ originalQueue = 'queue: ' . $ queue ;
251
+ $ tempQueue = $ originalQueue . ':temp: ' . time ();
252
+ $ requeueQueue = $ tempQueue . ':requeue ' ;
253
+
254
+ // move each item from original queue to temp queue and process it
255
+ $ finished = false ;
256
+ while (!$ finished ) {
257
+ $ string = self ::redis ()->rpoplpush ($ originalQueue , self ::redis ()->getPrefix () . $ tempQueue );
258
+
259
+ if (!empty ($ string )) {
260
+ $ decoded = json_decode ($ string , true );
261
+ if (in_array ($ decoded ['class ' ], $ items )) {
262
+ $ counter ++;
263
+ } else {
264
+ self ::redis ()->rpoplpush ($ tempQueue , self ::redis ()->getPrefix () . $ requeueQueue );
265
+ }
266
+ } else {
267
+ $ finished = true ;
268
+ }
269
+ }
270
+
271
+ // move back from temp queue to original queue
272
+ $ finished = false ;
273
+ while (!$ finished ) {
274
+ $ string = self ::redis ()->rpoplpush ($ requeueQueue , self ::redis ()->getPrefix () .$ originalQueue );
275
+ if (empty ($ string )) {
276
+ $ finished = true ;
277
+ }
278
+ }
279
+
280
+ // remove temp queue and requeue queue
281
+ self ::redis ()->del ($ requeueQueue );
282
+ self ::redis ()->del ($ tempQueue );
283
+
284
+ return $ counter ;
285
+ }
286
+
287
+ /**
288
+ * Remove List
289
+ *
290
+ * @private
291
+ *
292
+ * @params string $queue the name of the queue
293
+ * @return integer number of deleted items belongs to this list
294
+ */
295
+ private static function removeList ($ queue )
296
+ {
297
+ $ counter = self ::size ($ queue );
298
+ $ result = self ::redis ()->del ('queue: ' . $ queue );
299
+ return ($ result == 1 ) ? $ counter : 0 ;
300
+ }
218
301
}
302
+
0 commit comments