-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
Xinfo command #2069
Xinfo command #2069
Conversation
Builder classes used for decoding Returned type changed to Map<String,Object>
@sazzad16 @marcosnils @gkorland @xetorthio could you give me some input? |
My initial thought is that |
But this will not solve the problem of returning very generic object.
What I had in mind is to have 3 functions returning different types which expose more clear getters
Other option would be to return something like
exposing |
Sorry my mistake... should be draft |
No problem, I'm working on the new implementation, I hope I can have some commits ready soon |
@MichalCho sorry to nudge, but are still working on this PR? |
@gkorland no problem. Sorry I got quite busy at the office. I will try to use holiday break now to craft some code. Will you be willing to do some code review? |
@MichalCho no pressure, I just wanted to check if it's still relevant for you. |
@MichalCho sorry,,,i want know xinfo() method Progress?? :) :) :D |
Hi @startjava |
@MichalCho |
A lot of refactoring to be done. This commit is just for showing the idea
Hi, |
@MichalCho Even though I've put some review comments,
Perhaps one method (per class) returning a
|
@sazzad16 thanks a lot for the review. Regarding formatting comments - I was aware of most of them, I just wanted to show something before leaving for holidays :)
I was thinking about it. Then I had an idea to provide getters for all map members. Otherwise user will have to try to get on Object from the map and he will have to know what kind of object it is. something like (if xinfo returns just a map): Another issue that I had in mind is - when we decode the answer we can not be fully flexible as we need to know how to decode the answer (to know that "length" is a integer, "last-generated-id" is a string and "first-entry" is a stream entry object). |
@MichalCho hi~ what time xinfo method final over? thank you job ! |
xinfo commands return now just a Map<String,Object> In case when (in the future) redis includes additional fields in a reply we will try to decode them using known decoders
hi @sazzad16! I've implemented your comments and changed the returned type just to be During the weekend I will try to add more test cases and maybe make the code prettier. PS @startjava it's ongoing, you can check the latest commit |
Some code clean up done together with more tests
I've added more tests and worked on the review comments. I think that the PR is ready for a final review from you guys. I have one thing in mind - how should we act if redis decide to add more fields in a reply and we are not able to decode them? Ignore them and decode what we can? Throw an exception? Log something? Please share your thoughts. |
src/test/java/redis/clients/jedis/tests/commands/StreamsCommandsTest.java
Outdated
Show resolved
Hide resolved
Some minor refactoring done together with restoring getters for elements known to be returned by redis now. In case new elements are added in the future the map can be used to obtain them.
I've just committed changes according to review comments. I've restored getters for map elements, that are known to be present in a reply as per today. But please check my reply to your comment - should we have those getters or just keep constants (not variables) that can make getting objects from the map easier. Still the question is - how shall we try to decode those unknown elements. As for now we try use a set of decoding functions that we know are needed to decode specific type of answer. Should all decoding function should be added? |
Refactor xinfo to simplify usage. Javadoc will be added in another commit
hi @gkorland, I've implemented your suggestion - splitting xinfo into 3 different methods. I've also added some simple javadocs to make it easier for a user to understand how to use xinfo with jedis. I had some doubts regarding how I create info objects, for example:
This can fail if length is not present in the map( for example future version of redis will remove this filed). But according to redis documentation:
so I guess it's save to assume that fields that exist now will always be there. Nothing is mentioned about removing fields. |
byte[] xinfoStream (byte[] key); | ||
|
||
List<byte[]> xinfoGroup (byte[] key); | ||
|
||
List<byte[]> xinfoConsumers (byte[] key, byte[] 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.
Why byte[]
? What about the Objects?
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 think we need some aligment here. I can see that some BinaryJedisCommands
returns Objects (or Collections of Objects) - in some cases using builder factory directly like
public List<GeoRadiusResponse> georadiusByMember(final byte[] key, final byte[] member, final double radius,
final GeoUnit unit, final GeoRadiusParam param) {
checkIsInMultiOrPipeline();
client.georadiusByMember(key, member, radius, unit, param);
return BuilderFactory.GEORADIUS_WITH_PARAMS_RESULT.build(client.getObjectMultiBulkReply());
}
some other returns byte arrays or collection of byte arrays etc.
Maybe I missunderstood the purpose of binary client - I thought it was supposed to use just binary data, without trying to decode them. Could you please help me to understand that?
I have seen in #2084 that you mention that returning List<byte[]> instead of List is a bug
If we should return objects then I would propose following:
Object xinfoStream (byte[] key);
List<Object> xinfoGroup (byte[] key);
List<Object> xinfoConsumers (byte[] key, byte[] 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.
Following would be good enough:
StreamInfo xinfoStream (byte[] key);
List<StreamGroupInfo> xinfoGroup (byte[] key);
List<StreamConsumersInfo> xinfoConsumers (byte[] key, byte[] 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.
I've refactored it that way and added a test for binary usage.
public static final String STREAM = "STREAM"; | ||
public static final String GROUPS = "GROUPS"; | ||
public static final String CONSUMERS = "CONSUMERS"; |
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.
Prefix these, perhaps with XINFO_
. Also put these along with SENTINEL_...
, CLUSTER_...
, PUBSUB_...
variables.
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.
done
Also a test for binary xinfo commands has been added
List<StreamConsumersInfo> consumersInfo = jedis.xinfoConsumers(STREAM_NAME, G1); | ||
|
||
//Stream info test | ||
assertEquals(2L,streamInfo.getStreamInfo().get(LENGTH)); |
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.
Missing LAST_GENERATED_ID
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.
Done in a way that we check if it's not null - it is difficult to know what last-generated should be
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.
shouldn't it be id2?
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.
you are right. I've missed that we have that info already.
I have also changed returned object to be StreamEntryID
src/test/java/redis/clients/jedis/tests/commands/StreamsCommandsTest.java
Show resolved
Hide resolved
firstEntry = (StreamEntry) map.get(FIRST_ENTRY); | ||
lastEntry = (StreamEntry) map.get(LAST_ENTRY); | ||
|
||
} else throw new IllegalArgumentException("InfoMap can not be null"); |
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.
If we are throwing runtime exception anyway when map is null isn't it better to just let it throw NullPointerException?
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.
Done. My initial thought was that it is not nice to see NullPointers
pending = (long) map.get(PENDING); | ||
lastDeliveredId = (String) map.get(LAST_DELIVERED); | ||
|
||
} else throw new IllegalArgumentException(); |
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.
If we are throwing runtime exception anyway when map is null isn't it better to just let it throw NullPointerException?
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.
Done. My initial thought was that it is not nice to see NullPointers
pending = (long) map.get(PENDING); | ||
|
||
|
||
} else throw new IllegalArgumentException(); |
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.
If we are throwing runtime exception anyway when map is null isn't it better to just let it throw NullPointerException?
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.
Done. My initial thought was that it is not nice to see NullPointers
Added test for last-generated-id Moved xinfo keywords to enum Removed throwing runtime exception from xinfo classes
Better to use existing class
Tests are failing https://travis-ci.org/xetorthio/jedis/jobs/648852944 |
I'm on it Update: |
@MichalCho sounds OK just sleep for 1ms |
LastDeliveredId type has been changed to be StreamEntryId instead of simple String. Also unstable test for Idle Consumer time has been fixed.
I think we are done here. @gkorland is there a list of features/ issues to be implemented/fixed? I would like to contribute more :) |
Merged into master. Excellent job @MichalCho |
@MichalCho thanks for the great help! |
Hi,
I've noticed that xinfo command is missing so I've started to implement it.
This is just to start a discussion about how this should be fixed.
Currently I've implemented a single xinfo command that returns a map of <String,Objects>.
This would work for any variant of xinfo (stream,groups, consumers) but it's a bit generic.
The other idea would be to create 3 xinfo commands, returning something like XInfoStream, XInfoConsumers etc. objects. That would give a better visibility of returned values.
I will be happy to work on it.