This module provides a POLog CRDT implementation with an Erlang map data type for use in internal CloudI services. Usage of the module handles the replication of Erlang map state between Erlang processes to provide an eventually consistent data store among internal CloudI service processes.
.Copyright © 2017-2018 Michael Truog
Version: 1.7.3 Feb 26 2018 17:29:20 ------------------------------------------------------------------------
Authors: Michael Truog (mjtruog [at] gmail (dot) com).
This module provides a POLog CRDT implementation with an Erlang map data type for use in internal CloudI services. Usage of the module handles the replication of Erlang map state between Erlang processes to provide an eventually consistent data store among internal CloudI service processes.
The bootstrap functionality and the clean_vclocks functionality are not described in the POLog papers and are likely unique to this implementation. This additional functionality allows CloudI service processes that utilize cloudi_crdt to start, restart or fail (a crash, netsplit, etc.) without affecting other instances of cloudi_crdt that are configured with the same service name and manage the same data.
The cloudi_crdt functions that may be called within cloudi_service_init/4 are events_subscribe/3, events_subscribe/4, events_clear/3, new/1 and new/2. A CloudI service that uses cloudi_crdt should have a destination refresh method that is immediate.
The papers related to this implementation of the POLog CRDT are:
Carlos Baquero, Paulo Sérgio Almeida, Ali Shoker. Pure Operation-Based Replicated Data Types. 2017. https://arxiv.org/abs/1710.04469
Georges Younes, Ali Shoker, Paulo Sérgio Almeida, and Carlos Baquero. Integration Challenges of Pure Operation-based CRDTs in Redis. In First Workshop on Programming Models and Languages for Distributed Computing (PMLDC '16). ACM, New York, NY, USA, Article 7, 2016. http://haslab.uminho.pt/cbm/files/pmldc-2016-redis-crdts.pdf
Carlos Baquero, Paulo Sérgio Almeida, and Ali Shoker. Making operation-based crdts operation-based. In Proceedings of the First Workshop on Principles and Practice of Eventual Consistency, page 7. ACM, 2014. http://haslab.uminho.pt/ashoker/files/opbaseddais14.pdf
Mattern, Friedemann. "Virtual Time and Global States of Distributed Systems". Workshop on Parallel and Distributed Algorithms: pp. 215-226 (1988). http://homes.cs.washington.edu/~arvind/cs425/doc/mattern89virtual.pdf
Lamport, Leslie. "Time, clocks, and the ordering of events in a distributed system". Communications of the ACM. 21 (7): 558–565. (1978) http://research.microsoft.com/en-us/um/people/lamport/pubs/time-clocks.pdfevent_type() = assign | clear | decr | incr | put | update
events() = #{key() := [event_type()]}
key() = any()
node_id() = {node(), cloudi_service:source()}
operation_write() = {assign, Key::key(), Value::value()} | {incr, Key::key(), Value::value()} | {decr, Key::key(), Value::value()} | {update, Key::key(), ModuleVersion::list(), Module::module(), Function::atom()} | {update, Key::key(), ModuleVersion::list(), Module::module(), Function::atom(), Argument1::any()} | {put, Key::key(), Value::value()} | {clear, Key::key()} | clear_all
options() = [{service_name, string()} | {clean_vclocks, seconds()} | {clean_vclocks_failure, float() | 1..100} | {retry, non_neg_integer()} | {retry_delay, non_neg_integer()}]
polog() = [{vclock(), operation_write()}]
polog_mode() = bootstrap | normal
seconds() = 1..4294967
state() = #cloudi_crdt{service_name_full = cloudi_service:service_name(), clean_vclocks_interval = seconds(), clean_vclocks_failure = number(), queue = cloudi_queue:state(), word_size = pos_integer(), node_id = node_id(), node_ids = [node_id()], vclock = vclock(), vclocks = vclocks(), polog_mode = polog_mode(), polog = polog(), data = data(), events = events()}
value() = any()
vclock() = #{node_id() := non_neg_integer()}
vclocks() = #{node_id() := vclock()}
assign(Dispatcher::cloudi_service:dispatcher(), Key::key(), Value::value(), State::state()) -> state()
byte_size(Dispatcher::cloudi_service:dispatcher(), State::state()) -> non_neg_integer()
clear(Dispatcher::cloudi_service:dispatcher(), State::state()) -> state()
clear(Dispatcher::cloudi_service:dispatcher(), Key::key(), State::state()) -> state()
decr(Dispatcher::cloudi_service:dispatcher(), Key::key(), State::state()) -> state()
decr(Dispatcher::cloudi_service:dispatcher(), Key::key(), Value::number(), State::state()) -> state()
events_clear(Dispatcher::cloudi_service:dispatcher(), Key::key(), State::state()) -> state()
events_subscribe(Dispatcher::cloudi_service:dispatcher(), Key::key(), State::state()) -> state()
events_subscribe(Dispatcher::cloudi_service:dispatcher(), Key::key(), EventTypes::[event_type()], State::state()) -> state()
find(Dispatcher::cloudi_service:dispatcher(), Key::key(), State::state()) -> {ok, Value::value()} | error
fold(Dispatcher::cloudi_service:dispatcher(), F::fun((Key::key(), Value::value(), AccIn::any()) -> AccOut::any()), AccInit::any(), State::state()) -> AccFinal::any()
get(Dispatcher::cloudi_service:dispatcher(), Key::key(), State::state()) -> Value::value()
handle_info(Request::any(), State::state(), Dispatcher::cloudi_service:dispatcher()) -> {ok, StateNew::state()} | {{error, Reason::cloudi_service:error_reason()}, StateNew::state()} | {ignored, State::state()}
cloudi_service_handle_info/3
callback function.
handle_request(Type::cloudi_service:request_type(), Name::cloudi_service:service_name(), Pattern::cloudi_service:service_name_pattern(), RequestInfo::cloudi_service:request_info(), Request::cloudi_service:request(), Timeout::cloudi_service:timeout_value_milliseconds(), Priority::cloudi_service:priority_value(), TransId::cloudi_service:trans_id(), Pid::cloudi_service:source(), State::state(), Dispatcher::cloudi_service:dispatcher()) -> {ok, StateNew::state()} | {ignored, State::state()}
cloudi_service_handle_request/11
callback function.
incr(Dispatcher::cloudi_service:dispatcher(), Key::key(), State::state()) -> state()
incr(Dispatcher::cloudi_service:dispatcher(), Key::key(), Value::number(), State::state()) -> state()
is_key(Dispatcher::cloudi_service:dispatcher(), Key::key(), State::state()) -> boolean()
keys(Dispatcher::cloudi_service:dispatcher(), State::state()) -> [key()]
new(Dispatcher::cloudi_service:dispatcher()) -> state()
new(Dispatcher::cloudi_service:dispatcher(), Options::options()) -> state()
put(Dispatcher::cloudi_service:dispatcher(), Key::key(), Value::value(), State::state()) -> state()
size(Dispatcher::cloudi_service:dispatcher(), State::state()) -> non_neg_integer()
update(Dispatcher::cloudi_service:dispatcher(), Key::key(), Module::module(), Function::atom(), State::state()) -> state()
update(Dispatcher::cloudi_service:dispatcher(), Key::key(), Module::module(), Function::atom(), Argument1::any(), State::state()) -> state()
values(Dispatcher::cloudi_service:dispatcher(), State::state()) -> [value()]
zero(Dispatcher::cloudi_service:dispatcher(), Key::key(), State::state()) -> state()
Generated by EDoc, Feb 26 2018, 17:29:20.