@@ -3,6 +3,7 @@ package redis
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "math"
6
7
"strconv"
7
8
"strings"
8
9
"sync"
@@ -15,6 +16,8 @@ import (
15
16
log "github.com/sirupsen/logrus"
16
17
)
17
18
19
+ const count = math .MaxInt64
20
+
18
21
// Broker based on redis STREAM and ZSET.
19
22
// Implements a delayed queue with support for retries.
20
23
type Stream struct {
@@ -275,6 +278,12 @@ func (b *Stream) Stop() error {
275
278
}()
276
279
err := b .Redis .XGroupDelConsumer (
277
280
context .TODO (), b .stream , b .streamGroup , b .consumerName ).Err ()
281
+ if err != nil {
282
+ if strings .HasPrefix (err .Error (), "NOGROUP" ) {
283
+ b .isConsuming = false
284
+ return nil
285
+ }
286
+ }
278
287
b .isConsuming = false
279
288
return err
280
289
}
@@ -305,10 +314,18 @@ func (b *Stream) Stats() *disq.Stats {
305
314
}
306
315
}
307
316
317
+ func (b * Stream ) Name () string {
318
+ return b .opts .Name
319
+ }
320
+
308
321
func (b * Stream ) Status () bool {
309
322
return b .isConsuming
310
323
}
311
324
325
+ func (b * Stream ) Config () disq.Config {
326
+ return b .opts
327
+ }
328
+
312
329
func unixMs (tm time.Time ) int64 {
313
330
return tm .UnixNano () / int64 (time .Millisecond )
314
331
}
@@ -404,3 +421,124 @@ func (b *Stream) schedulePending(ctx context.Context) (int, error) {
404
421
405
422
return len (pending ), nil
406
423
}
424
+
425
+ func (q * Stream ) ZRangebyScore (ctx context.Context , min string , max string ) ([]string , error ) {
426
+ bodies , err := q .opts .Redis .ZRangeByScore (ctx , q .zset , & redis.ZRangeBy {
427
+ Min : min ,
428
+ Max : max ,
429
+ }).Result ()
430
+ if err != nil {
431
+ return nil , err
432
+ }
433
+ return bodies , nil
434
+ }
435
+
436
+ func (q * Stream ) XPendingExt (ctx context.Context , start string , end string ) ([]redis.XPendingExt , error ) {
437
+ pending , err := q .opts .Redis .XPendingExt (ctx , & redis.XPendingExtArgs {
438
+ Stream : q .stream ,
439
+ Group : q .streamGroup ,
440
+ Start : start ,
441
+ End : end ,
442
+ Count : count ,
443
+ }).Result ()
444
+ if err != nil {
445
+ if strings .HasPrefix (err .Error (), "NOGROUP" ) {
446
+ _ = q .Redis .XGroupCreateMkStream (ctx , q .stream , q .streamGroup , "0" ).Err ()
447
+ }
448
+ return nil , err
449
+ }
450
+ return pending , nil
451
+ }
452
+
453
+ func (q * Stream ) XRange (ctx context.Context , start string , end string ) * redis.XMessageSliceCmd {
454
+ xrange := q .Redis .XRange (ctx , q .stream , start , end )
455
+ return xrange
456
+ }
457
+
458
+ func (q * Stream ) XRangeN (ctx context.Context , start string , end string , count int64 ) * redis.XMessageSliceCmd {
459
+ xrange := q .Redis .XRangeN (ctx , q .stream , start , end , count )
460
+ return xrange
461
+ }
462
+
463
+ func (q * Stream ) XPending (ctx context.Context ) (* redis.XPending , error ) {
464
+ pending , err := q .Redis .XPending (ctx , q .stream , q .streamGroup ).Result ()
465
+ if err != nil {
466
+ if strings .HasPrefix (err .Error (), "NOGROUP" ) {
467
+ _ = q .opts .Redis .XGroupCreateMkStream (ctx , q .stream , q .streamGroup , "0" ).Err ()
468
+ }
469
+ }
470
+ return pending , err
471
+ }
472
+
473
+ func (q * Stream ) ZRem (ctx context.Context , body string ) * redis.IntCmd {
474
+ result := q .Redis .ZRem (ctx , q .zset , body )
475
+ return result
476
+ }
477
+
478
+ func (q * Stream ) XDel (ctx context.Context , id string ) * redis.IntCmd {
479
+ result := q .Redis .XDel (ctx , q .stream , id )
480
+ return result
481
+ }
482
+
483
+ func (q * Stream ) XAck (ctx context.Context , id string ) * redis.IntCmd {
484
+ result := q .Redis .XAck (ctx , q .stream , id )
485
+ return result
486
+ }
487
+
488
+ func (q * Stream ) XInfoConsumers (ctx context.Context ) * redis.XInfoConsumersCmd {
489
+ consumersInfo := q .Redis .XInfoConsumers (ctx , q .stream , q .streamGroup )
490
+ return consumersInfo
491
+ }
492
+
493
+ func (q * Stream ) XInfoStream (ctx context.Context ) * redis.XInfoStreamCmd {
494
+ infoStream := q .Redis .XInfoStream (ctx , q .stream )
495
+ return infoStream
496
+ }
497
+
498
+ func (q * Stream ) ExportMessagesfromStream (ctx context.Context ) ([]disq.Message , error ) {
499
+ xmsgs , err := q .XRange (ctx , "-" , "+" ).Result ()
500
+ if err != nil {
501
+ return nil , err
502
+ }
503
+
504
+ msgs := make ([]disq.Message , len (xmsgs ))
505
+ for i := range xmsgs {
506
+ xmsg := & xmsgs [i ]
507
+ msg := & msgs [i ]
508
+
509
+ err = StreamUnmarshalMessage (msg , xmsg )
510
+
511
+ if err != nil {
512
+ return nil , err
513
+ }
514
+ }
515
+ return msgs , nil
516
+ }
517
+
518
+ func (q * Stream ) ExportMessagesfromStreamXACK (ctx context.Context ) ([]disq.Message , error ) {
519
+ xmsgs , err := q .XRange (ctx , "-" , "+" ).Result ()
520
+ if err != nil {
521
+ return nil , err
522
+ }
523
+
524
+ msgs := make ([]disq.Message , len (xmsgs ))
525
+ for i := range xmsgs {
526
+ xmsg := & xmsgs [i ]
527
+ msg := & msgs [i ]
528
+
529
+ err = StreamUnmarshalMessage (msg , xmsg )
530
+
531
+ if err != nil {
532
+ return nil , err
533
+ }
534
+ if err := q .opts .Redis .XAck (ctx , q .stream , q .streamGroup , xmsg .ID ).Err (); err != nil {
535
+ return nil , err
536
+ }
537
+
538
+ err = q .opts .Redis .XDel (ctx , q .stream , xmsg .ID ).Err ()
539
+ if err != nil {
540
+ return nil , err
541
+ }
542
+ }
543
+ return msgs , nil
544
+ }
0 commit comments