Skip to content
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

SCAN: New Feature SCAN cursor [TYPE type] modifier suggested in issue #6107 #6116

Merged
merged 4 commits into from
Jul 8, 2019

Conversation

AngusP
Copy link
Contributor

@AngusP AngusP commented May 22, 2019

Extends the SCAN (but not ZSCAN, HSCAN etc.) API to

SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]

This allows scanning the DB for keys of a single type, which may be useful for finding streams, garbage collection, migrations etc.

The feature was suggested by @gkorland in #6107.

The argument type is the string you get when asking Redis for the TYPE of a key, so works with modules as well as the native types. A quirk to be aware of here is that the GEO commands are backed by ZSETs not their own type, so they're not distinguishable from other ZSETs. Similarly, Hyperloglogs, bitmaps and bit fields are backed by strings so are also not distinguishable.

Additionally, for sparse types that are rare in the DB, this has the same behaviour as MATCH in that it may return many empty results before giving something, even for large COUNTs.

Also adds tests to check basic functionality of this optional TYPE keyword, and also tested with a module (redisgraph). Checked quickly with valgrind, no issues.

Copies name the type name canonicalisation code from typeCommand, perhaps this would be better factored out to prevent the two diverging and both needing to be edited to add new OBJ_* types, but this is a little fiddly/messy with C string, so I haven't addressed it.

The redis-doc repo will need to be updated with this new arg if accepted.

Many thanks as always 👍

…#6107.

Add tests to check basic functionality of this optional keyword, and also tested with
a module (redisgraph). Checked quickly with valgrind, no issues.

Copies name the type name canonicalisation code from `typeCommand`, perhaps this would
be better factored out to prevent the two diverging and both needing to be edited to
add new `OBJ_*` types, but this is a little fiddly with C strings.

The [redis-doc](https://github.com/antirez/redis-doc/blob/master/commands.json) repo
will need to be updated with this new arg if accepted.

A quirk to be aware of here is that the GEO commands are backed by zsets not their own
type, so they're not distinguishable from other zsets.

Additionally, for sparse types this has the same behaviour as `MATCH` in that it may
return many empty results before giving something, even for large `COUNT`s.
@itamarhaber
Copy link
Member

Looks good, although I'm not sure about the two "new" types introduced: 'none' and 'unknown'.

src/db.c Outdated Show resolved Hide resolved
@AngusP
Copy link
Contributor Author

AngusP commented May 22, 2019

@itamarhaber Yeah, there's a little difficulty in working out how to handle those errors here - These values are possible but not actually types so we maybe ought to do and return nothing...

"none" can be returned if the key is missed (lookupKeyReadWithFlags returned NULL) so a test case to trigger this would be useful. As far as I can see, "unknown" shouldn't be possible to trigger unless Redis is rather confused - after all, these two non-types can be returned from TYPE key too but I've never seen this happen in my experience...

…n SCAN and TYPE commands,

and to keep OBJ_* enum to string canonicalization in one place.
@AngusP
Copy link
Contributor Author

AngusP commented Jun 13, 2019

@antirez any opinion on whether this would be a useful feature to have?

@antirez
Copy link
Contributor

antirez commented Jul 5, 2019

Hello @AngusP, this feature looks good to me, thanks a lot for proposing. Please could you operate the following trivial changes?

  1. In code like char* typeNameCanonicalize(robj*), follow the rest of the Redis code by writing the asterisk near the function name (or variable name).
  2. Let's rename the function in a way that is more Redis-ish :-D, for instance getObjectTypeName() would be perfect.

Thanks!

@AngusP
Copy link
Contributor Author

AngusP commented Jul 5, 2019

@antirez will do, apologies - should’ve spotted the style!

@antirez
Copy link
Contributor

antirez commented Jul 7, 2019

@AngusP I apologize for asking about the changes actually, it's not the important part of the PR, but given that it's a trivial change, better to stay consistent :-) Thanks.

@AngusP
Copy link
Contributor Author

AngusP commented Jul 8, 2019

@antirez see new commit for your recommended changes

@antirez antirez merged commit 7224465 into redis:unstable Jul 8, 2019
@antirez
Copy link
Contributor

antirez commented Jul 8, 2019

Thanks @AngusP, merged! If you will follow up with redis-doc as well, it will be appreciated. Make sure to comment here as well once you submit the doc PR as the redis-doc repo is inspected with a different frequency. Thank you.

@antirez
Copy link
Contributor

antirez commented Jul 8, 2019

P.S. In the unit tests you wrote, I would change them to include a non-string object in the first iteration, because to test all-white all-black is generally not able to visit as many states as testing for mixed conditions.

@AngusP
Copy link
Contributor Author

AngusP commented Jul 8, 2019

@antirez redis-doc redis/redis-doc#1137

I'm not too sure what you mean "I would change them to include a non-string object in the first iteration", do you mean to test for a database populated with a mix of strings and not-strings? I'd agree that would be a more robust test, but there's no easy debug populate equivalent I'm aware of - is there a tcl test function for this kind of thing? Or, I can just add a loop to do so

@gkorland
Copy link
Contributor

gkorland commented Jul 8, 2019

@antirez can it be ported to 5.0.x too?

@antirez
Copy link
Contributor

antirez commented Jul 8, 2019

@AngusP Hey! I just mean: DEBUG POPULATE ... + ZADD foobar, so you have at least a key that is not a string. And later you check that the count is 1000 and 1 :-D Thanks for the doc.

@antirez
Copy link
Contributor

antirez commented Jul 8, 2019

@gkorland I think so.

@AngusP maybe for Redis 6 we should at least report HyperLogLog as a type if it matches the HLL format. Or, even better, we should move away from the string representation entirely. I'll think about this.

JackieXie168 pushed a commit to JackieXie168/redis that referenced this pull request Jul 10, 2019
SCAN: New Feature `SCAN cursor [TYPE type]` modifier suggested in issue redis#6107
michael-grunder added a commit to phpredis/phpredis that referenced this pull request Oct 10, 2019
NOTE:  [This
comment](redis/redis#6116 (comment))
indicates the feature may be backported to Redis 5, so we'll want to
change our unit test if that happens.
michael-grunder added a commit to phpredis/phpredis that referenced this pull request Feb 6, 2020
NOTE:  [This
comment](redis/redis#6116 (comment))
indicates the feature may be backported to Redis 5, so we'll want to
change our unit test if that happens.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants