-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[upstream] Add support for XDELEX and XACKDEL, and expand options for XADD and XTRIM #3272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note
Thank you @viktoriya-kutsarova for the excellent deprecated detailed descriptions tells users what replacement to use w/o them having to do software archeology to figure it out. :)
Once Jenkins and PR is green and we resolve the rename concern (#3272 (comment)) this will be ready to merge.
Also note that I will do some final massaging of the commits (couple of squashes and be sure they proper links are in the commits etc..).
Thanks
| if (options.hasTrimOptions()) { | ||
| TrimOptions trim = options.getTrimOptions(); | ||
| var strategy = trim.getTrimStrategy(); | ||
| TrimStrategy strategy = trim.getTrimStrategy(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm an advocate for var and I may bad-influenced you by using var in my previous commit or in some pseudo code when we were discussing things. If so, my bad. In general you will not find it in the main source of many Spring projects (sometimes in the tests).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, let's keep using the proper type.
| private final TrimStrategy trimStrategy; | ||
| private final TrimOperator trimOperator; | ||
| private final @Nullable Long limit; | ||
| private final @Nullable StreamDeletionPolicy pendingReferences; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do have a small concern about possible confusion caused from tbedeletionPolicy/getPendingReferences rename. I believe now that the benefit of a better high-level api name pendingRefereneces does not outweigh the inconsistency between the two names throughout. I am leaning towards consistency here and just leave it named deletionPolicy for now. I would like to get yours MP input on this topic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect that I came up with the name of pendingReferences and StreamDeletionPolicy (not really sure about whether it was me or someone else). In any case, both terms describe concepts. Redis command documentation says:
Specifies how to handle consumer group references when trimming. If there are no consumer groups, these arguments have no effect. Available since Redis 8.2.
When trimming, removes entries … preserves existing references to these entries in all consumer groups' PEL (Pending Entries List).
Redis sometimes isn't great at making some concepts explicit, instead the underlying concept leaks through documentation. I think StreamDeletionPolicy is the shortest possible name to express a deletion policy for stream entry references from the pending element list. Agreed that the combination is not super-self explanatory, however it is something that when I encounter, I would want to read up more what this is. PendingElementListDeletionPolicy could be an alternative, yet its wordiness is much more annoying than the state we are currently at.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like I introduced some inconsistency with the rename, so I want to make sure I understand: are we discussing the naming of the class (StreamDeletionPolicy), the field (currently pendingReferences), or both?
Personally, I would stick with streamDeletionPolicy for both. Based on the Redis documentation, all three options (KEEPREF | DELREF | ACKED) represent different policies for how entries are removed from the stream. KEEPREF and DELREF delete entries strictly according to the trimming strategy (differing only in how PEL references are handled), while ACKED deletes only entries that were read and acknowledged by all consumer groups. In that sense, streamDeletionPolicy feels like the most concise name that still reflects the underlying concept.
As you noted, consistency across the API is important, so aligning on a single name and using it consistently seems like the best approach.
Signed-off-by: Chris Bono <chris.bono@broadcom.com>
See #3232 Signed-off-by: Chris Bono <chris.bono@broadcom.com>
…options See #3232 Signed-off-by: Chris Bono <chris.bono@broadcom.com>
See #3232 Signed-off-by: viktoriya.kutsarova <viktoriya.kutsarova@redis.com>
This commit makes the following "polish" changes: - remove manual not null check in `TrimOptions.<init>` as it's already `@NullMarked` - annnotate `RedisStreamCommands.XDelOptions` with `@NullMarked` - minor tweak to javadoc - remove usage of `var` in main code - use since `4.1` instead of `4.0` See #3232 Signed-off-by: Chris Bono <chris.bono@broadcom.com>
mp911de
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've left a few comments. There are several public API elements (methods, classes), that are missing Javadoc along with a mix of im proper or missing @since tags. I strongly urge to refrain from Deprecated(forRemoval=true) as the current API isn't breaking anything nor imposes its usage any danger, we've just broadened feature support.
Test code is overly verbose in its current form as each test scenratio is unfolded in a separate method rather than utilizing parametrized tests. In some areas we follow a test approach that doesn't consider refactoring of the underlying code inside components that we're testing. These require cleanup along with proper formatting according to our code style.
| assertThat(params).extracting("expiration", "expirationValue").containsExactly(expirationType, expirationValue); | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Formatting
| RecordId recordId = RecordId.of("1234567890-0"); | ||
| XAddOptions options = XAddOptions.none(); | ||
|
|
||
| XAddParams params = StreamConverters.toXAddParams(recordId, options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A testing approach of testing that a component is not doing something quickly leads to a lot of complexity as the subsequent lines unfold into several assertions. Instead, I suggest testing for the expectation that the component is doing something we expect, namely, not adding any command arguments.
XAddParams.addParams(CommandArguments) would be a neat way to utilize public API for testing which command arguments are added.
| } | ||
|
|
||
| @Nested // GH-3232 | ||
| class ToStreamDeletionPolicyShould { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of having each invariant represented by a test method, can we turn this into parametrized tests if you want to cover each code path in tests? The current arrangement is pretty verbose requiring a lot of mental energy to parse those tests. Using a parametrized test condenses the setup into an assertion and a set of input/expected arguments.
| } | ||
|
|
||
| @Test // GH-3232 | ||
| void xaddShouldHonorMinId() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Testing individual arguments in the xadd command series deviates from the underlying code.
Clearly, previously, the conversion has happened in the xadd method itself. With this pull request, all command conversion has been refactored to a converter, so it would be sufficient to keep a single xadd test with options and remove all other test variants to align with the code under test.
| RecordId messageId = streamOps.add(key, Collections.singletonMap(hashKey, value)); | ||
|
|
||
| streamOps.createGroup(key, ReadOffset.from("0-0"), "my-group"); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Formatting
| private final TrimStrategy trimStrategy; | ||
| private final TrimOperator trimOperator; | ||
| private final @Nullable Long limit; | ||
| private final @Nullable StreamDeletionPolicy pendingReferences; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect that I came up with the name of pendingReferences and StreamDeletionPolicy (not really sure about whether it was me or someone else). In any case, both terms describe concepts. Redis command documentation says:
Specifies how to handle consumer group references when trimming. If there are no consumer groups, these arguments have no effect. Available since Redis 8.2.
When trimming, removes entries … preserves existing references to these entries in all consumer groups' PEL (Pending Entries List).
Redis sometimes isn't great at making some concepts explicit, instead the underlying concept leaks through documentation. I think StreamDeletionPolicy is the shortest possible name to express a deletion policy for stream entry references from the pending element list. Agreed that the combination is not super-self explanatory, however it is something that when I encounter, I would want to read up more what this is. PendingElementListDeletionPolicy could be an alternative, yet its wordiness is much more annoying than the state we are currently at.
| * Prefer {@code XAddOptions.trim(TrimOptions.maxLen(n).approximate())} or | ||
| * {@code XAddOptions.trim(TrimOptions.minId(id).exact())}. | ||
| */ | ||
| @Deprecated(since = "4.0", forRemoval = false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest avoiding forRemoval = true. It's a pretty harsh signal. Just the deprecation is a lighter form of signalling improper API usage, and that there is a better variant.
| public XAddOptions nomkstream(boolean nomkstream) { | ||
| return new XAddOptions(nomkstream, trimOptions); | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Formatting
| * The entry ID does not exist in the stream. | ||
| */ | ||
| NOT_FOUND(-1L), | ||
| /** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Formatting (missing blank line)
| * @since 4.1 | ||
| */ | ||
| enum StreamDeletionPolicy { | ||
| /** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Formatting (missing blank lines)
This change introduces the
Support XDELEX, XACKEX and extend XADD and XTRIM optionsfeature...See original pull request for more details.
Closes: #3232
Original Pull Request: #3247