-
Notifications
You must be signed in to change notification settings - Fork 0
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
feat: add RedisHashKeyValueDB
#16
Conversation
ce519e9
to
f190c5a
Compare
Looks like I think it |
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.
LGTM with minor comments.
Great job with tests! 🙏
src/redisClient.ts
Outdated
return this.redis().hscanStream(key, opt) | ||
} | ||
|
||
async hScanCount(key: string, opt: ScanStreamOptions): Promise<number> { |
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.
should it be in lowercase? (consistent)
async hScanCount(key: string, opt: ScanStreamOptions): Promise<number> { | |
async hscanCount(key: string, opt: ScanStreamOptions): Promise<number> { |
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.
My impression was that you tried to follow the same naming pattern whenever we are just providing a wrapper:
for example async mget()
wraps this.redis().mget()
(instead of async mGet()
).
And you followed camelCase whenever this lib provides extra funtionality, e.g.: mgetBuffer
or scanStreamFlat
.
So my logic was:
hscanStream()
wrapsthis.redis().hscanStream()
call, hence identically namedhScanCount()
provides custom functionality (i.e. there is noredis().hscanCount
call), hence camelCase
TBH I don't know and I don't feel strongly about it, so I trust your judgement in using lowercase
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.
No strong opinion either, I just thought it's a typo. You can pick how you prefer.
My gut feeling is with lowercase hscan
though
src/redisHashKeyValueDB.ts
Outdated
): Promise<void> { | ||
if (!entries.length) return | ||
|
||
const map: StringMap<any> = _mapObject(Object.fromEntries(entries), (k, v) => [ |
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.
p3: I'd use native map here (instead of _mapObject), like:
const map = Object.fromEntries(entries.map(...))
why?
Since you're already using native Object.fromEntries.
src/redisHashKeyValueDB.ts
Outdated
match: `${table}:*`, | ||
}) | ||
.flatMap( | ||
async keyValueList => { |
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.
Q: why is it async (and has concurrency), while I see no await inside?
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.
Copy-pasted from redisKeyValueDB
where it is correctly async.
As I re-wrote the function, I didn't notice that I removed the awaited calls in it.
src/redisHashKeyValueDB.ts
Outdated
match: `${table}:*`, | ||
}) | ||
.flatMap( | ||
async keyValueList => { |
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.
Q why async?
Also confirmed that the flakiness is due to parallel running the test suits on the same REDIS with the same table name. |
I never ran manual tests in parallel, so, never encountered this. "Manual tests" are not very well defined, I must admit. Maybe we can define them as "only to be run manually one by one, and never in bulk". |
In this PR, I implemented the RedisHashKeyValueDB which is a special class providing the usual CommonKeyValueDB functions on a hash field in Redis.
The underlying use-case is to
table:
prefix)Compared to using the more idiomatic
table:
prefix approach, the hash field approach has the benefit of fetching the entire hash with an O(n) operation n being the size of the hash - meanwhile with atable:
prefix, the scan operation would be O(m) where m is the number of keys in redis. (At least that is my understanding.)This PR depends on NaturalCycles/db-lib#18