Skip to content

Commit da6c288

Browse files
committed
Fixes gh-538 Document box.session.push() and IPROTO_CHUNK code
1 parent e2146aa commit da6c288

File tree

3 files changed

+137
-2
lines changed

3 files changed

+137
-2
lines changed

doc/1.10/book/box/box_session.rst

Lines changed: 133 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
===============================================================================
1010

1111
The ``box.session`` submodule allows querying the session state, writing to a
12-
session-specific temporary Lua table, or setting up triggers which will fire
12+
session-specific temporary Lua table, or sending out-of-band messages, or
13+
setting up triggers which will fire
1314
when a session starts or ends. A *session* is an object associated with each
1415
client connection.
1516

@@ -66,6 +67,10 @@ Below is a list of all ``box.session`` functions and members.
6667
| :ref:`box.session.on_auth() | Define an authentication |
6768
| <box_session-on_auth>` | trigger |
6869
+--------------------------------------+---------------------------------+
70+
| :ref:`box.session.push() | Send an out-of-band message |
71+
| <box_session-push>` | |
72+
+--------------------------------------+---------------------------------+
73+
6974

7075
.. module:: box.session
7176

@@ -476,3 +481,130 @@ Below is a list of all ``box.session`` functions and members.
476481
function 2, box.session.user()=guest
477482
function 2, user_name=admin
478483
function 1, box.session.user()=guest
484+
485+
.. _box_session-push:
486+
487+
.. function:: box.session.push(message [, sync])
488+
489+
Generate an out-of-band message. By "out-of-band" we mean an extra
490+
message which supplements what is passed in a network via the usual
491+
channels. Although ``box.session.push()`` can be called at any time, in
492+
practice it is used with networks that are set up with
493+
:ref:`module net.box <net_box-module>`, and
494+
it is invoked by the server (on the "remote database system" to use
495+
our terminology for net.box), and the client has options for getting
496+
such messages.
497+
498+
:param string-or-number message: what to send
499+
:param int sync: for an optional argument to indicate what the session is,
500+
as taken from an earlier call to :ref:`box_session:sync() <box_session-sync>`.
501+
If it is omitted, the default is the current ``box.session.sync()`` value.
502+
:rtype: {nil, error} or true.
503+
504+
If the result is an error, then the first part of the return is
505+
``nil`` and the second part is the error object. If the result is not
506+
an error, then the return is the boolean value ``true``.
507+
When the return is ``true``, the message has gone to the network
508+
buffer as a :ref:`packet <box_protocol-iproto_protocol>`
509+
with the code IPROTO_CHUNK (0x80).
510+
511+
The server's sole job is to call ``box.session.push()``, there is no
512+
automatic mechanism for showing that the message was received.
513+
The client's job is to check for such messages after it sends
514+
something to the server. The major client methods --
515+
:ref:`conn:call <net_box-call>`, :ref:`conn:eval <net_box-eval>`,
516+
:ref:`conn:select <conn-select>`, :ref:`conn:insert <conn-insert>`,
517+
:ref:`conn:replace <conn-replace>`, :ref:`conn:update <conn-update>`,
518+
:ref:`conn:upsert <conn-upsert>`, :ref:`delete <conn-delete>` --
519+
may cause the server to send a message.
520+
521+
Situation 1: when the client calls synchronously with the default
522+
``{async=false}`` option: there are two optional additional options:
523+
:samp:`on_push={function-name}`, and :samp:`on_push_ctx={function-argument}`.
524+
When the client receives an out-of-band message for the session,
525+
it invokes "function-name(function-argument)". For example, with
526+
options ``{on_push=table.insert, on_push_ctx=messages}``, the client
527+
will insert whatever it receives into a table named messages.
528+
529+
Situation 2: when the client calls asynchronously with the non-default
530+
``{async=true}`` option: ``on_push`` and ``on_push_ctx`` are not allowed, but
531+
the messages can be seen by calling ``pairs()`` in a loop.
532+
533+
Situation 2 complication: ``pairs()`` is subject to timeout. So there
534+
is an optional argument = timeout per iteration. If timeout occurs before
535+
there is a new message or a final response, there is an error return.
536+
To check for an error a one can use the first loop parameter (if the loop
537+
starts with "for i, message in future:pairs()" then the first loop parameter
538+
is i). If it is box.NULL then the second parameter (in our example, "message")
539+
is the error object.
540+
541+
** Example **
542+
543+
.. code-block:: lua
544+
545+
-- Make two shells. On Shell#1 set up a "server", and
546+
-- in it have a function that includes box.session.push:
547+
box.cfg{listen=3301}
548+
box.schema.user.grant('guest','read,write,execute','universe')
549+
x = 0
550+
fiber = require('fiber')
551+
function server_function() x=x+1; fiber.sleep(1); box.session.push(x); end
552+
553+
-- On Shell#2 connect to this server as a "client" that
554+
-- can handle Lua (such as another Tarantool server operating
555+
-- as a client), and initialize a table where we'll get messages:
556+
net_box = require('net.box')
557+
conn = net_box.connect(3301)
558+
messages_from_server = {}
559+
560+
-- On Shell#2 remotely call the server function and receive
561+
-- a SYNCHRONOUS out-of-band message:
562+
conn:call('server_function', {},
563+
{is_async = false,
564+
on_push = table.insert,
565+
on_push_ctx = messages_from_server})
566+
messages_from_server
567+
-- After a 1-second pause that is caused by the fiber.sleep()
568+
-- request inside server_function, the result in the
569+
-- messages_from_server table will be: 1. Like this:
570+
-- tarantool> messages_from_server
571+
-- ---
572+
-- - - 1
573+
-- ...
574+
-- Good. That shows that box.session.push(x) worked,
575+
-- because we know that x was 1.
576+
577+
-- On Shell#2 remotely call the same server function and
578+
-- get an ASYNCHRONOUS out-of-band message. For this we cannot
579+
-- use on_push and on_push_ctx options, but we can use pairs():
580+
future = conn:call('server_function', {}, {is_async = true})
581+
messages = {}
582+
keys = {}
583+
for i, message in future:pairs() do
584+
table.insert(messages, message) table.insert(keys, i) end
585+
messages
586+
future:wait_result(1000)
587+
for i, message in future:pairs() do
588+
table.insert(messages, message) table.insert(keys, i) end
589+
messages
590+
-- There is no pause because conn:call does not wait for
591+
-- server_function to finish. The first time that we go through
592+
-- the pairs() loop, we see the messages table is empty. Like this:
593+
-- tarantool> messages
594+
-- ---
595+
-- - - 2
596+
-- - []
597+
-- ...
598+
-- That is okay because the server hasn't yet called
599+
-- box.session.push(). The second time that we go through
600+
-- the pairs() loop, we see the value of x at the time of
601+
-- the second call to box.session.push(). Like this:
602+
-- tarantool> messages
603+
-- ---
604+
-- - - 2
605+
-- - &0 []
606+
-- - 2
607+
-- - *0
608+
-- ...
609+
-- Good. That shows that the message was asynchronous, and
610+
-- that box.session.push() did its job.

doc/1.10/dev_guide/box_protocol.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ We list them here too:
125125
<join> ::= 0x41
126126
<subscribe> ::= 0x42
127127
<request_vote> ::= 0x43
128-
128+
-- box.session.push's out-of-band message
129+
<chunk> ::= 0x80
129130
-- -- Value for <code> key in response can be:
130131
<OK> ::= 0x00
131132
<ERROR> ::= 0x8XXX

doc/1.10/reference/reference_lua/net_box.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ Most ``net.box`` methods allow a final ``{options}`` argument, which can be:
4242
* ``{is_async=...}``. For example, a method whose final argument is
4343
``{is_async=true}`` will not wait for the result of a request. See the
4444
:ref:`is_async <net_box-is_async>` description.
45+
* ``{on_push=... on_push_ctx=...}``. For receiving out-of-band messages.
46+
See the :ref:`box.session.push <box_session-push>` description.
4547

4648
The diagram below shows possible connection states and transitions:
4749

0 commit comments

Comments
 (0)