-
Notifications
You must be signed in to change notification settings - Fork 990
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: Use const ConnectionContext in VerifyCommand #1633
Conversation
src/facade/facade_types.h
Outdated
struct ErrorReply { | ||
explicit ErrorReply(std::string msg, std::string_view kind = {}) | ||
: message{move(msg)}, kind{kind} { | ||
} | ||
explicit ErrorReply(std::string_view msg, std::string_view kind = {}) : message{msg}, kind{kind} { | ||
} | ||
explicit ErrorReply(const char* msg, std::string_view kind = {}) | ||
: message{std::string_view{msg}}, kind{kind} { | ||
} | ||
explicit ErrorReply(OpStatus status) : message{}, kind{}, status{status} { | ||
} | ||
|
||
std::variant<std::string, std::string_view> message; | ||
std::string_view kind; | ||
std::optional<OpStatus> status{std::nullopt}; | ||
}; | ||
|
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 don't feel strong about having such a heavy type inside facade_types (which is included almost everywhere, but not sure where else to put 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.
I know its not used everywhere where it fits in, I'll have more iterations when I check other parts
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.
The const char msg* overload is to avoid ambiguity (const char* converts to both string and string_view implicitly)
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.
Maybe in order to reduce ambiguity, the std::string
c'tor could accept a std::string&&
instead? (I imagine this will allow removing the const char*
one, which is confusing).
If for some reason that doesn't work, I'd write that in a comment.
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.
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.
Please see some comments, mostly nits
src/facade/facade_types.h
Outdated
struct ErrorReply { | ||
explicit ErrorReply(std::string msg, std::string_view kind = {}) | ||
: message{move(msg)}, kind{kind} { | ||
} | ||
explicit ErrorReply(std::string_view msg, std::string_view kind = {}) : message{msg}, kind{kind} { | ||
} | ||
explicit ErrorReply(const char* msg, std::string_view kind = {}) | ||
: message{std::string_view{msg}}, kind{kind} { | ||
} | ||
explicit ErrorReply(OpStatus status) : message{}, kind{}, status{status} { | ||
} | ||
|
||
std::variant<std::string, std::string_view> message; | ||
std::string_view kind; | ||
std::optional<OpStatus> status{std::nullopt}; | ||
}; | ||
|
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.
Maybe in order to reduce ambiguity, the std::string
c'tor could accept a std::string&&
instead? (I imagine this will allow removing the const char*
one, which is confusing).
If for some reason that doesn't work, I'd write that in a comment.
explicit ErrorReply(OpStatus status) : message{}, kind{}, status{status} { | ||
} | ||
|
||
std::variant<std::string, std::string_view> message; |
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.
Maybe we can have message
of type string_view
, and some other member (like private message_memory_
) which message
may or may not point into?
It should make using this struct easier
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 remember you don't like using variants for storage at all, we already had this case once.
But I like to avoid self referential structs - it requires defining move/copy constructors and operators
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 am not worried about performance implications of using std::string in case we return errors.
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.
This is why I use string_view whenever its possible, in other cases you construct a string with StrCat and others anyways
I'll check once again for performance degradation, but it shouldn't be the case
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.
Btw I once thought of supporting an absl::Span<absl::Alphanumeric>
interface to write directly into the conn buffer without the intermediary string, but its just a random comment in this context 🙂
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.
So yes, I don't see any place where the number of intermediaries increased
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 meant - I am NOT worried - i.e. I think having a string here is perfectly fine since it's not on a hot path.
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 don't have any problem with storing variant
as a member, or using it as storage. I actually think variant
s are great.
I dislike the API that it brings in, though. I definitely understand your comment re/ having to implement an explicit move / copy operations.
I guess we could:
- Keep as is
- Provide a wrapper get-method that returns
string_view
which points to the right string - do my trick, but have the
string
inside aunique_ptr
- always use a
string
(Roman's suggestion)
Your call :)
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 see you decided to keep as is. I would still say it's not a great API to force a call to std::visit
with a templated lambda instead of having a
string_view GetMessage() const { visit... }
To wrap that, but again, your call :)
For the case where you want to move if possible, you could have another version (GetMessageDestructive()
?)
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.
😝
As soon as it'll be used more than in once place I'll add those
@@ -220,6 +220,14 @@ void RedisReplyBuilder::SendError(string_view str, string_view err_type) { | |||
} | |||
} | |||
|
|||
void RedisReplyBuilder::SendError(ErrorReply error) { |
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 don't see that you move anything from error
, so can you accept it by const&
?
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.
Not sure. Forgot to comment about it. I want the CapturingReplyBuilder to move out of the string so it can re-use its memory. The downside is that it requires passing the error by value everyewhere to comply with the interface
src/server/main_service.cc
Outdated
lock_guard lk(mu_); | ||
if (unknown_cmds_.size() < 1024) | ||
unknown_cmds_[cmd_str]++; | ||
return false; | ||
|
||
return facade::ErrorReply{StrCat("unknown command `", cmd_str, "`"), "unknown_cmd"}; |
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.
can you add using facade::ErrorReply
at the beginning?
too much horizontal space is wasted on these namespaces.
Fixed comments except those that are debatable 🙂 |
ff34107
to
fe43785
Compare
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 at high level.
@chakaz will continue :)
src/server/main_service.cc
Outdated
bool is_trans_cmd = CO::IsTransKind(cid->name()); | ||
bool under_script = bool(dfly_cntx->conn_state.script_info); | ||
bool under_script = bool(dfly_cntx.conn_state.script_info); |
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.
while here, maybe instead of casting to bool do:
bool under_script = dfly_cntx.conn_state.script_info != nullptr;
Signed-off-by: Vladislav Oleshko <[email protected]>
Signed-off-by: Vladislav Oleshko <[email protected]>
Signed-off-by: Vladislav Oleshko <[email protected]>
Signed-off-by: Vladislav Oleshko <[email protected]>
fe43785
to
62bfefc
Compare
You already did it in your previous PR, rebased |
Signed-off-by: Vladislav Oleshko <[email protected]>
62bfefc
to
f79e619
Compare
explicit ErrorReply(OpStatus status) : message{}, kind{}, status{status} { | ||
} | ||
|
||
std::variant<std::string, std::string_view> message; |
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 see you decided to keep as is. I would still say it's not a great API to force a call to std::visit
with a templated lambda instead of having a
string_view GetMessage() const { visit... }
To wrap that, but again, your call :)
For the case where you want to move if possible, you could have another version (GetMessageDestructive()
?)
Its an anti-pattern to use a mutable ConnectionContext pointer for both connection state queries and error replies. As a result we have a lot of excessive mutability and we pass it everywhere around. This might have not been an issue so far, but it becomes hard to manage with squashed command execution.
Its needed for squashed pipeline execution. Pipeline commands can make state changes (context & global), so command verification needs to happen immediately before execution. With squashed execution, this verification will take place from multiple threads -> possible trouble if not carefully done