forked from goodboy/tractor
1
0
Fork 0

Add context examples

contexts
Tyler Goodlet 2019-01-21 11:38:09 -05:00
parent b6cc1e8c22
commit 276782eb45
1 changed files with 38 additions and 17 deletions

View File

@ -42,6 +42,9 @@ down. A great place to start is the `trio docs`_ and this `blog post`_.
.. _modern async Python: https://www.python.org/dev/peps/pep-0525/ .. _modern async Python: https://www.python.org/dev/peps/pep-0525/
.. contents:: Table of Contents
Philosophy Philosophy
---------- ----------
``tractor``'s tenets non-comprehensively include: ``tractor``'s tenets non-comprehensively include:
@ -560,21 +563,20 @@ The ``name`` value you should pass to ``find_actor()`` is the one you passed as
*first* argument to either ``tractor.run()`` or ``ActorNursery.start_actor()``. *first* argument to either ``tractor.run()`` or ``ActorNursery.start_actor()``.
Streaming and using channels and contexts Streaming using channels and contexts
----------------------------------------- -------------------------------------
A ``Channel`` is the API which wraps an underlying *transport* and *interchange* ``Channel`` is the API which wraps an underlying *transport* and *interchange*
format to support *inter-actor-communication* (IAC). In its present state ``tractor`` format to enable *inter-actor-communication*. In its present state ``tractor``
uses TCP and msgpack_ but hopefully more alternatives in the future. uses TCP and msgpack_.
If you aren't fond of having to write an async generator to stream data If you aren't fond of having to write an async generator to stream data
between actors (or need something more flexible) you can instead use a between actors (or need something more flexible) you can instead use a
``Context``. A context wraps an actor-local spawned task and a ``Channel`` ``Context``. A context wraps an actor-local spawned task and a ``Channel``
so that tasks executing across multiple processes can stream data so that tasks executing across multiple processes can stream data
to one another using a low level, request oriented, API. to one another using a low level, request oriented API.
As an example if you wanted to create a streaming server without writing As an example if you wanted to create a streaming server without writing
an async generator that *yields* values (which are implicitly an async generator that *yields* values you instead define an async
shipped over a channel to the caller) you instead define an async
function: function:
.. code:: python .. code:: python
@ -593,16 +595,35 @@ function:
All that's required is declaring a ``ctx`` argument name somewhere in All that's required is declaring a ``ctx`` argument name somewhere in
your function signature and ``tractor`` will treat the async function your function signature and ``tractor`` will treat the async function
like async generator as a streaming function on the client task's side. like an async generator - as a streaming function from the client side.
As you can imagine, this turns out to be handy particularly if you have This turns out to be handy particularly if you have
multiple tasks streaming responses concurrently. multiple tasks streaming responses concurrently:
The context idea comes from the `protocol context`_ in nanomsg_. .. code:: python
It allows you to perfom IPC in a task or protocol specific way.
async def streamer(ctx, url, rate=2):
"""A simple web response streaming server.
"""
while True:
val = await web_request(url)
# this is the same as ``yield`` in the async gen case
await ctx.send_yield(val)
await trio.sleep(1 / rate)
Running actors standalone (without spawning) async def stream_multiple_sources(ctx, sources):
-------------------------------------------- async with trio.open_nursery() as n:
for url in sources:
n.start_soon(streamer, ctx, url)
The context notion comes from the context_ in nanomsg_.
Running actors standalone
-------------------------
You don't have to spawn any actors using ``open_nursery()`` if you just You don't have to spawn any actors using ``open_nursery()`` if you just
want to run a single actor that connects to an existing cluster. want to run a single actor that connects to an existing cluster.
All the comms and arbiter registration stuff still works. This can All the comms and arbiter registration stuff still works. This can
@ -654,8 +675,8 @@ say hi, please feel free to ping me on the `trio gitter channel`_!
.. _supervisors: https://github.com/tgoodlet/tractor/issues/22 .. _supervisors: https://github.com/tgoodlet/tractor/issues/22
.. _nanomsg: https://github.com/tgoodlet/tractor/issues/19 .. _nanomsg: https://nanomsg.github.io/nng/index.html
.. _nng context: https://github.com/tgoodlet/tractor/issues/19 .. _context: https://nanomsg.github.io/nng/man/tip/nng_ctx.5
.. _gossip protocol: https://en.wikipedia.org/wiki/Gossip_protocol .. _gossip protocol: https://en.wikipedia.org/wiki/Gossip_protocol
.. _trio gitter channel: https://gitter.im/python-trio/general .. _trio gitter channel: https://gitter.im/python-trio/general
.. _celery: http://docs.celeryproject.org/en/latest/userguide/debugging.html .. _celery: http://docs.celeryproject.org/en/latest/userguide/debugging.html