Skip to content

Commit 7c351fb

Browse files
xuniqpatiencedaur
andauthored
Document the watchers and built-in events (#2858)
Fixes #2551 Fixes #2409 Fixes #2407 * Add new functions to module box * Update watch and broadcast methods * Add System events section * Add glossary * Proofread text and add links Written by Kseniia Antonova Reviewed by Vladimir Davydov and Dmitry Oboukhov Proofread by Patience Daur Co-authored-by: Kseniia Antonova <[email protected]> Co-authored-by: Patience Daur <[email protected]>
1 parent a21b9bf commit 7c351fb

File tree

8 files changed

+361
-22
lines changed

8 files changed

+361
-22
lines changed

doc/reference/reference_lua/box.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ with ``box``, with no arguments. The ``box`` module contains:
3737

3838
box_txn_management
3939
box_sql
40+
box_events
4041
box_once
4142
box_snapshot
4243

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
.. _box-watchers:
2+
3+
Event watchers
4+
==============
5+
6+
The ``box`` module contains some features related to event subscriptions, also known as :term:`watchers <watcher>`.
7+
The subscriptions are used to inform the client about server-side :term:`events <event>`.
8+
Each event subscription is defined by a certain key.
9+
10+
.. glossary::
11+
12+
Event
13+
14+
An event is a state change or a system update that triggers the action of other systems.
15+
To read more about built-in events in Tarantool,
16+
check the :doc:`system events </reference/reference_lua/box_events/system_events>` section.
17+
18+
State
19+
A state is an internally stored key-value pair.
20+
The key is a string.
21+
The value is an arbitrary type that can be encoded as MsgPack.
22+
To update a state, use the ``box.broadcast()`` function.
23+
24+
Watcher
25+
A watcher is a :doc:`callback </book/box/triggers>` that is invoked when a state change occurs.
26+
To register a local watcher, use the ``box.watch()`` function.
27+
To create a remote watcher, use the ``watch()`` function from the ``net.box`` module.
28+
Note that it is possible to register more than one watcher for the same key.
29+
30+
How a watcher works
31+
-------------------
32+
33+
First, you register a watcher.
34+
After that, the watcher callback is invoked for the first time.
35+
In this case, the callback is triggered whether or not the key has already been broadcast.
36+
All subsequent invocations are triggered with :doc:`box.broadcast() </reference/reference_lua/box_events/broadcast>`
37+
called on the remote host.
38+
If a watcher is subscribed for a key that has not been broadcast yet, the callback is triggered only once,
39+
after the registration of the watcher.
40+
41+
The watcher callback takes two arguments.
42+
The first argument is the name of the key for which it was registered.
43+
The second one contains current key data.
44+
The callback is always invoked in a new fiber. It means that it is allowed to yield in it.
45+
A watcher callback is never executed in parallel with itself.
46+
If the key is updated while the watcher callback is running, the callback will be invoked again with the new
47+
value as soon as it returns.
48+
49+
``box.watch`` and ``box.broadcast`` functions can be used before :doc:`box.cfg </reference/reference_lua/box_cfg>`.
50+
51+
Below is a list of all functions and pages related to watchers or events.
52+
53+
.. container:: table
54+
55+
.. rst-class:: left-align-column-1
56+
.. rst-class:: left-align-column-2
57+
58+
.. list-table::
59+
:widths: 25 75
60+
:header-rows: 1
61+
62+
* - Name
63+
- Use
64+
65+
* - :doc:`./box_events/watch`
66+
- Create a local watcher.
67+
68+
* - :ref:`conn:watch() <conn-watch>`
69+
- Create a watcher for the remote host.
70+
71+
* - :doc:`./box_events/broadcast`
72+
- Update a state.
73+
74+
* - :ref:`Built-in events <system-events>`
75+
- Predefined events in Tarantool
76+
77+
.. toctree::
78+
:hidden:
79+
80+
box_events/watch
81+
box_events/broadcast
82+
box_events/system_events
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
.. _box-broadcast:
2+
3+
================================================================================
4+
box.broadcast()
5+
================================================================================
6+
7+
.. function:: box.broadcast(key, value)
8+
9+
Update the value of a particular key and notify all key watchers of the update.
10+
11+
:param string key: key name of the event to subscribe to
12+
:param value: any data that can be encoded in MsgPack
13+
14+
:return: none
15+
16+
**Possible errors:**
17+
18+
* The value can't be encoded as MsgPack.
19+
* The key refers to a ``box.`` system event
20+
21+
**Example:**
22+
23+
.. code-block:: lua
24+
25+
-- Broadcast value 42 for the 'foo' key.
26+
box.broadcast('foo', 42)
27+
28+
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
.. _system-events:
2+
3+
System events
4+
=============
5+
6+
Predefined events have a special naming schema -- theirs names always start with the reserved ``box.`` prefix.
7+
It means that you cannot create new events with it.
8+
9+
The system processes the following events:
10+
11+
* ``box.id``
12+
* ``box.status``
13+
* ``box.election``
14+
* ``box.schema``
15+
16+
In response to each event, the server sends back certain ``IPROTO`` fields.
17+
18+
The events are available from the beginning as non-:ref:`MP_NIL <box_protocol-notation>`.
19+
If a watcher subscribes to a system event before it has been broadcast,
20+
it receives an empty table for the event value.
21+
22+
The event is generated when there is a change in any of the values listed in the event.
23+
For example, see the parameters in the ``box.id`` event below -- ``id``, ``instance_uuid``, and ``replicaset_uuid``.
24+
Suppose the ``ìd`` value (``box.info.id``) has changed.
25+
This triggers the ``box.info`` event, which states that the value of ``box.info.id`` has changed,
26+
while ``box.info.uuid`` and ``box.info.cluster.uuid`` remain the same.
27+
28+
box.id
29+
~~~~~~
30+
31+
Contains :ref:`identification <box_info_info>` of the instance.
32+
Value changes are rare.
33+
34+
* ``id``: the numeric instance ID is unknown before the registration.
35+
For anonymous replicas, the value is ``0`` until they are officially registered.
36+
37+
* ``instance_uuid``: the UUID of the instance never changes after the first
38+
:doc:`box.cfg </reference/reference_lua/box_cfg>`.
39+
The value is unknown before the ``box.cfg`` call.
40+
41+
* ``replicaset_uuid``: the value is unknown until the instance joins a replicaset or boots a new one.
42+
43+
.. code-block:: none
44+
45+
-- box.id value
46+
{
47+
MP_STR “id”: MP_UINT; box.info.id,
48+
MP_STR “instance_uuid”: MP_UUID; box.info.uuid,
49+
MP_STR “replicaset_uuid”: MP_UUID box.info.cluster.uuid,
50+
}
51+
52+
box.status
53+
~~~~~~~~~~
54+
55+
Contains generic information about the instance status.
56+
57+
* ``is_ro``: :ref:`indicates the read-only mode <box_introspection-box_info>` or the ``orphan`` status.
58+
* ``is_ro_cfg``: indicates the :ref:`read_only <cfg_basic-read_only>` mode for the instance.
59+
* ``status``: shows the status of an instance.
60+
61+
.. code-block:: none
62+
63+
{
64+
MP_STR “is_ro”: MP_BOOL box.info.ro,
65+
MP_STR “is_ro_cfg”: MP_BOOL box.cfg.read_only,
66+
MP_STR “status”: MP_STR box.info.status,
67+
}
68+
69+
box.election
70+
~~~~~~~~~~~~
71+
72+
Contains fields of :doc:`box.info.election </reference/reference_lua/box_info/election>`
73+
that are necessary to find out the most recent writable leader.
74+
75+
* ``term``: shows the current election term.
76+
* ``role``: indicates the election state of the node -- ``leader``, ``follower``, or ``candidate``.
77+
* ``is_ro``: :ref:`indicates the read-only mode <box_introspection-box_info>` or the ``orphan`` status.
78+
* ``leader``: shows the leader node ID in the current term.
79+
80+
.. code-block:: none
81+
82+
{
83+
MP_STR “term”: MP_UINT box.info.election.term,
84+
MP_STR “role”: MP_STR box.info.election.state,
85+
MP_STR “is_ro”: MP_BOOL box.info.ro,
86+
MP_STR “leader”: MP_UINT box.info.election.leader,
87+
}
88+
89+
box.schema
90+
~~~~~~~~~~
91+
92+
Contains schema-related data.
93+
94+
* ``version``: shows the schema version.
95+
96+
.. code-block:: none
97+
98+
{
99+
MP_STR “version”: MP_UINT schema_version,
100+
}
101+
102+
Usage example
103+
-------------
104+
105+
.. code-block:: lua
106+
107+
local conn = net.box.connect(URI)
108+
local log = require('log')
109+
-- Subscribe to updates of key 'box.id'
110+
local w = conn:watch('box.id', function(key, value)
111+
assert(key == 'box.id')
112+
log.info("The box.id value is '%s'", value)
113+
end)
114+
115+
If you want to unregister the watcher when it's no longer needed, use the following command:
116+
117+
.. code-block:: lua
118+
119+
w:unregister()
120+
121+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
.. _box-watch:
2+
3+
================================================================================
4+
box.watch()
5+
================================================================================
6+
7+
.. function:: box.watch(key, func)
8+
9+
Subscribe to events broadcast by a local host.
10+
11+
:param string key: key name of the event to subscribe to
12+
:param function func: callback to invoke when the key value is updated
13+
14+
:return: a watcher handle. The handle consists of one method -- ``unregister()``, which unregisters the watcher.
15+
16+
To read more about watchers, see the :ref:`Functions for watchers <box-watchers>` section.
17+
18+
.. note::
19+
20+
Keep in mind that garbage collection of a watcher handle doesn't lead to the watcher's destruction.
21+
In this case, the watcher remains registered.
22+
It is okay to discard the result of ``watch`` function if the watcher will never be unregistered.
23+
24+
**Example:**
25+
26+
Server:
27+
28+
.. code-block:: lua
29+
30+
-- Broadcast value 42 for the 'foo' key.
31+
box.broadcast('foo', 42)
32+
33+
Client:
34+
35+
.. code-block:: lua
36+
37+
conn = require('net.box').connect(URI)
38+
local log = require('log')
39+
-- Subscribe to updates of the 'foo' key.
40+
local w = box.watch('foo', function(key, value)
41+
assert(key == 'foo')
42+
log.info("The box.id value is '%d'", value)
43+
end)
44+
45+
If you don't need the watcher anymore, you can unregister it using the command below:
46+
47+
.. code-block:: lua
48+
49+
w:unregister()
50+

doc/reference/reference_lua/net_box.rst

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.. _net_box-module:
1+
zc.. _net_box-module:
22

33
--------------------------------------------------------------------------------
44
Module net.box
@@ -125,14 +125,16 @@ Below is a list of all ``net.box`` functions.
125125
* - :ref:`conn:call() <net_box-call>`
126126
- Call a stored procedure
127127
* - :ref:`conn:timeout() <conn-timeout>`
128-
- Set a timeout
128+
- Set a timeout
129+
* - :ref:`conn:watch() <conn-watch>`
130+
- Subscribe to events broadcast by a remote host
129131
* - :ref:`conn:on_connect() <net_box-on_connect>`
130132
- Define a connect trigger
131133
* - :ref:`conn:on_disconnect() <net_box-on_disconnect>`
132134
- Define a disconnect trigger
133135
* - :ref:`conn:on_schema_reload() <net_box-on_schema_reload>`
134136
- Define a trigger when schema is modified
135-
* - :ref:`conn:new_stream() <conn-new_stream>`
137+
* - :ref:`conn:new_stream() <conn-new_stream>`
136138
- Create a stream
137139
* - :ref:`stream:begin() <net_box-stream_begin>`
138140
- Begin a stream transaction
@@ -216,7 +218,7 @@ Below is a list of all ``net.box`` functions.
216218
support the specified features, the connection will fail with an error message.
217219
With ``required_protocol_features = {'transactions'}``, all connections fail where the
218220
server has ``transactions: false``.
219-
221+
220222
.. container:: table
221223

222224
.. list-table::
@@ -240,7 +242,7 @@ Below is a list of all ``net.box`` functions.
240242
- IPROTO_FEATURE_ERROR_EXTENSION
241243
- 2 and newer
242244
* - ``watchers``
243-
- Requires remote watchers support on the server
245+
- Requires remote :ref:`watchers <conn-watch>` support on the server
244246
- IPROTO_FEATURE_WATCHERS
245247
- 3 and newer
246248

@@ -533,7 +535,61 @@ Below is a list of all ``net.box`` functions.
533535
- B
534536
...
535537
538+
.. _conn-watch:
539+
540+
.. method:: watch(key, func)
541+
542+
Subscribe to events broadcast by a remote host.
543+
544+
:param string key: a key name of an event to subscribe to
545+
:param function func: a callback to invoke when the key value is updated
546+
:return: a watcher handle. The handle consists of one method -- ``unregister()``, which unregisters the watcher.
547+
548+
To read more about watchers, see the :ref:`Functions for watchers <box-watchers>` section.
549+
550+
The method has the same syntax as the :doc:`box.watch() </reference/reference_lua/box_events/broadcast>`
551+
function, which is used for subscribing to events locally.
552+
553+
Watchers survive reconnection (see the ``reconnect_after`` connection :ref:`option <net_box-new>`).
554+
All registered watchers are automatically resubscribed when the
555+
connection is reestablished.
556+
557+
If a remote host supports watchers, the ``watchers`` key will be set in the
558+
connection ``peer_protocol_features``.
559+
For details, check the :ref:`net.box features table <net_box-new>`.
560+
561+
.. note::
562+
563+
Keep in mind that garbage collection of a watcher handle doesn't lead to the watcher's destruction.
564+
In this case, the watcher remains registered.
565+
It is okay to discard the result of ``watch`` function if the watcher will never be unregistered.
566+
567+
**Example:**
568+
569+
Server:
570+
571+
.. code-block:: lua
572+
573+
-- Broadcast value 42 for the 'foo' key.
574+
box.broadcast('foo', 42)
575+
576+
Client:
577+
578+
.. code-block:: lua
579+
580+
conn = net.box.connect(URI)
581+
local log = require('log')
582+
-- Subscribe to updates of the 'foo' key.
583+
w = conn:watch('foo', function(key, value)
584+
assert(key == 'foo')
585+
log.info("The box.id value is '%d'", value)
586+
end)
587+
588+
If you don't need the watcher anymore, you can unregister it using the command below:
589+
590+
.. code-block:: lua
536591
592+
w:unregister()
537593
538594
.. _conn-timeout:
539595

0 commit comments

Comments
 (0)