@@ -44,9 +44,9 @@ Because RabbitMQ already uses an implementation of the Raft consensus algorithm
4444for its quorum queues, it was decided to leverage that library for all
4545metadata. That's how Khepri was borned.
4646
47- Thanks to Ra and Raft, it is <strong>clear how Khepri will behave during and
48- recover from a network partition </strong>. This makes it more comfortable for
49- the RabbitMQ team and users, thanks to the absence of unknowns.
47+ Thanks to Ra and Raft, it is <strong>clear how Khepri will behave during a
48+ network partition and recover from it </strong>. This makes it more comfortable
49+ for the RabbitMQ team and users, thanks to the absence of unknowns.
5050
5151<blockquote>
5252At the time of this writing, RabbitMQ does not use Khepri in a production
@@ -91,7 +91,7 @@ More payload types may be added in the future.
9191
9292Payloads are represented using macros or helper functions:
9393<ul>
94- <li>`none ' and {@link khepri:no_payload/0}</li>
94+ <li>`?NO_PAYLOAD ' and {@link khepri:no_payload/0}</li>
9595<li>`#kpayload_data{data = Term}' and {@link khepri:data_payload/1}</li>
9696<li>`#kpayload_sproc{sproc = Fun}' and {@link khepri:sproc_payload/1}</li>
9797</ul>
@@ -108,10 +108,10 @@ specific use cases and detect the type of payload.
108108Properties are:
109109<ul>
110110<li>The version of the payload, tracking the number of times it was modified
111- ({@link khepri_machine :payload_version()}).</li>
111+ ({@link khepri :payload_version()}).</li>
112112<li>The version of the list of child nodes, tracking the number of times child
113- nodes were added or removed ({@link khepri_machine :child_list_version()}).</li>
114- <li>The number of child nodes ({@link khepri_machine :child_list_count()}).</li>
113+ nodes were added or removed ({@link khepri :child_list_version()}).</li>
114+ <li>The number of child nodes ({@link khepri :child_list_count()}).</li>
115115</ul>
116116
117117=== Addressing a tree node ===
@@ -189,68 +189,45 @@ KeepWhileCondition = #{[stock, wood] => #if_child_list_length{count = {gt, 0}}}.
189189`keep_while' conditions on self (like the example above) are not evaluated on
190190the first insert though.
191191
192- == Khepri API ==
192+ == Stores ==
193+
194+ A Khepri store corresponds to one Ra cluster. In fact, the name of the Ra
195+ cluster is the name of the Khepri store. It is possible to have multiple
196+ database instances running on the same Erlang node or cluster by starting
197+ multiple Ra clusters. Note that it is called a "Ra cluster" but it can have a
198+ single member.
193199
194- === High-level API ===
200+ By default, {@link khepri:start/0} starts a default store called `khepri',
201+ based on Ra's default system. You can start a simple store using {@link
202+ khepri:start/1}. To configure a cluster, you need to use {@link
203+ khepri_clustering} to add or remove members.
204+
205+ == Khepri API ==
195206
196- A high-level API is provided by the {@link khepri} module. It covers most
197- common use cases and should be straightforward to use.
207+ The essential part of the public API is provided by the {@link khepri} module.
208+ It covers most common use cases and should be straightforward to use.
198209
199210```
200- khepri:insert ([stock, wood, <<"lime tree">>], 150),
211+ {ok, _} = khepri:put ([stock, wood, <<"lime tree">>], 150),
201212
202213Ret = khepri:get([stock, wood, <<"lime tree">>]),
203214{ok, #{[stock, wood, <<"lime tree">>] =>
204- #{child_list_count => 0 ,
205- child_list_version => 1,
206- data => 150 ,
207- payload_version => 1}}} = Ret,
215+ #{data => 150 ,
216+ payload_version => 1,
217+ child_list_count => 0 ,
218+ child_list_version => 1}}} = Ret,
208219
209220true = khepri:exists([stock, wood, <<"lime tree">>]),
210221
211- khepri:delete([stock, wood, <<"lime tree">>]).
222+ {ok, _} = khepri:delete([stock, wood, <<"lime tree">>]).
212223'''
213224
214- === Low-level API ===
225+ Inside transaction funtions, {@link khepri_tx} must be used instead of {@link
226+ khepri}. The former provides the same API, except for functions which don't
227+ make sense in the context of a transaction function.
215228
216229The high-level API is built on top of a low-level API. The low-level API is
217- provided by the {@link khepri_machine} module.
218-
219- The low-level API provides just a handful of primitives. More advanced or
220- specific use cases may need to rely on that low-level API.
221-
222- ```
223- %% Unlike the high-level API's `khepri:insert/2' function, this low-level
224- %% insert returns whatever it replaced (if anything). In this case, there was
225- %% nothing before, so the returned value is empty.
226- Ret1 = khepri_machine:put(
227- StoreId, [stock, wood, <<"lime tree">>],
228- #kpayload_data{data = 150}),
229- {ok, #{}} = Ret1,
230-
231- Ret2 = khepri_machine:get(StoreId, [stock, wood, <<"lime tree">>]),
232- {ok, #{[stock, wood, <<"lime tree">>] =>
233- #{child_list_count => 0,
234- child_list_version => 1,
235- data => 150,
236- payload_version => 1}}} = Ret2,
237-
238- %% Unlike the high-level API's `khepri:delete/2' function, this low-level
239- %% delete returns whatever it deleted.
240- Ret3 = khepri_machine:delete(StoreId, [stock, wood, <<"lime tree">>]),
241- {ok, #{[stock, wood, <<"lime tree">>] =>
242- #{child_list_count => 0,
243- child_list_version => 1,
244- data => 150,
245- payload_version => 1}}} = Ret3.
246- '''
247-
248- === Stores ===
249-
250- It is possible to have multiple database instances running on the same Erlang
251- node or cluster.
252-
253- By default, Khepri starts a default store, based on Ra's default system.
230+ provided by the private {@link khepri_machine} module.
254231
255232== Transactions ==
256233
@@ -273,8 +250,7 @@ next section need to be taken into account.</li>
273250</ul>
274251
275252The nature of the anonymous function is passed as the `ReadWrite' argument to
276- {@link khepri:transaction/3} or {@link khepri_machine:transaction/3}
277- functions.
253+ {@link khepri:transaction/3}.
278254
279255=== The constraints imposed by Raft ===
280256
@@ -344,9 +320,9 @@ outside of the changes to the tree nodes.
344320If the transaction needs to have side effects, there are two options:
345321<ul>
346322<li>Perform any side effects after the transaction.</li>
347- <li>Use {@link khepri_machine :put/3} with {@link
348- khepri_condition:if_payload_version()} conditions in the path and retry if the
349- put fails because the version changed in between.</li>
323+ <li>Use {@link khepri :put/3} with {@link khepri_condition:if_payload_version()}
324+ conditions in the path and retry if the put fails because the version changed
325+ in between.</li>
350326</ul>
351327
352328Here is an example of the second option:
@@ -355,7 +331,7 @@ Here is an example of the second option:
355331Path = [stock, wood, <<"lime tree">>],
356332{ok, #{Path := #{data = Term,
357333 payload_version = PayloadVersion}}} =
358- khepri_machine :get(StoredId, Path),
334+ khepri :get(StoredId, Path),
359335
360336%% Do anything with `Term` that depend on external factors and could have side
361337%% effects.
@@ -420,40 +396,40 @@ A stored procedure can accept any numbers of arguments too.
420396
421397It is possible to execute a stored procedure directly without configuring any
422398triggers. To execute a stored procedure, you can call {@link
423- khepri_machine :run_sproc/3}. Here is an example:
399+ khepri :run_sproc/3}. Here is an example:
424400
425401```
426- Ret = khepri_machine :run_sproc(
402+ Ret = khepri :run_sproc(
427403 StoreId,
428404 StoredProcPath,
429405 [] = _Args).
430406'''
431407
432408This works exactly like {@link erlang:apply/2}. The list of arguments passed
433- to {@link khepri_machine :run_sproc/3} must correspond to the stored procedure
409+ to {@link khepri :run_sproc/3} must correspond to the stored procedure
434410arity.
435411
436412=== Configuring a trigger ===
437413
438414Khepri uses <em>event filters</em> to associate a type of events with a stored
439415procedure. Khepri supports tree changes events and thus only supports a single
440- event filter called {@link khepri_machine :event_filter_tree()}.
416+ event filter called {@link khepri :event_filter_tree()}.
441417
442- An event filter is registered using {@link khepri_machine :register_trigger/4}:
418+ An event filter is registered using {@link khepri :register_trigger/4}:
443419
444420```
445421EventFilter = #kevf_tree{path = [stock, wood, <<"oak">>], %% Required
446422 props = #{on_actions => [delete], %% Optional
447423 priority => 10}}, %% Optional
448424
449- ok = khepri_machine :register_trigger(
425+ ok = khepri :register_trigger(
450426 StoreId,
451427 TriggerId,
452428 EventFilter,
453429 StoredProcPath))}.
454430'''
455431
456- In this example, the {@link khepri_machine :event_filter_tree()} record only
432+ In this example, the {@link khepri :event_filter_tree()} record only
457433requires the path to monitor. The path can be any path pattern and thus can
458434have conditions to monitor several nodes at once.
459435
0 commit comments