|
30 | 30 | import org.springframework.data.redis.connection.ReactiveRedisConnection.CommandResponse; |
31 | 31 | import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand; |
32 | 32 | import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse; |
| 33 | +import org.springframework.data.redis.connection.RedisStreamCommands.XPendingOptions; |
33 | 34 | import org.springframework.data.redis.connection.RedisZSetCommands.Limit; |
34 | 35 | import org.springframework.data.redis.connection.stream.ByteBufferRecord; |
35 | 36 | import org.springframework.data.redis.connection.stream.Consumer; |
| 37 | +import org.springframework.data.redis.connection.stream.PendingMessage; |
| 38 | +import org.springframework.data.redis.connection.stream.PendingMessages; |
| 39 | +import org.springframework.data.redis.connection.stream.PendingMessagesSummary; |
36 | 40 | import org.springframework.data.redis.connection.stream.ReadOffset; |
37 | 41 | import org.springframework.data.redis.connection.stream.RecordId; |
38 | 42 | import org.springframework.data.redis.connection.stream.StreamOffset; |
39 | 43 | import org.springframework.data.redis.connection.stream.StreamReadOptions; |
40 | 44 | import org.springframework.data.redis.connection.stream.StreamRecords; |
41 | 45 | import org.springframework.lang.Nullable; |
42 | 46 | import org.springframework.util.Assert; |
| 47 | +import org.springframework.util.StringUtils; |
43 | 48 |
|
44 | 49 | /** |
45 | 50 | * Stream-specific Redis commands executed using reactive infrastructure. |
@@ -410,6 +415,225 @@ default Mono<Long> xLen(ByteBuffer key) { |
410 | 415 | */ |
411 | 416 | Flux<NumericResponse<KeyCommand, Long>> xLen(Publisher<KeyCommand> commands); |
412 | 417 |
|
| 418 | +/** |
| 419 | + * Obtain the {@link PendingMessagesSummary} for a given {@literal consumer group}. |
| 420 | + * |
| 421 | + * @param key the {@literal key} the stream is stored at. Must not be {@literal null}. |
| 422 | + * @param groupName the name of the {@literal consumer group}. Must not be {@literal null}. |
| 423 | + * @return {@link Mono} emitting a summary of pending messages within the given {@literal consumer group}. |
| 424 | + * @see <a href="https://redis.io/commands/xpending">Redis Documentation: xpending</a> |
| 425 | + * @since 2.3 |
| 426 | + */ |
| 427 | +default Mono<PendingMessagesSummary> xPending(ByteBuffer key, String groupName) { |
| 428 | + |
| 429 | +Assert.notNull(key, "Key must not be null!"); |
| 430 | +Assert.notNull(groupName, "GroupName must not be null!"); |
| 431 | + |
| 432 | +return xPendingSummary(Mono.just(new PendingRecordsCommand(key, groupName, null, Range.unbounded(), null))).next() |
| 433 | +.map(CommandResponse::getOutput); |
| 434 | +} |
| 435 | + |
| 436 | +/** |
| 437 | + * Obtain the {@link PendingMessagesSummary} for a given {@literal consumer group}. |
| 438 | + * |
| 439 | + * @param commands must not be {@literal null}.. |
| 440 | + * @return {@link Flux} emitting a summary of pending messages within the given {@literal consumer group} one by one. |
| 441 | + * @see <a href="https://redis.io/commands/xpending">Redis Documentation: xpending</a> |
| 442 | + * @since 2.3 |
| 443 | + */ |
| 444 | +Flux<CommandResponse<PendingRecordsCommand, PendingMessagesSummary>> xPendingSummary( |
| 445 | +Publisher<PendingRecordsCommand> commands); |
| 446 | + |
| 447 | +/** |
| 448 | + * Obtained detailed information about all pending messages for a given {@link Consumer}. |
| 449 | + * |
| 450 | + * @param key the {@literal key} the stream is stored at. Must not be {@literal null}. |
| 451 | + * @param consumer the consumer to fetch {@link PendingMessages} for. Must not be {@literal null}. |
| 452 | + * @return {@link Mono} emitting pending messages for the given {@link Consumer}. |
| 453 | + * @see <a href="https://redis.io/commands/xpending">Redis Documentation: xpending</a> |
| 454 | + * @since 2.3 |
| 455 | + */ |
| 456 | +@Nullable |
| 457 | +default Mono<PendingMessages> xPending(ByteBuffer key, Consumer consumer) { |
| 458 | +return xPending(key, consumer.getGroup(), consumer.getName()); |
| 459 | +} |
| 460 | + |
| 461 | +/** |
| 462 | + * Obtained detailed information about all pending messages for a given {@literal consumer}. |
| 463 | + * |
| 464 | + * @param key the {@literal key} the stream is stored at. Must not be {@literal null}. |
| 465 | + * @param groupName the name of the {@literal consumer group}. Must not be {@literal null}. |
| 466 | + * @param consumerName the consumer to fetch {@link PendingMessages} for. Must not be {@literal null}. |
| 467 | + * @return {@link Mono} emitting pending messages for the given {@link Consumer}. |
| 468 | + * @see <a href="https://redis.io/commands/xpending">Redis Documentation: xpending</a> |
| 469 | + * @since 2.3 |
| 470 | + */ |
| 471 | +@Nullable |
| 472 | +default Mono<PendingMessages> xPending(ByteBuffer key, String groupName, String consumerName) { |
| 473 | +return xPending(Mono.just(new PendingRecordsCommand(key, groupName, consumerName, Range.unbounded(), null))).next() |
| 474 | +.map(CommandResponse::getOutput); |
| 475 | +} |
| 476 | + |
| 477 | +/** |
| 478 | + * Obtain detailed information about pending {@link PendingMessage messages} for a given {@link Range} within a |
| 479 | + * {@literal consumer group}. |
| 480 | + * |
| 481 | + * @param key the {@literal key} the stream is stored at. Must not be {@literal null}. |
| 482 | + * @param groupName the name of the {@literal consumer group}. Must not be {@literal null}. |
| 483 | + * @param range the range of messages ids to search within. Must not be {@literal null}. |
| 484 | + * @param count limit the number of results. Must not be {@literal null}. |
| 485 | + * @return {@link Mono} emitting pending messages for the given {@literal consumer group}. transaction. |
| 486 | + * @see <a href="https://redis.io/commands/xpending">Redis Documentation: xpending</a> |
| 487 | + * @since 2.3 |
| 488 | + */ |
| 489 | +default Mono<PendingMessages> xPending(ByteBuffer key, String groupName, Range<?> range, Long count) { |
| 490 | +return xPending(Mono.just(new PendingRecordsCommand(key, groupName, null, range, count))).next() |
| 491 | +.map(CommandResponse::getOutput); |
| 492 | +} |
| 493 | + |
| 494 | +/** |
| 495 | + * Obtain detailed information about pending {@link PendingMessage messages} for a given {@link Range} and |
| 496 | + * {@link Consumer} within a {@literal consumer group}. |
| 497 | + * |
| 498 | + * @param key the {@literal key} the stream is stored at. Must not be {@literal null}. |
| 499 | + * @param consumer the name of the {@link Consumer}. Must not be {@literal null}. |
| 500 | + * @param range the range of messages ids to search within. Must not be {@literal null}. |
| 501 | + * @param count limit the number of results. Must not be {@literal null}. |
| 502 | + * @return {@link Mono} emitting pending messages for the given {@link Consumer}. |
| 503 | + * @see <a href="https://redis.io/commands/xpending">Redis Documentation: xpending</a> |
| 504 | + * @since 2.3 |
| 505 | + */ |
| 506 | +default Mono<PendingMessages> xPending(ByteBuffer key, Consumer consumer, Range<?> range, Long count) { |
| 507 | +return xPending(key, consumer.getGroup(), consumer.getName(), range, count); |
| 508 | +} |
| 509 | + |
| 510 | +/** |
| 511 | + * Obtain detailed information about pending {@link PendingMessage messages} for a given {@link Range} and |
| 512 | + * {@literal consumer} within a {@literal consumer group}. |
| 513 | + * |
| 514 | + * @param key the {@literal key} the stream is stored at. Must not be {@literal null}. |
| 515 | + * @param groupName the name of the {@literal consumer group}. Must not be {@literal null}. |
| 516 | + * @param consumerName the name of the {@literal consumer}. Must not be {@literal null}. |
| 517 | + * @param range the range of messages ids to search within. Must not be {@literal null}. |
| 518 | + * @param count limit the number of results. Must not be {@literal null}. |
| 519 | + * @return {@link Mono} emitting pending messages for the given {@literal consumer} in given |
| 520 | + * {@literal consumer group}. |
| 521 | + * @see <a href="https://redis.io/commands/xpending">Redis Documentation: xpending</a> |
| 522 | + * @since 2.3 |
| 523 | + */ |
| 524 | +default Mono<PendingMessages> xPending(ByteBuffer key, String groupName, String consumerName, Range<?> range, |
| 525 | +Long count) { |
| 526 | +return xPending(Mono.just(new PendingRecordsCommand(key, groupName, consumerName, range, count))).next() |
| 527 | +.map(CommandResponse::getOutput); |
| 528 | +} |
| 529 | + |
| 530 | +/** |
| 531 | + * Obtain detailed information about pending {@link PendingMessage messages} applying given {@link XPendingOptions |
| 532 | + * options}. |
| 533 | + * |
| 534 | + * @param commands must not be {@literal null}. |
| 535 | + * @return {@link Flux} emitting pending messages matching given criteria. |
| 536 | + * @see <a href="https://redis.io/commands/xpending">Redis Documentation: xpending</a> |
| 537 | + * @since 2.3 |
| 538 | + */ |
| 539 | +Flux<CommandResponse<PendingRecordsCommand, PendingMessages>> xPending(Publisher<PendingRecordsCommand> commands); |
| 540 | + |
| 541 | +/** |
| 542 | + * Value Object holding parameters for obtaining pending messages. |
| 543 | + * |
| 544 | + * @author Christoph Strobl |
| 545 | + * @since 2.3 |
| 546 | + */ |
| 547 | +class PendingRecordsCommand extends KeyCommand { |
| 548 | + |
| 549 | +private final String groupName; |
| 550 | +private final @Nullable String consumerName; |
| 551 | +private final Range<?> range; |
| 552 | +private final @Nullable Long count; |
| 553 | + |
| 554 | +private PendingRecordsCommand(ByteBuffer key, String groupName, @Nullable String consumerName, Range<?> range, |
| 555 | +@Nullable Long count) { |
| 556 | + |
| 557 | +super(key); |
| 558 | + |
| 559 | +this.groupName = groupName; |
| 560 | +this.consumerName = consumerName; |
| 561 | +this.range = range; |
| 562 | +this.count = count; |
| 563 | +} |
| 564 | + |
| 565 | +/** |
| 566 | + * Create new unbounded {@link PendingRecordsCommand}. |
| 567 | + * |
| 568 | + * @param key the {@literal key} the stream is stored at. Must not be {@literal null}. |
| 569 | + * @param groupName the name of the {@literal consumer group}. Must not be {@literal null}. |
| 570 | + * @return new instance of {@link PendingRecordsCommand}. |
| 571 | + */ |
| 572 | +static PendingRecordsCommand pending(ByteBuffer key, String groupName) { |
| 573 | +return new PendingRecordsCommand(key, groupName, null, Range.unbounded(), null); |
| 574 | +} |
| 575 | + |
| 576 | +/** |
| 577 | + * Create new {@link PendingRecordsCommand} with given {@link Range} and limit. |
| 578 | + * |
| 579 | + * @return new instance of {@link XPendingOptions}. |
| 580 | + */ |
| 581 | +public PendingRecordsCommand range(Range<String> range, Long count) { |
| 582 | +return new PendingRecordsCommand(getKey(), groupName, consumerName, range, count); |
| 583 | +} |
| 584 | + |
| 585 | +/** |
| 586 | + * Append given consumer. |
| 587 | + * |
| 588 | + * @param consumerName must not be {@literal null}. |
| 589 | + * @return new instance of {@link PendingRecordsCommand}. |
| 590 | + */ |
| 591 | +public PendingRecordsCommand consumer(String consumerName) { |
| 592 | +return new PendingRecordsCommand(getKey(), groupName, consumerName, range, count); |
| 593 | +} |
| 594 | + |
| 595 | +public String getGroupName() { |
| 596 | +return groupName; |
| 597 | +} |
| 598 | + |
| 599 | +/** |
| 600 | + * @return can be {@literal null}. |
| 601 | + */ |
| 602 | +@Nullable |
| 603 | +public String getConsumerName() { |
| 604 | +return consumerName; |
| 605 | +} |
| 606 | + |
| 607 | +/** |
| 608 | + * @return never {@literal null}. |
| 609 | + */ |
| 610 | +public Range<?> getRange() { |
| 611 | +return range; |
| 612 | +} |
| 613 | + |
| 614 | +/** |
| 615 | + * @return can be {@literal null}. |
| 616 | + */ |
| 617 | +@Nullable |
| 618 | +public Long getCount() { |
| 619 | +return count; |
| 620 | +} |
| 621 | + |
| 622 | +/** |
| 623 | + * @return {@literal true} if a consumer name is present. |
| 624 | + */ |
| 625 | +public boolean hasConsumer() { |
| 626 | +return StringUtils.hasText(consumerName); |
| 627 | +} |
| 628 | + |
| 629 | +/** |
| 630 | + * @return {@literal true} count is set. |
| 631 | + */ |
| 632 | +public boolean isLimited() { |
| 633 | +return count != null && count > -1; |
| 634 | +} |
| 635 | +} |
| 636 | + |
413 | 637 | /** |
414 | 638 | * {@code XRANGE}/{@code XREVRANGE} command parameters. |
415 | 639 | * |
|
0 commit comments