-
Notifications
You must be signed in to change notification settings - Fork 5
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
support new data structure #4
base: main
Are you sure you want to change the base?
Conversation
L-jasmine
commented
Dec 23, 2022
- Optimize the code structure for new data structure.
- Implement a "causal consistency" HashMap
- Implement a "causal consistency" counter
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.
Thanks a lot for this PR! Since it is quite large I started reviewing by commit, currently up to commit d4834dc.
- Commits 9669689 to 0e65f7f look good to me.
- I'm not sure about commit a8e2945 ("feat: add
KeyOperation::SetAdd
").- Why do we need a new
KeyOperation
for this? Couldn't we just create a newput_causal_set
method insrc/nodes/client/mod.rs
that handles the vector clock on the client-side and then callself.put(key, LatticeValue::SingleCausal(...))
? - The
SingleKeyCausalLattice
already implements a merge logic:anna-rs/api/src/lattice/causal/single_key_causal.rs
Lines 42 to 54 in e60629b
let prev = self.element.vector_clock.clone(); self.element.vector_clock.merge(&other.vector_clock); if self.element.vector_clock == other.vector_clock { // the value in `other` is strictly newer, i.e. in causally follows `self` self.element.value = other.value.clone(); } else if self.element.vector_clock == prev { // our value is strictly newer, i.e. `self` causally follows `other -> nothing to do } else { // the value was written concurrently -> merge the values using their `Lattice` impl self.element.value.merge(&other.value); } }
I don't think that it's a good idea to implement a different merge logic in the KVS request handler depending on the request type. In my opinion, there should be one canoncial merge implementation for each type as part of theLattice
trait implementation without any special casing. - With this change it would be possible to write the same key using different operations,
SetAdd
andPut
, with different results. This could easily lead to confusion and bugs in practice.
- Why do we need a new
- I have the same concerns about 5674795. Why not set the vector clock at the client side instead and use a normal
PUT
operation? - 75f4361, 3763a48, and d4834dc look good to me.
Hi Phillip, Happy new year! Thank you for the quick review. Let me take a step back and give a little more context on the PR. Our goalOur end goal here is to provide a Redis compatible API for storing / managing data structures over anna-rs. It alleviates a key problem Redis faces — it is single threaded and cannot scale well for the cloud. Overall approachWe initially thought that we can use client side transactions to compose multiple PUT / SET operations for each data structure type. But we concluded that a client-only solution is not possible. Specifically,
Hence, the approach in this PR is to modify the anna-rs server injunction with the client to support key data structures such as Set and Map. We believe that more complex data structures can be supported more easily later once we have Set and Map. Why I modified
|
Thanks a lot for clarifying and happy new year to you too! I understand your points about the network overhead of modify operations and the need for server-side validation. However, I'm still not sure if it's a good idea to extend the |
Thanks! Let me try and create a ClientKeyOperation as you suggested. Will update soon. |
I just saw that you pushed some new commits. Is this ready for another round of review? |
Hi, We are using a GitHub bot to automatically generate code review summaries from ChatGPT/4 for PRs in this repo. Please excuse the construction as we are optimizing the prompts. Here I am going to the magic words to summon the bot: flows summarize |
This comment was marked as off-topic.
This comment was marked as off-topic.
@juntao Thanks for the summary! @L-jasmine Is this PR ready for another round of review from your side? |
Oh, I'm sorry for replying so late. Yes, I'm ready for another round of review now. I noticed that there are some conflicts, but I will resolve them later. Please proceed with the review for now. Thank you. |
We upgraded the bot to GPT4. So, I will summon it to summarize again. :) Feel free to delete the summaries if they clutter up the timeline. Thanks! flows summarize |
Hello, I am a serverless review bot on flows.network. Here are my reviews of code commits in this PR. Overall, this set of patches introduces various changes to the source code, including adding new functions, refactoring existing code, modifying data structures, and changing serialization and deserialization libraries. Potential issues and errors:
Important findings:
Due to these changes, it is essential to thoroughly test the updated code, ensure proper error handling, and verify compatibility with older clients and external dependencies. Moreover, the refactoring should be monitored for any impacts on performance and maintainability. DetailsCommit 1Summary of key changes:
Potential problems:
Commit 2Summary of key changes:
Potential problems:
Commit 3This patch introduces the following key changes:
fn reveal_mut(&mut self) -> &mut Self::Element; This method returns a mutable reference to the current value stored in the lattice.
Potential problems:
Commit 4Summary:
Potential issues:
Important findings:
Commit 5Summary of key changes:
Potential problems:
It's essential to verify all code paths referencing Commit 6This patch renames
Potential problems:
Overall, assuming that all references to the renamed struct have been updated accordingly, this patch should not introduce any significant problems. Commit 7Summary of key changes:
Potential problems:
Commit 8Summary of key changes:
Potential problems:
Commit 9Summary of Key Changes:
Potential Problems:
Commit 10Summary of key changes:
Potential problems:
Commit 11This patch adds a new client command called
Potential issues:
Commit 12This patch updates a test file named Summary of Changes:
Potential problems:
Commit 13Summary of key changes:
Potential problems and suggestions:
Commit 14The patch mainly introduces a new function Key changes:
Potential problems:
Commit 15Summary of key changes:
Potential problems:
Commit 16Summary of Changes:
Potential problems:
Commit 17The key changes in this patch include:
Some potential problems in this patch are:
Commit 18Summary of Key Changes:
Possible Problems:
Note: At first glance, the changes seem reasonable given the goal of moving the Commit 19This patch makes the following key changes:
Potential problems and concerns:
Commit 20Summary of Changes:
Potentials problems:
Commit 21This patch implements a causal counter with the following key changes:
One potential issue is that decrementing the counter using a negative increment value will be allowed by this implementation. Commit 22This patch includes changes affecting 27 files. The main change is replacing Other changes include:
Potential problems could arise from ensuring that the changes in serialization library behavior (from Additionally, the removal of the Commit 23The patch contains changes addressing the Key Changes:
Potential Problems:
Commit 24This patch renames
Potential issues:
|
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.
Thanks a lot for the updates!
@@ -25,7 +25,8 @@ log = "0.4.14" | |||
fern = "0.6.0" | |||
futures-timer = "3.0.2" | |||
once_cell = "1.8.0" | |||
serde_json = "1.0.64" | |||
# serde_json = "1.0.64" |
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.
We can remove this dependency if it's no longer needed.
let work_start = Instant::now(); | ||
|
||
let mut addr_keyset_map: HashMap<String, HashSet<Key>> = HashMap::new(); | ||
for key in self.local_changeset.drain() { | ||
for key in self.local_changeset.drain().collect::<Vec<Key>>() { |
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.
To avoid the extra allocation, we could replace the self.local_changeset
with an empty set:
for key in self.local_changeset.drain().collect::<Vec<Key>>() { | |
for key in std::mem::take(&mut self.local_changeset) { |
@@ -0,0 +1,149 @@ | |||
//! Defines the zenoh topic paths that should be used for messages. |
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 seems quite a bit of duplication across this new file and src/topics.rs
. Given that the anna
crate depends on anna-api
, it should be possible to reuse the API topics in the anna
topics module.
const HELP: &str = "\n\nValid commands are are GET, GET_SET, PUT, PUT_SET, \ | ||
PUT_CAUSAL, and GET_CAUSAL."; | ||
const HELP: &str = | ||
"\n\nValid commands are are GET, PUT, GET_SET, ADD_SET, GET_HASHMAP and ADD_HASHMAP."; |
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.
"\n\nValid commands are are GET, PUT, GET_SET, ADD_SET, GET_HASHMAP and ADD_HASHMAP."; | |
"\n\nValid commands are are GET, PUT, GET_SET, ADD_SET, GET_HASHMAP, ADD_HASHMAP, and INC."; |
if let Some((field, value)) = s.split_once(":") { | ||
Some((field.to_string(), value.to_string().into_bytes())) | ||
} else { | ||
None |
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 silently ignores values that use incorrect syntax. Perhaps it would be better to error instead?
.await | ||
.context("put failed")?; | ||
|
||
.context("failed to send put_lww")?; |
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.
Isn't this missing a wait_for_matching_response
call?
use super::Lattice; | ||
use std::collections::HashMap; | ||
|
||
/// [`Lattice`] implementation that merges elements by taking their maximum. |
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 still the docstring of MaxLattice
.
) -> Result<Option<ClientResponseValue>, AnnaError> { | ||
use std::collections::hash_map::Entry; | ||
|
||
match operation { |
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.
Would it be possible to always go through inner_key_operation_handler
? My idea in #4 (comment) was that we could translate the ClientKeyOperation
to an InnerKeyOperation
that uses the normal merge logic. This way, we could be sure that we don't violate any invariants of the lattice types (e.g. that a value is monotonically increasing).
For example, instead of doing an in-place modification of SingleCausal
lattice values, we could construct a new SingleKeyCausalLattice
and then invoke inner_key_operation_handler
. This way, we also reduce code duplication.
What do you think?
match self.kvs.entry(key.clone()) { | ||
Entry::Vacant(entry) => { | ||
entry.insert(LatticeValue::SingleCausal( | ||
SingleKeyCausalLattice::create_with_default_clock(value), |
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 creates an empty vector clock, but if the key already exists, we insert a format!("{}/{}", self.node_id
entry into the vector clock (below). Is this intended?
match self.kvs.entry(key.clone()) { | ||
Entry::Vacant(entry) => { | ||
entry.insert(LatticeValue::SingleCausalMap( | ||
SingleKeyCausalLattice::create_with_default_clock(value), |
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 here.