doc: improve multicall documentation

Rewrite our multicall documentation to use the active voice, clarify
examples, and steer users more strongly towards the newer
MultiCallSession class.
This commit is contained in:
Ken Dreyer 2022-01-25 12:16:16 -05:00
parent e029d4c489
commit 94ea0a4909

View file

@ -182,80 +182,83 @@ receives status on a task. That is the return value.
Using multicall
~~~~~~~~~~~~~~~
Koji supports a multicall feature where many calls are passed to the
server wrapped as a single call. This can reduce the overhead when a
large number of related calls need to be made.
Koji supports XML-RPC multicalls. Clients can send multiple calls to a hub in
a single request. This is a faster and more efficient way to make many
related calls, and it reduces overhead on the client and server.
The ``ClientSession`` class provides support for this and there are several
examples in the existing client code. Some examples in the cli include:
``edit-host``, ``add-pkg``, ``disable-host``, and ``list-hosts``.
There are two ways to use multicall.
The original modal method works within the ``ClientSession`` object and
prevents making other normal calls until the multicall is completed.
The newer method uses a separate ``MultiCallSession`` object and is much
more flexible.
**Using MultiCallSession**
Note: this feature was added in Koji version 1.18.
A ``MultiCallSession`` object is used to track an individual multicall attached
to a session.
To create one, you can simply call your session's ``multicall`` method.
Once created, the object can be used like a session, but calls are stored
rather than sent immediately.
The stored calls are executed by calling the ``call_all()`` method.
Koji tracks individual muticalls for a session with a ``MultiCallSession``
object. To create one, call your session's ``multicall()`` method. Use this
object like a session, but it will store calls rather than sending
immediately. To execute the calls, call the ``call_all()`` method.
::
task_ids_to_cancel = [123, 456, 789]
m = session.multicall()
for task_id in mylist:
for task_id in task_ids_to_cancel:
m.cancelTask(task_id)
m.call_all()
This object can also be used as a context manager, so the following is
equivalent:
::
Alternatively, you can use this as a context manager. The following is
equivalent::
task_ids_to_cancel = [123, 456, 789]
with session.multicall() as m:
for task_id in mylist:
for task_id in task_ids_to_cancel:
m.cancelTask(task_id)
Method calls to a ``MultiCallSession`` object return a ``VirtualCall`` object
that stands in for the result.
Once the multicall is executed, the result of each call can be accessed via
the ``result`` property of the ``VirtualCall`` object.
Accessing the ``result`` property before the call is executed will result in
an error.
When the context manager exits, the client sends the multicall to the hub
(implicitly executing ``call_all()``).
::
Another example, getting a list of tag names from ids::
with session.multicall() as m:
tags = [m.getTag(tag_id) for tag_id in mylist]
tags = [m.getTag(tag_id) for tag_id in my_tag_ids]
for tag in tags:
print(tag.result['name'])
There are two parameters affecting the behavior of the multicall.
If the ``strict`` parameter is set to True, the multicall will raise the first
error it encounters, if any.
If the ``batch`` parameter is set to a number greater than zero, the multicall
will spread the calls across multiple multicall batches of at most that number.
These parameters may be passed when the ``MultiCallSession`` is initialized,
or they may be passed to the ``call_all`` method.
Each method you call on a ``MultiCallSession`` object will return a
``VirtualCall`` object that stands in for the result.
Once you send the multicall and the hub executes it, you can access the result
of each call via the ``result`` property on each ``VirtualCall`` object. (You
must execute the call before accessing the ``.result`` property, or
``VirtualCall`` will raise an exception.)
::
Two parameters affect the behavior of the multicall.
* If the ``strict`` parameter is set to ``True``, the multicall will raise the
first error it encounters, if any.
* If the ``batch`` parameter is set to a number greater than zero, the
multicall will spread the calls across multiple multicall batches of at most
that number.
You may pass these parameters to the ``call_all()`` method, or you may pass
them when you initialize ``MultiCallSession``::
with session.multicall(strict=True, batch=500) as m:
builds = [m.getBuild(build_id) for build_id in mylist]
**Using ClientSession.multiCall**
**Deprecated: Using ClientSession.multiCall**
Note: this approach is still supported, but we highly recommend using
``MultiCallSession`` as described above, unless you need to support Koji
versions prior to 1.18.
.. note::
This section describes the old (modal) way to make multicalls in Koji: set
the ``.multicall`` property to ``True`` and call the ``.multiCall()``
method on the ``ClientSession`` object. You cannot make other normal calls
until you complete the multicall with ``.multiCall()``.
Please switch your code to use the newer ``multicall()`` pattern described
above. Only use this older-style code pattern if you must support Koji
versions prior to 1.18.
To use the feature, you first set the ``multicall`` attribute of the session
to ``True``. Once this is done, the session will not immediately process