The problem/use-case that the feature addresses

When a user calls the normal Redis API scan, a cursor is returned. while the value of the cursor is opaque to the caller, its data that they will provide back to redis for future iterations of Scan. Modules cannot implement similiar functionality on top of RedisModule_Scan() as the Cursor struct is opaque to it. All a redis module can do is is create and destroy it. If a redis module would want to implement scan type funtionality (say with alternative filter modes), it can't using the module api.

Description of the feature

new module APIs

void RedisModule_SetScanCursor(RedisModuleScanCursor * cursor, int value)
int RedisModule_GetScanCursor(RedisModuleScanCursor * cursor)

and possibly a int RedisModule_IsScanCusorDone(RedisModuleScanCursor *cursor)

Alternatives you've considered

simply calling RM_Call("SCAN") directly, as can parse out the cursor from the Reply object and pass it back into a new RM_Call().

Comment From: oranagra

Note that the reason we used an opaque struct and didn't expose the integer cursor directly is so that we are future compatible with the day the redis dictionary will no longer be dict.c (hash table) based. e.g. a dict based on radix tree can still support iteration without server side cursor, but the client side cursor is a string (last scanned key name) rather than an integer.

we could expose a mechanism to serialize the cursor into a byte array and deserialize it, in case you want to backup and restore a cursor or pass it to the client side, but if your intention is to re-implement or extend the SCAN command (which provides an integer cursor), i suppose the only way is to add the APIs you suggested.

maybe doing so would still in some way serve the original purpose, since the only modules that will use it, are ones that absolutely have to (need an integer cursor), and others which do the full iteration inside the module, will keep using the opaque class.

@yossigo @guybe7 @MeirShpilraien WDYT?

Comment From: sjpotter

for some background, the issue we have is in terms of providing an equivalent of a cluster getkeysinslot without redis cluster being enabled.

There were 2 similar ideas being explored.

1) propose a patch to extend scan itself where it could filter by a set of slot values (say "1,4-7,9,13-18") and it would ignore (possibly not returning any keys but an updated cursor) any key whose slot value isn't in that set. The problem with this approach, is that, without changing scan's output format, this would push the requirement to the user to recompute the slot for each key outputted (not crazy hard, but duplicate work on the client to do).

2) basically do the same in the module, but since the module is providing a new command, their is no output to be backwards compatible with, so can mimic scan, but instead of returning simply "key_name" for each array element, can return [key_name, slot_number] for each array element.

Comment From: oranagra

so in the second case, if it's a new command that doesn't have to be compatible with SCAN, it can also return a cursor that's not an integer?

Comment From: sjpotter

correct. the point would be, I don't think we would want to leak "cursor" objects (i.e. equivalent might be forcing client to delete cursor when done, but bad api) so want something that can be recreated each go through.

Comment From: MeirShpilraien

The API to the client can declare that the client gets a blob that he need to send back in order to continue, in the current implementation this blob will be the cursor. If, one day, we will move to trie, the blob will be the key name from which you want to continue. @sjpotter @oranagra WDYT?

Comment From: oranagra

yes, i think that's what i suggested too: serialize the cursor into a byte array