From 7efb7da3001fd76e936ccde5683dac70a140a729 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 2 Nov 2021 15:08:20 -0400 Subject: [PATCH 1/5] Start a hot tips for devs doc --- docs/dev_tips.rst | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 docs/dev_tips.rst diff --git a/docs/dev_tips.rst b/docs/dev_tips.rst new file mode 100644 index 0000000..96ded0c --- /dev/null +++ b/docs/dev_tips.rst @@ -0,0 +1,40 @@ +Hot tips for ``tractor`` hackers +================================ + +This is a WIP guide for newcomers to the project mostly to do with +dev, testing, CI and release gotchas, reminders and best practises. + +``tractor`` is a fairly novel project compared to most since it is +effectively a new way of doing distributed computing in Python and is +much closer to working with an "application level runtime" (like erlang +OTP or scala's akka project) then it is a traditional Python library. +As such, having an arsenal of tools and recipes for figuring out the +right way to debug problems when they do arise is somewhat of +a necessity. + + +Making a Release +---------------- +We currently do nothing special here except the traditional +PyPa release recipe as in `documented by twine`_. I personally +create sub-dirs within the generated `dist/` with an explicit +release name such as `alpha3/` when there's been a sequence of +releases I've made, but it really is up to you how you like to +organize generated sdists locally. + + +.. _documented by twine: https://twine.readthedocs.io/en/latest/#using-twine + + +Debugging and monitoring actor trees +------------------------------------ +TODO: but there are tips in the readme for some terminal commands +which can be used to see the process trees easily on Linux. + + +Using the log system to trace `trio` task flow +---------------------------------------------- +TODO: the logging system is meant to be oriented around +stack "layers" of the runtime such that you can track +"logical abstraction layers" in the code such as errors, cancellation, +IPC and streaming, and the low level transport and wire protocols. From 4cbb8641de12474db9f2f4c157833b5a08f65e07 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 2 Nov 2021 15:37:36 -0400 Subject: [PATCH 2/5] Add an `open_actor_cluster()` usage example --- examples/quick_cluster.py | 50 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 examples/quick_cluster.py diff --git a/examples/quick_cluster.py b/examples/quick_cluster.py new file mode 100644 index 0000000..7ced773 --- /dev/null +++ b/examples/quick_cluster.py @@ -0,0 +1,50 @@ +from functools import partial + +import trio +import tractor + + +async def sleepy_jane(): + uid = tractor.current_actor().uid + print(f'Yo i am actor {uid}') + await trio.sleep_forever() + + +async def main(): + ''' + Spawn a flat actor cluster, with one process per + detected core. + + ''' + portal_map: dict[str, tractor.Portal] + results: dict[str, str] + + # look at this hip new syntax! + async with ( + + tractor.open_actor_cluster( + modules=[__name__] + ) as portal_map, + + trio.open_nursery() as n, + ): + + for (name, portal) in portal_map.items(): + n.start_soon( + partial( + portal.run, + sleepy_jane, + ) + ) + + await trio.sleep(0.5) + + # kill the cluster with a cancel + raise KeyboardInterrupt + + +if __name__ == '__main__': + try: + trio.run(main) + except KeyboardInterrupt: + pass From 74f460eba7429ab6e69004db4dea0bffc6b341d3 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 2 Nov 2021 15:40:15 -0400 Subject: [PATCH 3/5] Make auto generated child names . --- tractor/_clustering.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tractor/_clustering.py b/tractor/_clustering.py index 6d7e7c8..41aaabf 100644 --- a/tractor/_clustering.py +++ b/tractor/_clustering.py @@ -38,7 +38,7 @@ async def open_actor_cluster( uid = tractor.current_actor().uid async def _start(name: str) -> None: - name = f'{name}.{uid}' + name = f'{uid[0]}.{name}' portals[name] = await an.start_actor( enable_modules=modules, name=name, From 94a6fefedebf77d0b285ddc8ac4ed764e6a2accb Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 2 Nov 2021 15:42:19 -0400 Subject: [PATCH 4/5] Add `open_actor_cluster()` eg. to readme --- docs/README.rst | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/docs/README.rst b/docs/README.rst index 15abc89..0d474fd 100644 --- a/docs/README.rst +++ b/docs/README.rst @@ -313,9 +313,69 @@ real time:: This uses no extra threads, fancy semaphores or futures; all we need is ``tractor``'s IPC! +To be extra terse the ``tractor`` devs have started hacking some "higher +level" APIs for managing actor trees/clusters. These interfaces should +generally be condsidered provisional for now but we encourage you to try +them and provide feedback. Here's a new API that let's you quickly +spawn a flat cluster: + +.. code:: python + + from functools import partial + + import trio + import tractor + + + async def sleepy_jane(): + uid = tractor.current_actor().uid + print(f'Yo i am actor {uid}') + await trio.sleep_forever() + + + async def main(): + ''' + Spawn a flat actor cluster, with one process per + detected core. + + ''' + portal_map: dict[str, tractor.Portal] + results: dict[str, str] + + # look at this hip new syntax! + async with ( + + tractor.open_actor_cluster( + modules=[__name__] + ) as portal_map, + + trio.open_nursery() as n, + ): + + for (name, portal) in portal_map.items(): + n.start_soon( + partial( + portal.run, + sleepy_jane, + ) + ) + + await trio.sleep(0.5) + + # kill the cluster with a cancel + raise KeyboardInterrupt + + + if __name__ == '__main__': + try: + trio.run(main) + except KeyboardInterrupt: + pass + .. _full worker pool re-implementation: https://github.com/goodboy/tractor/blob/master/examples/parallelism/concurrent_actors_primes.py + Install ------- From PyPi:: From 546e1b2fa3040de436e81f8e134d6fffb5e0d1d2 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Thu, 4 Nov 2021 10:41:25 -0400 Subject: [PATCH 5/5] Drop unecessary partial --- docs/README.rst | 9 +-------- examples/quick_cluster.py | 8 +------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/docs/README.rst b/docs/README.rst index 0d474fd..842cbcd 100644 --- a/docs/README.rst +++ b/docs/README.rst @@ -321,8 +321,6 @@ spawn a flat cluster: .. code:: python - from functools import partial - import trio import tractor @@ -353,12 +351,7 @@ spawn a flat cluster: ): for (name, portal) in portal_map.items(): - n.start_soon( - partial( - portal.run, - sleepy_jane, - ) - ) + n.start_soon(portal.run, sleepy_jane) await trio.sleep(0.5) diff --git a/examples/quick_cluster.py b/examples/quick_cluster.py index 7ced773..ca692a9 100644 --- a/examples/quick_cluster.py +++ b/examples/quick_cluster.py @@ -1,4 +1,3 @@ -from functools import partial import trio import tractor @@ -30,12 +29,7 @@ async def main(): ): for (name, portal) in portal_map.items(): - n.start_soon( - partial( - portal.run, - sleepy_jane, - ) - ) + n.start_soon(portal.run, sleepy_jane) await trio.sleep(0.5)