Source code for xotl.crdt.base

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ---------------------------------------------------------------------
# Copyright (c) Merchise Autrement [~º/~] and Contributors
# All rights reserved.
#
# This is free software; you can do what the LICENCE file allows you to.
#
"""Base interfaces."""
from dataclasses import dataclass


[docs]@dataclass(frozen=True, order=True) class Process: """Represents a process or node that holds replicated objects. We require (for some CRDTs) that processes are uniquely named and totally ordered across the cluster. So when adding/removing a process you should take measures for not reusing old names. """ order: int name: str def __init__(self, name: str, order: int) -> None: object.__setattr__(self, "name", name) object.__setattr__(self, "order", order) def __repr__(self): return f"Process({self.name!r}, {self.order!r})" def __eq__(self, other) -> bool: if isinstance(other, Process): return self.name == other.name else: return NotImplemented
[docs]class CvRDT: """Base class for Convergent Replicated Data Types. Basically this documents the expectation of each CvRDT. Subclasses **must** implement the following methods and attributes. """ def __init__(self, *, process: Process) -> None: self.process = process self.init()
[docs] def init(self) -> None: """Set the initial state of a newly create CRDT."""
[docs] def merge(self, other: "CvRDT") -> None: """Update the CvRDT to account for the another replica's state. """ raise NotImplementedError
@property def value(self): """The current value that is managed by this CRDT. This could be any type of value. But you *must* never assume changes to the value return will be of any effect. Each CRDT implements methods to properly update its value. This is a read-only property. """ raise NotImplementedError
[docs] def reset(self) -> None: "Reset the internal state of value, usually to the initial state." raise NotImplementedError
[docs] def __le__(self, other): """Compares two replicas for '<=' in the semilattice. This is **NOT** a relation of the `value`:any:. """ return NotImplemented
[docs] def __eq__(self, other) -> bool: """Compares two replicas for '==' in the semilattice. This is **NOT** a relation of the `value`:any:. """ return NotImplemented
[docs]def get_state(crdt: CvRDT) -> bytes: """Dumps the crdt in a way that is amenable for transmission/storage. """ import pickle return pickle.dumps(crdt)
[docs]def from_state(state: bytes) -> CvRDT: """Reconstruct the CRDT from its dumped state. `state` should be the result of calling `get_state`:func:. The following property should always hold:: assert crdt == from_state(get_state(crdt)) """ import pickle res = pickle.loads(state) if not isinstance(res, CvRDT): raise ValueError("Invalid state") # pragma: no cover else: return res