moat-kv 0.70.24__py3-none-any.whl → 0.71.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- build/lib/moat/kv/_cfg.yaml +2 -6
- build/lib/moat/kv/backend/mqtt.py +0 -3
- ci/rtd-requirements.txt +4 -0
- ci/test-requirements.txt +7 -0
- ci/travis.sh +96 -0
- debian/.gitignore +7 -0
- debian/changelog +1435 -0
- debian/control +43 -0
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/_cfg.yaml +2 -6
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/backend/mqtt.py +0 -3
- debian/moat-kv.postinst +3 -0
- debian/rules +20 -0
- debian/source/format +1 -0
- debian/watch +4 -0
- docs/Makefile +20 -0
- docs/make.bat +36 -0
- docs/source/TODO.rst +61 -0
- docs/source/_static/.gitkeep +0 -0
- docs/source/acls.rst +80 -0
- docs/source/auth.rst +84 -0
- docs/source/client_protocol.rst +456 -0
- docs/source/code.rst +341 -0
- docs/source/command_line.rst +1187 -0
- docs/source/common_protocol.rst +47 -0
- docs/source/debugging.rst +70 -0
- docs/source/extend.rst +37 -0
- docs/source/history.rst +36 -0
- docs/source/index.rst +75 -0
- docs/source/model.rst +54 -0
- docs/source/overview.rst +83 -0
- docs/source/related.rst +89 -0
- docs/source/server_protocol.rst +450 -0
- docs/source/startup.rst +31 -0
- docs/source/translator.rst +244 -0
- docs/source/tutorial.rst +711 -0
- docs/source/v3.rst +168 -0
- examples/code/transform.scale.yml +21 -0
- examples/code/transform.switch.yml +82 -0
- examples/code/transform.timeslot.yml +63 -0
- moat/kv/_cfg.yaml +2 -6
- moat/kv/backend/mqtt.py +0 -3
- {moat_kv-0.70.24.dist-info → moat_kv-0.71.0.dist-info}/METADATA +2 -5
- {moat_kv-0.70.24.dist-info → moat_kv-0.71.0.dist-info}/RECORD +68 -17
- scripts/current +15 -0
- scripts/env +8 -0
- scripts/init +39 -0
- scripts/recover +17 -0
- scripts/rotate +33 -0
- scripts/run +29 -0
- scripts/run-all +10 -0
- scripts/run-any +10 -0
- scripts/run-single +15 -0
- scripts/success +4 -0
- systemd/moat-kv-recover.service +21 -0
- systemd/moat-kv-rotate.service +20 -0
- systemd/moat-kv-rotate.timer +10 -0
- systemd/moat-kv-run-all.service +26 -0
- systemd/moat-kv-run-all@.service +25 -0
- systemd/moat-kv-run-any.service +26 -0
- systemd/moat-kv-run-any@.service +25 -0
- systemd/moat-kv-run-single.service +26 -0
- systemd/moat-kv-run-single@.service +25 -0
- systemd/moat-kv.service +27 -0
- systemd/postinst +7 -0
- systemd/sysusers +3 -0
- build/lib/moat/kv/backend/serf.py +0 -45
- build/lib/moat/kv/mock/serf.py +0 -250
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/backend/serf.py +0 -45
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/mock/serf.py +0 -250
- moat/kv/backend/serf.py +0 -45
- moat/kv/mock/serf.py +0 -250
- {moat_kv-0.70.24.dist-info → moat_kv-0.71.0.dist-info}/WHEEL +0 -0
- {moat_kv-0.70.24.dist-info → moat_kv-0.71.0.dist-info}/licenses/LICENSE.txt +0 -0
- {moat_kv-0.70.24.dist-info → moat_kv-0.71.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,456 @@
|
|
1
|
+
========================
|
2
|
+
MoaT-KV's client protocol
|
3
|
+
========================
|
4
|
+
|
5
|
+
MoaT-KV's native client protocol is based on MsgPack. The client sends
|
6
|
+
requests; the server sends one or more responses. You may (and indeed
|
7
|
+
should) run concurrent requests on the same connection.
|
8
|
+
|
9
|
+
Strings must be UTF-8, as per MsgPack specification.
|
10
|
+
|
11
|
+
Requests and replies are mappings.
|
12
|
+
|
13
|
+
The server initially sends a greeting, using sequence number zero. It will
|
14
|
+
not send any other unsolicited message.
|
15
|
+
|
16
|
+
Requests
|
17
|
+
========
|
18
|
+
|
19
|
+
Client requests are always mappings. ``seq`` and ``action`` must be
|
20
|
+
present. All other fields are request specific. The server will ignore
|
21
|
+
fields it doesn't understand.
|
22
|
+
|
23
|
+
seq
|
24
|
+
---
|
25
|
+
|
26
|
+
Every client request must contain a strictly increasing positive sequence
|
27
|
+
number. All replies associated with a request carry the same sequence
|
28
|
+
number.
|
29
|
+
|
30
|
+
action
|
31
|
+
------
|
32
|
+
|
33
|
+
The action which the server is requested to perform. Valid actions are
|
34
|
+
described below.
|
35
|
+
|
36
|
+
nchain
|
37
|
+
------
|
38
|
+
|
39
|
+
This field tells the MoaT-KV server how many change entries to return.
|
40
|
+
The default is zero. If you want to update a value, retrieve the
|
41
|
+
original with ``nchain`` set to one. Synchronization between MoaT-KV servers
|
42
|
+
requires the number of possible partitions plus one, in order to protect
|
43
|
+
against spurious conflict reports.
|
44
|
+
|
45
|
+
path
|
46
|
+
----
|
47
|
+
|
48
|
+
The subset of data affected by the current command.
|
49
|
+
|
50
|
+
|
51
|
+
Replies
|
52
|
+
=======
|
53
|
+
|
54
|
+
Server replies are always mappings. At least one of ``seq`` and ``error``
|
55
|
+
must be present. The client must ignore fields it doesn't expect.
|
56
|
+
|
57
|
+
seq
|
58
|
+
---
|
59
|
+
|
60
|
+
The sequence number of the request which caused this reply.
|
61
|
+
|
62
|
+
Server messages which don't include a sequence number are errors and
|
63
|
+
will close the connection.
|
64
|
+
|
65
|
+
The server will either send exactly one reply with any given sequence number,
|
66
|
+
or a multi-reply sequence which starets with a ``state=start`` message.
|
67
|
+
|
68
|
+
error
|
69
|
+
-----
|
70
|
+
|
71
|
+
This field contains a human-readable error message. A request has failed if
|
72
|
+
this field is present.
|
73
|
+
|
74
|
+
value
|
75
|
+
-----
|
76
|
+
|
77
|
+
The value of the MoaT-KV entry, assuming one was requested.
|
78
|
+
|
79
|
+
state
|
80
|
+
-----
|
81
|
+
May be ``start`` or ``end``
|
82
|
+
|
83
|
+
* ``start`` indicates the beginning of a multi-value result.
|
84
|
+
|
85
|
+
* ``end`` indicates that a multi-value result has finished. No more
|
86
|
+
messages with this sequence number will be sent.
|
87
|
+
|
88
|
+
The ``start`` message will contain neither an error nor a value.
|
89
|
+
|
90
|
+
chain
|
91
|
+
-----
|
92
|
+
|
93
|
+
The change chain resulting from, or retrieved by, a command.
|
94
|
+
|
95
|
+
Change chains track which server last modified a value, so that replayed
|
96
|
+
updates can be ignored and conflicting updates can be recognized. A chain
|
97
|
+
never contains any one MoaT-KV server more than once.
|
98
|
+
|
99
|
+
See the server protocol for a detailed description.
|
100
|
+
|
101
|
+
tick
|
102
|
+
----
|
103
|
+
|
104
|
+
The current server's change counter. This field can be used to ensure that
|
105
|
+
the local server is not restarted with old state.
|
106
|
+
|
107
|
+
tock
|
108
|
+
----
|
109
|
+
|
110
|
+
An always-increasing integer that's (supposed to be) shared within the
|
111
|
+
whole MoaT-KV system. You can use it when you need to reconnect to a server,
|
112
|
+
to make sure that the system is (mostly) up-to-date.
|
113
|
+
|
114
|
+
path
|
115
|
+
----
|
116
|
+
|
117
|
+
The subset of data described by the current message.
|
118
|
+
|
119
|
+
depth
|
120
|
+
-----
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
Actions
|
125
|
+
=======
|
126
|
+
|
127
|
+
connect
|
128
|
+
-------
|
129
|
+
|
130
|
+
This is a pseudo-action with sequence number zero, which the server assumes
|
131
|
+
to have received after connecting. The server's first message will contain
|
132
|
+
``seq=0``, its ``node`` name, a ``version`` (as a list of integers), and
|
133
|
+
possibly its current ``tick`` and ``tock`` sequence numbers.
|
134
|
+
|
135
|
+
The ``auth`` parameter, if present, carries a list of configured
|
136
|
+
authorization methods. The first method in the list **should** be used to
|
137
|
+
authorize the client. If the list's first entry is ``None`` then
|
138
|
+
authorization is not required. Other entries **may** be used for
|
139
|
+
testing after a client is logged in.
|
140
|
+
|
141
|
+
Sample::
|
142
|
+
|
143
|
+
>>> {'seq': 0, 'version': (0, 58, 12), 'node': 'dev', 'tick': 350225, 'tock': 558759182, 'qlen': 10, 'auth': ('password',)}
|
144
|
+
|
145
|
+
auth
|
146
|
+
----
|
147
|
+
|
148
|
+
Tell the server about your identity. This method **must** be sent first, if
|
149
|
+
the server requests authorization.
|
150
|
+
|
151
|
+
The ``identity`` parameter tells the server which user ID (or equivalent)
|
152
|
+
to use for logging in. ``typ`` contains the auth type to use; this
|
153
|
+
**must** be identical to the first entry in the ``connect`` reply's
|
154
|
+
``auth`` parameter.
|
155
|
+
|
156
|
+
If this is not the first auth message, the authorization is verified but the
|
157
|
+
resulting user identity is ignored.
|
158
|
+
|
159
|
+
Example::
|
160
|
+
|
161
|
+
>>> {'typ': 'password', 'ident': 'root', 'password': b'[data]', 'action': 'auth', 'seq': 2}
|
162
|
+
<<< {'seq': 2}
|
163
|
+
|
164
|
+
test_acl
|
165
|
+
--------
|
166
|
+
|
167
|
+
Check whether the given ``path`` is accessible with the given ``mode``.
|
168
|
+
|
169
|
+
The ``acl`` to test may be specified. The user's ACL, if any, is also
|
170
|
+
tested; the return message's ``access`` element may contain ``False``
|
171
|
+
(access not allowed), ``True`` (access allowed but no ACL details
|
172
|
+
available) or the actual ACL characters.
|
173
|
+
|
174
|
+
Access will not be granted if you try to check a specific ACL when your
|
175
|
+
own rights don't include 'a' (for accessing ACLs).
|
176
|
+
|
177
|
+
stop
|
178
|
+
----
|
179
|
+
|
180
|
+
Send this action to abort a running multi-value request. Set ``task`` to
|
181
|
+
the sequence number of the request to abort.
|
182
|
+
|
183
|
+
This action only works after you received a ``start`` state message.
|
184
|
+
It returns a :class:`bool` which is ``True`` if the command was still
|
185
|
+
running.
|
186
|
+
|
187
|
+
A positive reply does not indicate that no more messages with the stated
|
188
|
+
sequence number will arrive; this will be indicated by the ``state=end``
|
189
|
+
message.
|
190
|
+
|
191
|
+
get_value
|
192
|
+
---------
|
193
|
+
|
194
|
+
Retrieve a single value.
|
195
|
+
|
196
|
+
If the value does not exist or has been deleted, you'll get ``None`` back.
|
197
|
+
|
198
|
+
Alternately, you can set ``node`` and ``tick``, which returns the entry
|
199
|
+
that has been set by this event (if the event is still available). The
|
200
|
+
entry will contain the current value even if the event has set a previous
|
201
|
+
value.
|
202
|
+
|
203
|
+
Example::
|
204
|
+
>>> {'path': P('test.one'), 'action': 'get_value', 'seq': 4}
|
205
|
+
<<< {'value': 'Two', 'tock': 12345, 'seq': 4}
|
206
|
+
|
207
|
+
set_value
|
208
|
+
---------
|
209
|
+
|
210
|
+
Set a single value. The ``path`` to that ``value`` needs to be sent as a list.
|
211
|
+
|
212
|
+
If you are updating a known value, you should send a ``chain`` entry
|
213
|
+
to help ensure that no other node has changed it unexpectedly. (Of course,
|
214
|
+
due to the distributed nature of MoaT-KV, this may happen anyway.) You can
|
215
|
+
also use ``prev`` to send an expected old value, but you really shouldn't.
|
216
|
+
|
217
|
+
This action returns the node's new change ``chain``. If you did not send a
|
218
|
+
``chain`` field, the previous value is returned in ``prev``.
|
219
|
+
|
220
|
+
Simple example::
|
221
|
+
|
222
|
+
>>> {'path': P('test.one'), 'value': 'Three', 'action': 'set_value', 'seq': 5}
|
223
|
+
<<< {'changed': True, 'tock': 12348, 'seq': 5}
|
224
|
+
|
225
|
+
However, this is not particularly safe if you want to modify a value, as
|
226
|
+
there's no way to ascertain that it hasn't been changed by somebody else in
|
227
|
+
the meantime. It's safer to retrieve the entry's change log, or at least
|
228
|
+
its first couple of entries, and then send that along with the
|
229
|
+
``set_value`` request::
|
230
|
+
|
231
|
+
>>> {'path': P('test.one'), 'nchain': 3, 'action': 'get_value', 'seq': 4}
|
232
|
+
<<< {'value': 'Three', 'chain': {'node': 'r-a', 'tick': 121, 'prev': None}, 'tock': 12355, 'seq': 4}
|
233
|
+
>>> {'path': P('test.one'), 'value': 'Four', 'nchain': 3, 'chain': {'node': 'r-a', 'tick': 121, 'prev': None}, 'action': 'set_value', 'seq': 5}
|
234
|
+
<<< {'changed': True, 'chain': {'node': 'dev', 'tick': 69, 'prev': {'node': 'r-a', 'tick': 121, 'prev': None}}, 'tock': 12358, 'seq': 5}
|
235
|
+
|
236
|
+
The ``chain`` value should be treated as opaque, except for``None`` which
|
237
|
+
indicates that the node doesn't exist.
|
238
|
+
|
239
|
+
delete_value
|
240
|
+
------------
|
241
|
+
|
242
|
+
Remove a single value. This is the same as setting it to ``None``. The
|
243
|
+
``chain`` semantics of ``set_value`` apply.
|
244
|
+
|
245
|
+
get_state
|
246
|
+
---------
|
247
|
+
|
248
|
+
Retrieve the current system state. The following ``bool``-valued attributes
|
249
|
+
may be set to specify what is returned. The corresponding reply is stored
|
250
|
+
in an attribute of the same name.
|
251
|
+
|
252
|
+
All of these data is mainly useful for debugging the replication / recovery
|
253
|
+
protocol. The resulting lists can become somewhat long on a busy system.
|
254
|
+
|
255
|
+
* nodes
|
256
|
+
|
257
|
+
A dict of server ⇒ tick. Each server's known Tick values must be
|
258
|
+
consecutive; when they are not, MoaT-KV tries to retrieve the missing
|
259
|
+
entries.
|
260
|
+
|
261
|
+
* deleted
|
262
|
+
|
263
|
+
A dict of server ⇒ ranges of ticks known to have been deleted.
|
264
|
+
|
265
|
+
* known
|
266
|
+
|
267
|
+
A dict of server ⇒ ranges of ticks known. This contains current data as well
|
268
|
+
as events that have been superseded.
|
269
|
+
|
270
|
+
* current
|
271
|
+
|
272
|
+
A dict of server ⇒ ranges of ticks corresponding to the current state of
|
273
|
+
nodes. This is expensive to calculate. It is a superset of `'known``.
|
274
|
+
|
275
|
+
* missing
|
276
|
+
|
277
|
+
A dict of server ⇒ ranges of ticks not available on the server. This list is
|
278
|
+
empty if the server thinks it is up-to-date.
|
279
|
+
|
280
|
+
* remote_missing
|
281
|
+
|
282
|
+
A dict of server ⇒ ranges of ticks reported to be missing at some other node.
|
283
|
+
|
284
|
+
* present
|
285
|
+
|
286
|
+
A dict of server ⇒ ranges of entries that actually exist.
|
287
|
+
|
288
|
+
* superseded
|
289
|
+
|
290
|
+
A dict of server ⇒ ranges of entries that have been replaced by a newer
|
291
|
+
version of the corresponding node.
|
292
|
+
|
293
|
+
get_tree
|
294
|
+
--------
|
295
|
+
|
296
|
+
Retrieves all values with the prefix given in ``path``.
|
297
|
+
|
298
|
+
This is a multi-value reply; each reply contains ``path`` and ``value``
|
299
|
+
entries. Deleted nodes may or may not be reported.
|
300
|
+
|
301
|
+
If the path does not exist or does not have children, a single-value reply
|
302
|
+
is returned.
|
303
|
+
|
304
|
+
Optimization: if a reply contains a "depth" key, its path is shortened by
|
305
|
+
the request's path, plus that many elements from the previous reply's path.
|
306
|
+
|
307
|
+
Thus, if you request a path of ``['a','b','c']``, this reply::
|
308
|
+
|
309
|
+
{ seq=13, path=['a','b','c'], value="one" }
|
310
|
+
{ seq=13, path=['a','b','c','d','e'], value="two" }
|
311
|
+
{ seq=13, path=['a','b','c','d','f'], value="three" }
|
312
|
+
|
313
|
+
is equivalent to::
|
314
|
+
|
315
|
+
{ seq=13, depth=0, value="one" }
|
316
|
+
{ seq=13, depth=0, path=['d','e'], value="two" }
|
317
|
+
{ seq=13, depth=1, path=['f'], value="three" }
|
318
|
+
|
319
|
+
* min_depth
|
320
|
+
|
321
|
+
Start reporting nodes at this depth.
|
322
|
+
|
323
|
+
* max_depth
|
324
|
+
|
325
|
+
Limit recursion depth.
|
326
|
+
|
327
|
+
* empty
|
328
|
+
|
329
|
+
Include empty nodes. This is useful when limiting the depth to non-leaf
|
330
|
+
nodes without data.
|
331
|
+
|
332
|
+
root
|
333
|
+
----
|
334
|
+
|
335
|
+
Switch the client's root to the given path. This request returns the new
|
336
|
+
root node.
|
337
|
+
|
338
|
+
It is not possible to undo this request (other than to reconnect).
|
339
|
+
Tasks started before this action are not affected.
|
340
|
+
|
341
|
+
This action returns the new root node's value.
|
342
|
+
|
343
|
+
watch
|
344
|
+
-----
|
345
|
+
|
346
|
+
Monitor changes to this node (and those below it). Replies look like those from ``get_tree``.
|
347
|
+
|
348
|
+
The recommended way to run the ``watch`` call with ``fetch=True``. This
|
349
|
+
fetches the current state and guarantees that no updates are lost. To mark
|
350
|
+
the end of the static data, the server sends a ``state=uptodate`` message.
|
351
|
+
This process will not send stale data after an update, so your code may
|
352
|
+
safely replace an old entry's state with new data.
|
353
|
+
|
354
|
+
This task obeys ``min_depth`` and ``max_depth`` restrictions.
|
355
|
+
|
356
|
+
save
|
357
|
+
----
|
358
|
+
|
359
|
+
Instruct the server to save its state to the given ``path`` (a string with
|
360
|
+
a filename).
|
361
|
+
|
362
|
+
log
|
363
|
+
---
|
364
|
+
|
365
|
+
Instruct the server to continuously write change entries to the given ``path``
|
366
|
+
(a string with a filename). If ``fetch`` is ``True``, the server will also
|
367
|
+
write its current state to that file.
|
368
|
+
|
369
|
+
This command returns after the new file has been opened and the initial
|
370
|
+
state has been written, if so requested. If there was an old log stream,
|
371
|
+
there may be some duplicate entries. No updates are skipped.
|
372
|
+
|
373
|
+
msg_send
|
374
|
+
--------
|
375
|
+
|
376
|
+
Pass-through call to transmit a message. Parameters are ``type`` (the user
|
377
|
+
event to send to) and ``data`` (the data to send).
|
378
|
+
|
379
|
+
Raw binary data may be transmitted by using ``raw`` instead of ``data``.
|
380
|
+
|
381
|
+
msg_monitor
|
382
|
+
-----------
|
383
|
+
|
384
|
+
Pass-through call to receive brodcast messages. You'll get a
|
385
|
+
stream with ``data`` containing the decoded message. If decoding fails,
|
386
|
+
``raw`` contains the message's bytes and ``error`` holds a string
|
387
|
+
representation of the decoder problem.
|
388
|
+
|
389
|
+
Set ``raw`` to True if the incoming messages are not supposed to be
|
390
|
+
msgpack-encoded in the first place. In this case, ``data`` and ``error``
|
391
|
+
will always be missing.
|
392
|
+
|
393
|
+
Examples
|
394
|
+
========
|
395
|
+
|
396
|
+
You can turn on message debugging with 'moat -vvv kv'.
|
397
|
+
|
398
|
+
Get and set a value
|
399
|
+
-------------------
|
400
|
+
|
401
|
+
If the value is not set::
|
402
|
+
|
403
|
+
Send {'path': ('test',), 'nchain': 3, 'action': 'get_tree', 'seq': 1}
|
404
|
+
Recv {'value': None, 'seq': 1}
|
405
|
+
|
406
|
+
Setting an initial value::
|
407
|
+
|
408
|
+
Send {'value': 1234, 'path': ('test',), 'nchain': 2, 'chain': None, 'action': 'set_value', 'seq': 2}
|
409
|
+
Recv {'changed': True, 'chain': {'node': 'test1', 'tick': 2, 'prev': None}, 'seq': 2}
|
410
|
+
|
411
|
+
Trying the same thing again will result in an error::
|
412
|
+
|
413
|
+
Send {'value': 1234, 'path': ('test',), 'nchain': 2, 'chain': None, 'action': 'set_value', 'seq': 3}
|
414
|
+
Recv {'error': 'This entry already exists', 'seq': 3}
|
415
|
+
|
416
|
+
To fix that, use the chain value you got when setting or retrieving the
|
417
|
+
previous value::
|
418
|
+
|
419
|
+
Send {'value': 123, 'path': ('test',), 'nchain': 2, 'chain': {'node': 'test1', 'tick': 2}, 'action': 'set_value', 'seq': 4}
|
420
|
+
Recv {'changed': True, 'chain': {'node': 'test1', 'tick': 3, 'prev': None}, 'seq': 4}
|
421
|
+
|
422
|
+
Sending no precondition would also work
|
423
|
+
|
424
|
+
After you set multiple values::
|
425
|
+
|
426
|
+
Send {'value': 123, 'path': ('test', 'foo'), 'nchain': 0, 'action': 'set_value', 'seq': 5}
|
427
|
+
Recv {'changed': True, 'prev': None, 'seq': 5}
|
428
|
+
Send {'value': 12, 'path': ('test', 'foo', 'bap'), 'nchain': 0, 'action': 'set_value', 'seq': 6}
|
429
|
+
Recv {'changed': True, 'prev': None, 'seq': 6}
|
430
|
+
Send {'value': 1, 'path': ('test', 'foo', 'bar', 'baz'), 'nchain': 0, 'action': 'set_value', 'seq': 7}
|
431
|
+
Recv {'changed': True, 'prev': None, 'seq': 7}
|
432
|
+
Send {'value': 1234, 'path': ('test',), 'nchain': 0, 'action': 'set_value', 'seq': 8}
|
433
|
+
Recv {'changed': True, 'prev': 123, 'seq': 8}
|
434
|
+
|
435
|
+
you can retrieve the whole subtree::
|
436
|
+
|
437
|
+
Send {'path': ('test',), 'nchain': 0, 'action': 'get_tree', 'seq': 1}
|
438
|
+
Recv {'seq': 1, 'state': 'start'}
|
439
|
+
Recv {'value': 1234, 'depth': 0, 'seq': 1}
|
440
|
+
Recv {'value': 123, 'path': ('foo',), 'depth': 0, 'seq': 1}
|
441
|
+
Recv {'value': 12, 'path': ('bap',), 'depth': 1, 'seq': 1}
|
442
|
+
Recv {'value': 1, 'path': ('bar', 'baz'), 'depth': 1, 'seq': 1}
|
443
|
+
Recv {'seq': 1, 'state': 'end'}
|
444
|
+
|
445
|
+
Retrieving this tree with ``moat kv test get -rd ':val'`` would print::
|
446
|
+
|
447
|
+
test:
|
448
|
+
:val: 1
|
449
|
+
foo:
|
450
|
+
:val: 1
|
451
|
+
bap: {':val': 12}
|
452
|
+
bar:
|
453
|
+
:val: 1
|
454
|
+
baz: {':val': 1}
|
455
|
+
|
456
|
+
|