* fix merge issues of DataEnvelope and its pruning * simplify by removing the tombstones, which didn't work in all cases anyway * keep the PruningPerformed markers in the DataEnvelope until configured TTL has elapsed (wall clock) * simplify PruningState structure * also store the pruning markers in durable data * collect removed nodes from the data, listing on MemberRemoved is not enough * possibility to disable pruning altogether * documented caveat for durable data
108 lines
3.2 KiB
Scala
108 lines
3.2 KiB
Scala
/**
|
|
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
|
|
*/
|
|
package akka.cluster.ddata
|
|
|
|
import akka.cluster.UniqueAddress
|
|
|
|
/**
|
|
* Interface for implementing a state based convergent
|
|
* replicated data type (CvRDT).
|
|
*
|
|
* ReplicatedData types must be serializable with an Akka
|
|
* Serializer. It is highly recommended to implement a serializer with
|
|
* Protobuf or similar. The built in data types are marked with
|
|
* [[ReplicatedDataSerialization]] and serialized with
|
|
* [[akka.cluster.ddata.protobuf.ReplicatedDataSerializer]].
|
|
*
|
|
* Serialization of the data types are used in remote messages and also
|
|
* for creating message digests (SHA-1) to detect changes. Therefore it is
|
|
* important that the serialization produce the same bytes for the same content.
|
|
* For example sets and maps should be sorted deterministically in the serialization.
|
|
*
|
|
* ReplicatedData types should be immutable, i.e. "modifying" methods should return
|
|
* a new instance.
|
|
*/
|
|
trait ReplicatedData {
|
|
/**
|
|
* The type of the concrete implementation, e.g. `GSet[A]`.
|
|
* To be specified by subclass.
|
|
*/
|
|
type T <: ReplicatedData
|
|
|
|
/**
|
|
* Monotonic merge function.
|
|
*/
|
|
def merge(that: T): T
|
|
|
|
}
|
|
|
|
/**
|
|
* Java API: Interface for implementing a [[ReplicatedData]] in Java.
|
|
*
|
|
* The type parameter `D` is a self-recursive type to be defined by the
|
|
* concrete implementation.
|
|
* E.g. `class TwoPhaseSet extends AbstractReplicatedData<TwoPhaseSet>`
|
|
*/
|
|
abstract class AbstractReplicatedData[D <: AbstractReplicatedData[D]] extends ReplicatedData {
|
|
|
|
override type T = ReplicatedData
|
|
|
|
/**
|
|
* Delegates to [[#mergeData]], which must be implemented by subclass.
|
|
*/
|
|
final override def merge(that: ReplicatedData): ReplicatedData =
|
|
mergeData(that.asInstanceOf[D])
|
|
|
|
/**
|
|
* Java API: Monotonic merge function.
|
|
*/
|
|
def mergeData(that: D): D
|
|
|
|
}
|
|
|
|
/**
|
|
* [[ReplicatedData]] that has support for pruning of data
|
|
* belonging to a specific node may implement this interface.
|
|
* When a node is removed from the cluster these methods will be
|
|
* used by the [[Replicator]] to collapse data from the removed node
|
|
* into some other node in the cluster.
|
|
*
|
|
* See process description in the 'CRDT Garbage' section of the [[Replicator]]
|
|
* documentation.
|
|
*/
|
|
trait RemovedNodePruning extends ReplicatedData {
|
|
|
|
/**
|
|
* The nodes that have changed the state for this data
|
|
* and would need pruning when such node is no longer part
|
|
* of the cluster.
|
|
*/
|
|
def modifiedByNodes: Set[UniqueAddress]
|
|
|
|
/**
|
|
* Does it have any state changes from a specific node,
|
|
* which has been removed from the cluster.
|
|
*/
|
|
def needPruningFrom(removedNode: UniqueAddress): Boolean
|
|
|
|
/**
|
|
* When the `removed` node has been removed from the cluster the state
|
|
* changes from that node will be pruned by collapsing the data entries
|
|
* to another node.
|
|
*/
|
|
def prune(removedNode: UniqueAddress, collapseInto: UniqueAddress): T
|
|
|
|
/**
|
|
* Remove data entries from a node that has been removed from the cluster
|
|
* and already been pruned.
|
|
*/
|
|
def pruningCleanup(removedNode: UniqueAddress): T
|
|
}
|
|
|
|
/**
|
|
* Marker trait for `ReplicatedData` serialized by
|
|
* [[akka.cluster.ddata.protobuf.ReplicatedDataSerializer]].
|
|
*/
|
|
trait ReplicatedDataSerialization extends Serializable
|
|
|