@@ -292,6 +292,149 @@ extension RedisClient {
292
292
}
293
293
}
294
294
295
+ // MARK: Blocking Pop
296
+
297
+ extension RedisClient {
298
+ /// Removes the element from a sorted set with the lowest score, blocking until an element is
299
+ /// available.
300
+ ///
301
+ /// - Important:
302
+ /// This will block the connection from completing further commands until an element
303
+ /// is available to pop from the set.
304
+ ///
305
+ /// It is **highly** recommended to set a reasonable `timeout`
306
+ /// or to use the non-blocking `zpopmin` method where possible.
307
+ ///
308
+ /// See [https://redis.io/commands/bzpopmin](https://redis.io/commands/bzpopmin)
309
+ /// - Parameters:
310
+ /// - key: The key identifying the sorted set in Redis.
311
+ /// - timeout: The time (in seconds) to wait. `0` means indefinitely.
312
+ /// - Returns:
313
+ /// The element and its associated score that was popped from the sorted set,
314
+ /// or `nil` if the timeout was reached.
315
+ @inlinable
316
+ public func bzpopmin(
317
+ from key: String ,
318
+ timeout: Int = 0
319
+ ) -> EventLoopFuture < ( Double , RESPValue ) ? > {
320
+ return bzpopmin ( from: [ key] , timeout: timeout)
321
+ . map {
322
+ guard let response = $0 else { return nil }
323
+ return ( response. 1 , response. 2 )
324
+ }
325
+ }
326
+
327
+ /// Removes the element from a sorted set with the lowest score, blocking until an element is
328
+ /// available.
329
+ ///
330
+ /// - Important:
331
+ /// This will block the connection from completing further commands until an element
332
+ /// is available to pop from the group of sets.
333
+ ///
334
+ /// It is **highly** recommended to set a reasonable `timeout`
335
+ /// or to use the non-blocking `zpopmin` method where possible.
336
+ ///
337
+ /// See [https://redis.io/commands/bzpopmin](https://redis.io/commands/bzpopmin)
338
+ /// - Parameters:
339
+ /// - keys: A list of sorted set keys in Redis.
340
+ /// - timeout: The time (in seconds) to wait. `0` means indefinitely.
341
+ /// - Returns:
342
+ /// If timeout was reached, `nil`.
343
+ ///
344
+ /// Otherwise, the key of the sorted set the element was removed from, the element itself,
345
+ /// and its associated score is returned.
346
+ @inlinable
347
+ public func bzpopmin(
348
+ from keys: [ String ] ,
349
+ timeout: Int = 0
350
+ ) -> EventLoopFuture < ( String , Double , RESPValue ) ? > {
351
+ return self . _bzpop ( command: " BZPOPMIN " , keys, timeout)
352
+ }
353
+
354
+ /// Removes the element from a sorted set with the highest score, blocking until an element is
355
+ /// available.
356
+ ///
357
+ /// - Important:
358
+ /// This will block the connection from completing further commands until an element
359
+ /// is available to pop from the set.
360
+ ///
361
+ /// It is **highly** recommended to set a reasonable `timeout`
362
+ /// or to use the non-blocking `zpopmax` method where possible.
363
+ ///
364
+ /// See [https://redis.io/commands/bzpopmax](https://redis.io/commands/bzpopmax)
365
+ /// - Parameters:
366
+ /// - key: The key identifying the sorted set in Redis.
367
+ /// - timeout: The time (in seconds) to wait. `0` means indefinitely.
368
+ /// - Returns:
369
+ /// The element and its associated score that was popped from the sorted set,
370
+ /// or `nil` if the timeout was reached.
371
+ @inlinable
372
+ public func bzpopmax(
373
+ from key: String ,
374
+ timeout: Int = 0
375
+ ) -> EventLoopFuture < ( Double , RESPValue ) ? > {
376
+ return self . bzpopmax ( from: [ key] , timeout: timeout)
377
+ . map {
378
+ guard let response = $0 else { return nil }
379
+ return ( response. 1 , response. 2 )
380
+ }
381
+ }
382
+
383
+ /// Removes the element from a sorted set with the highest score, blocking until an element is
384
+ /// available.
385
+ ///
386
+ /// - Important:
387
+ /// This will block the connection from completing further commands until an element
388
+ /// is available to pop from the group of sets.
389
+ ///
390
+ /// It is **highly** recommended to set a reasonable `timeout`
391
+ /// or to use the non-blocking `zpopmax` method where possible.
392
+ ///
393
+ /// See [https://redis.io/commands/bzpopmax](https://redis.io/commands/bzpopmax)
394
+ /// - Parameters:
395
+ /// - keys: A list of sorted set keys in Redis.
396
+ /// - timeout: The time (in seconds) to wait. `0` means indefinitely.
397
+ /// - Returns:
398
+ /// If timeout was reached, `nil`.
399
+ ///
400
+ /// Otherwise, the key of the sorted set the element was removed from, the element itself,
401
+ /// and its associated score is returned.
402
+ @inlinable
403
+ public func bzpopmax(
404
+ from keys: [ String ] ,
405
+ timeout: Int = 0
406
+ ) -> EventLoopFuture < ( String , Double , RESPValue ) ? > {
407
+ return self . _bzpop ( command: " BZPOPMAX " , keys, timeout)
408
+ }
409
+
410
+ @usableFromInline
411
+ func _bzpop(
412
+ command: String ,
413
+ _ keys: [ String ] ,
414
+ _ timeout: Int
415
+ ) -> EventLoopFuture < ( String , Double , RESPValue ) ? > {
416
+ let args = keys as [ RESPValueConvertible ] + [ timeout]
417
+ return send ( command: command, with: args)
418
+ // per the Redis docs,
419
+ // we will receive either a nil response,
420
+ // or an array with 3 elements in the form [Set Key, Element Score, Element Value]
421
+ . flatMapThrowing {
422
+ guard !$0. isNull else { return nil }
423
+ guard let response = [ RESPValue] ( $0) else {
424
+ throw NIORedisError . responseConversion ( to: [ RESPValue ] . self)
425
+ }
426
+ assert ( response. count == 3 , " Unexpected response size returned! " )
427
+ guard
428
+ let key = response [ 0 ] . string,
429
+ let score = Double ( response [ 1 ] )
430
+ else {
431
+ throw NIORedisError . assertionFailure ( message: " Unexpected structure in response: \( response) " )
432
+ }
433
+ return ( key, score, response [ 2 ] )
434
+ }
435
+ }
436
+ }
437
+
295
438
// MARK: Increment
296
439
297
440
extension RedisClient {
0 commit comments