-
Notifications
You must be signed in to change notification settings - Fork 871
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(streams): support XACK command #1923
Conversation
|
||
OpResult<uint32_t> result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); | ||
if (result || result.status() == OpStatus::KEY_NOTFOUND) { | ||
return (*cntx)->SendLong(*result); |
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.
Wouldn't *result
crash if result.status() == OpStatus::KEY_NOTFOUND
?
Perhaps you could add an if
before, something along the lines of:
if (result.status() == OpStatus::KEY_NOTFOUND) {
result = 0UL;
}
if (result) {
// send long...
}
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.
sorry.. I just verified again. when key is not found, the *result is actually 0...
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.
Yes +1, same for when the cgroup
does not exist. Good catch @theyueli
Oh, and I just noticed there are no tests (which could have caught the NOTFOUND issue), could you add some please? 🙏 |
Yes I was working on that, now they are complete. |
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.
Good work 👨🍳 @theyueli`
Very small nit to replace NULL
with nullptr
and I will approve.
string_view key = ArgS(args, 0); | ||
string_view group = ArgS(args, 1); | ||
args.remove_prefix(2); | ||
absl::InlinedVector<streamID, 8> ids(args.size()); |
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.
Nice!
src/server/stream_family.cc
Outdated
@@ -1444,7 +1476,7 @@ void DestroyGroup(string_view key, string_view gname, ConnectionContext* cntx) { | |||
return OpDestroyGroup(t->GetOpArgs(shard), key, gname); | |||
}; | |||
|
|||
OpStatus result = cntx->transaction->ScheduleSingleHop(std::move(cb)); | |||
OpStatus result = cntx->transaction->ScheduleSingleHop(cb); |
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.
💯 for making the changes across the file
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.
question, what's the reason for removing move
?
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 that the claim is that it doesn't do anything (because all captures are by ref, and so "moving" pointers is the same as copying them).
I would, however, counter-claim that it's a better practice to use move
even in such cases, because there's no harm, and it's future proof and does not require carefully reviewing the capture list..
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 have not seen the original request but +1 to what @chakaz said. If tomorrow cb
will capture a 1MB string, it will be copied, and performance bugs are hard to catch.
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.
ok, I'm good with either way. I will reverse these changes.
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.
Small rant vol2, it captures everything by reference, even if we added a string, we would need to explicitly copy it by value making it nearly impossible for this to happen unless you really want to copy this 1mb string...
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.
Re/ 1: I'd rather have longer compilation times than runtime. When a stressed compiler will be an issue, we can tackle that (and I doubt that this will be the cause of pain for the compiler). I'd even bet that <utility>
is included in every (or 99%) of TUs we use (either directly or indirectly).
Re/ 2: I'd argue that:
- It's way more common to capture more local variables (we all add them, all the time) than to add members to structs, and so it makes sense to have a different rule of thumb
- If you add a 1mb string to your class, it might make sense to also add a move-constructor (if one is not generated for you)
- It's much less noisier to move callbacks than to move all structs that are ever assigned :)
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.
Small rant vol2, it captures everything by reference, even if we added a string, we would need to explicitly copy it by value making it nearly impossible for this to happen unless you really want to copy this 1mb string...
Simple grep
ping found 2 cases in which we capture by-ref by-default, but also some vars by value:
https://github.com/romange/helio/blob/937652d5803596893aa774206b36d7b91dccf883/util/fibers/fiberqueue_threadpool.h#L108
https://github.com/romange/helio/blob/937652d5803596893aa774206b36d7b91dccf883/util/fibers/fiberqueue_threadpool.h#L122
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 you add a 1mb string to your class, it might make sense to also add a move-constructor (if one is not generated for you)
yes but to trigger it you need to call std::move
everywhere -- ouch!
Simple grepping found 2 cases in which we capture by-ref by-default, but also some vars by value:
Both of them capture a Done
object which internally holds an intrusive_ptr
. So no deep copying whatsoever...
And if you tell me that if somebody adds a 1mb string to the class Done
I would say it would have the same effect as:
somewhere in our codebase:
void some_func_call(Done done) {
}
void foo() {
Done copy_1mb;
some_func_call(copy_1mb);
}
Once you add that 1mb
string, it will have the same effect for any function that accepts a Done
object
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.
Sorry Shahar, I really don't see any value in using std::move()
like that. It's noise, even for (1) above, if you add a non trivial type either move it or capture it by reference (the same you would do for any object IMO). Again, since you and Roman agree, I think we got a consensus. I don't want to push staff neither do I think this move is the end of the world or high in importance.
auto [stream_inst, cg] = *res; | ||
|
||
if (cg == nullptr || stream_inst == nullptr) { | ||
return 0; |
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.
Originally, I wrote this long message here cause I thought you were transforming an error to a valid result. Upon testing this on redis (and going over the ACK docs) it seems to be correct. Therefore, both if the cg and the key does not exist we should return 0.
|
||
OpResult<uint32_t> result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); | ||
if (result || result.status() == OpStatus::KEY_NOTFOUND) { | ||
return (*cntx)->SendLong(*result); |
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.
Yes +1, same for when the cgroup
does not exist. Good catch @theyueli
Thanks! fixed. |
fixes #1869