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
Handle analytical mode in community_detection during parallel changes #400
Conversation
cpp/mg_utility/mg_graph.hpp
Outdated
if (memgraph_to_inner_id_.find(memgraph_id) == memgraph_to_inner_id_.end()) { | ||
if (IsTransactional()) { | ||
throw mg_exception::InvalidIDException(); | ||
} | ||
return std::nullopt; | ||
} | ||
return memgraph_to_inner_id_.at(memgraph_id); |
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.
You can keep a reference to iterator here, and instead of doing find
, and then at
, you can do find
, and return element if it is there
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.
Done
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 good job in general, take care about duplication please :)
|
||
// Otherwise: | ||
auto record = record_factory.NewRecord(); | ||
record.Insert(kFieldNode.data(), graph.GetNodeById(mgp::Id::FromUint(node_id))); |
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.
Cache result of calling graph.GetNodeById, no need to call it twice
|
||
// Otherwise: | ||
auto record = record_factory.NewRecord(); | ||
record.Insert(kFieldNode.data(), graph.GetNodeById(mgp::Id::FromUint(node_id))); |
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.
Same
// As IN_MEMORY_ANALYTICAL doesn’t offer ACID guarantees, check if the graph elements in the result exist | ||
try { | ||
// If so, throw an exception: | ||
const auto maybe_node = graph.GetNodeById(mgp::Id::FromUint(node_id)); |
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.
What exceptions can be thrown in GetNodeById
?
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.
NotFoundException
https://github.com/memgraph/memgraph/blob/master/include/mgp.hpp#L1959
cpp/mg_utility/mg_utils.hpp
Outdated
bool isTransactionalStorage = mgp::graph_is_transactional(memgraph_graph); | ||
graph->SetIsTransactional(isTransactionalStorage); |
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.
bool isTransactionalStorage = mgp::graph_is_transactional(memgraph_graph); | |
graph->SetIsTransactional(isTransactionalStorage); | |
graph->SetIsTransactional(mgp::graph_is_transactional(memgraph_graph)); |
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.
Done
@@ -1,4 +1,6 @@ | |||
#include <chrono> |
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.
Why these 2 things got included?
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.
Removed – I’d originally added them to help with replicating the issue.
auto *vertex = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast<int64_t>(node_id)}, memory); | ||
if (!vertex) { | ||
if (mgp::graph_is_transactional(graph)) { | ||
throw mg_exception::InvalidIDException(); | ||
} | ||
// In IN_MEMORY_ANALYTICAL mode, vertices/edges may be erased by parallel transactions. | ||
return; | ||
} | ||
|
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.
These code is duplicates over all modules... It would be good to respect to respect DRY principle here and abstract this code into a method.
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.
Done
cpp/mg_utility/mg_graph.hpp
Outdated
if (memgraph_to_inner_id_.find(memgraph_id) == memgraph_to_inner_id_.end()) { | ||
if (IsTransactional()) { | ||
throw mg_exception::InvalidIDException(); | ||
} | ||
return std::nullopt; | ||
} | ||
return memgraph_to_inner_id_.at(memgraph_id); |
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 (memgraph_to_inner_id_.find(memgraph_id) == memgraph_to_inner_id_.end()) { | |
if (IsTransactional()) { | |
throw mg_exception::InvalidIDException(); | |
} | |
return std::nullopt; | |
} | |
return memgraph_to_inner_id_.at(memgraph_id); | |
auto it = memgraph_to_inner_id_.find(memgraph_id); | |
if (it != memgraph_to_inner_id_.end()) { | |
return *it; | |
} | |
if (IsTransactional()) { | |
throw mg_exception::InvalidIDException(); | |
} | |
return 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.
Done
And you have build errors, please take care about that before requesting review again. For next time tip: it is better to request review after build errors are fixed since it gives reviewer more confidence that hey this is good and meaningful fix without negative impact on the rest of the system |
|
||
// Otherwise: | ||
auto record = record_factory.NewRecord(); | ||
record.Insert(kFieldNode, graph.GetNodeById(mgp::Id::FromUint(node_id))); |
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.
Instead of calling graph.GetNodeById
once again, can we use maybe_node here?
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.
Done
// As IN_MEMORY_ANALYTICAL doesn’t offer ACID guarantees, check if the graph elements in the result exist | ||
try { | ||
// If so, throw an exception: | ||
const auto maybe_node = graph.GetNodeById(mgp::Id::FromUint(node_id)); |
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.
Since the function returns not optional Node, IMO it's better to name the variable as node and reuse it later.
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.
Done
// As IN_MEMORY_ANALYTICAL doesn’t offer ACID guarantees, check if the graph elements in the result exist | ||
try { | ||
// If so, throw an exception: | ||
const auto maybe_node = graph.GetNodeById(mgp::Id::FromUint(node_id)); |
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 same comment as in katz_centrality_online_module.cpp
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.
Done
// As IN_MEMORY_ANALYTICAL doesn’t offer ACID guarantees, check if the graph elements in the result exist | ||
try { | ||
// If so, throw an exception: | ||
const auto maybe_node = graph.GetNodeById(mgp::Id::FromUint(node_id)); |
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.
NotFoundException
https://github.com/memgraph/memgraph/blob/master/include/mgp.hpp#L1959
My initial idea was to make body of |
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. I can't approve the PR since I'm author.
…mage into handle-analytical-mode
Kudos, SonarCloud Quality Gate passed! 0 Bugs No Coverage information |
@vpavicic As this PR is the MAGE side of memgraph/memgraph#1395, they are covered by the same docs PR (memgraph/documentation#361) and should both be linked in the same release note. |
Description
NB: PR taken over by @antepusic; connected with memgraph/memgraph#1395
Since there are no ACID guarantees in analytical storage mode, the graph may get modified by parallel transactions while the user’s query is running. Query procedures and functions that return graph elements (nodes and relationships) should be robust to the deletion of graph elements, and this PR aims to fix that.
This PR contains changes to query modules that ensure the intended behavior:
Merge commit message:
Pull request type
Related issues
Resolves memgraph/memgraph#1036 (together with memgraph/memgraph#1395)
######################################
Reviewer checklist (the reviewer checks this part)
Module/Algorithm
######################################