Add some doc on LWW

This commit is contained in:
Quentin 2020-11-23 18:17:48 +01:00
parent 8722e27600
commit cbd10c1b0a

View file

@ -40,7 +40,22 @@ where
/// Last Write Win (LWW) /// Last Write Win (LWW)
/// ///
/// LWW is a very simple /// LWW is based on time, the most recent write wins.
/// As multiple computers clocks are always desynchronized,
/// when operations are close enough, it is equivalent to
/// take one copy and drop the other one.
///
/// Given that clocks are not too desynchronized, this assumption
/// is enough for most cases, as there is few chance that two humans
/// coordonate themself faster than the time difference between two NTP servers.
///
/// As a more concret example, let's suppose you want to upload a file
/// with the same key (path) in the same bucket at the very same time.
/// For each request, the file will be timestamped by the receiving server
/// and may differ from what you observed with your atomic clock!
///
/// This scheme is used by AWS S3 or Soundcloud and often without knowing
/// in entreprise when reconciliating databases with ad-hoc scripts.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct LWW<T> { pub struct LWW<T> {
ts: u64, ts: u64,
@ -51,22 +66,36 @@ impl<T> LWW<T>
where where
T: CRDT, T: CRDT,
{ {
/// Creates a new CRDT
///
/// CRDT's internal timestamp is set with current node's clock.
pub fn new(value: T) -> Self { pub fn new(value: T) -> Self {
Self { Self {
ts: now_msec(), ts: now_msec(),
v: value, v: value,
} }
} }
/// Build a new CRDT from a previous non-compatible one
///
/// Compared to new, the CRDT's timestamp is not set to now
/// but must be set to the previous, non-compatible, CRDT's timestamp.
pub fn migrate_from_raw(ts: u64, value: T) -> Self { pub fn migrate_from_raw(ts: u64, value: T) -> Self {
Self { ts, v: value } Self { ts, v: value }
} }
/// Update the LWW CRDT while keeping some causal ordering.
pub fn update(&mut self, new_value: T) { pub fn update(&mut self, new_value: T) {
self.ts = std::cmp::max(self.ts + 1, now_msec()); self.ts = std::cmp::max(self.ts + 1, now_msec());
self.v = new_value; self.v = new_value;
} }
/// Get the CRDT value
pub fn get(&self) -> &T { pub fn get(&self) -> &T {
&self.v &self.v
} }
/// Get a mutable value for the CRDT
pub fn get_mut(&mut self) -> &mut T { pub fn get_mut(&mut self) -> &mut T {
&mut self.v &mut self.v
} }