From 339037e22866e55f2f1847a725d22b3f356c75c7 Mon Sep 17 00:00:00 2001 From: Micah Lyle Date: Sun, 9 May 2021 18:00:43 -0700 Subject: [PATCH 01/14] Initial CEP draft for Jumpstarter. Very WIP with lots of TODOs --- draft/jumpstarter.rst | 218 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 draft/jumpstarter.rst diff --git a/draft/jumpstarter.rst b/draft/jumpstarter.rst new file mode 100644 index 0000000..3b78fa0 --- /dev/null +++ b/draft/jumpstarter.rst @@ -0,0 +1,218 @@ +.. vale off + +====================== +CEP XXXX: Jumpstarter +====================== + +:CEP: XXXX +:Author: Micah Lyle +:Implementation Team: Omer Katz +:Shepherd: Omer Katz +:Status: Draft +:Type: Feature +:Created: 2021-05-09 +:Last-Modified: 2021-05-09 + +.. contents:: Table of Contents + :depth: 3 + :local: + +Abstract +======== + +`Next-Gen Celery`_ aims to: + +1. Move Celery from the past to the present. + +2. Resolve long-standing design bugs in our implementation. + +3. Modernize the code to support Python3+. + +4. Do a number of other things not entirely in the scope of this document (see `Next Gen Rationale`_). + +Before work is to begin on this next generation of Celery, it's crucial to have +a discussion about and carve out the building blocks that will form the +primitives for the upcoming Celery. These building blocks should fulfill 1, 2, +and 3 (especially) above, and also help fulfill the goals from the linked +`Next-Gen Rationale`_. + +For Celery to move forward into the modern age, and the future of computing +with increasingly decentralized systems, it's important for Celery to follow a +standardized asynchronous execution model. Namely, we want to define things +like: + +1. How does Celery interact with itself (its own internal components)? + +2. How does Celery interact with others (and how do others interact with it)? + +3. How do Celery's internal components interact with each other and their outside environment? + +Also, we want Celery to work with the emerging and maturing asynchronous python +landscape. Celery is *very asynchronous* by nature, dealing with brokers, +queues, results, timeouts, chord-like joins, task groups, you name it. +Modern asynchronous python frameworks have provided new, innovative, and robust +solutions to many things that overlap with Celery's goals. + +To do all of this, we propose modeling next-gen Celery off of the `Actor Model`_. Namely, +we propose that the Celery Worker will be modeled as an `Actor System`_ of sorts. + +By the end of this initial implementation, we should have a proposal and reference implementation that: + +1. Models Tasks and other key Celery primitives (some to be implemented and +further specced-out down the line) as Actors. + +2. Can give a clear overview about how these various Celery primitives (as +Actors) communicate with each other and pass messages (referencing the Actor +model). + +3. Can enable the development of a future version of Celery where it can be run +embedded with ``async/await`` (if desired by the programmer, not necessary), +and can have synchronous-friendly workers and asynchronous-friendsly/purely +asynchronous workers. + + +Specification +============= + +TODO + +This section should contain a complete, detailed technical specification should +describe the syntax and semantics of any new feature. The specification should +be detailed enough to allow implementation -- that is, developers other than the +author should (given the right experience) be able to independently implement +the feature, given only the CEP. + +Motivation +========== + +TODO (WIP) + +This section should explain *why* this CEP is needed. The motivation is critical +for CEPs that want to add substantial new features or materially refactor +existing ones. It should clearly explain why the existing solutions are +inadequate to address the problem that the CEP solves. CEP submissions without +sufficient motivation may be rejected outright. + +Let's start with an example, and then generalize. A quick search in Celery's +GitHub issue tracker for `chord +`_ shows +a many issues. A number of them (of which some have been fixed) involve complex +cases involving non-trivial Celery workflows. While fixes have been released +over time as these have come up, many issues stand unresolved to this day. The +Celery team could continue to try and fix these issues, or we could take a look +back and think about how we want to design Celery for the future. although +there have been a number of difficulties with getting started on fixing these +issues in the first place! I'll try and list some of what I see these to be: + +1. Celery has had to support, for a long time, both Python 2 and Python 3. +While the codebase has been modernized to a degree with Python 3 nowadays, it +wasn't originally conceived or written that way. It was built back in the +Python 2 days, and had (and still continues to have), a number of features and +ideas. It was (and still is), incredibly pluggible, and supports a number of +use cases and very high throughout if configured correctly. However, Python as +a language has changed significantly in the last 10 years. Namely, proper +support for coroutines in the form of `async/await`. + +2. Celery, as a whole, involves a number of different working parts that are +integrated together. In the current scheme of things, we have workers, brokers, +result stores, workflows (``canvas`` primitives), rate limiting, policies, +signatures, settings, periodic tasks, scheduling, ..., and many other things. +Many of the primitives for these integrated parts were built almost a decade +ago, when both the language landscape (as mentioned above), but also the +*library landscape* was quite a bit different than today. Celery came with a +custom CLI parser, custom event loop implementation (which it still has at the +time of writing), and support for a number of other things that are today +implemented in multiple different solid third party libraries. + +3. Given the complexity of the mentioned issues, it's not easy to get to the +root cause of what's happening in the first place. Because Celery is very +*asynchronous* by nature, many of the tests are wrapped with a ``flaky`` +decorator which means, sometimes (depending on the arrival of messages, speed +of IPC, speed of the network, and many other factors), maybe the test won't +pass in an expected amount of time or might not always succeed. Testing and +modeling asynchronous processes is definitely not easy, but the python +language, tooling, and libraries have evolved considerably in the last +*decade*, and Celery is well positioned for a large restructuring that allows +it both internally take advantage of the latest Python features, and also +provide external integration with them as well. + +With all of these mentioned, and given the chord example, again, we could +continue to try and improve and fix things as is, or we could take a step back +and reflect as to *why* there are so many subleties and quirks with the +implementation. I think one of the ultimate reasons boils down to a lack of +simplicity. In Celery, certain aspects of the codebase are responsible for +a number of things... + +^ TODO: I want to elborate on this more, but I'm not sure if it's appropriate. +I think the Actor Model and modeling the worker as an Actor System gives us a +number of benefits, which I want to succintly summarize in the beginning and +give a lot more detail as a part of the CEP. Specifically, I'd like to +explain/say why modeling things as an Actor system will make Celery a lot +easier to reason about, maintain, and add new, for example, Canvas primitives +to (or even re-build/design them, etc. if that's something that's desired). +There are clear advantages to keeping state internal to the worker, for +example, adding cancel groups, and other things that make some of the more +asynchronous parts of Celery easier to work with, test, and reason about. The +main thing also, though, is to really separate concerns and responsibilities. +It *seems* to me that some of the current Celery code is not very SRP, in the +sense that it's responsible for calling code at a number of different layers +and doing a number of complex things. With the actor system, each actor gets a +lot more specialized and I think that makes the implementation a lot easier to +both reason about and extend. Composition (vs., for example, inheritance +currently present with ``Signature`` objects for example to then create the +canvas objects) then becomes a lot more attractive and possible. To give an +example, a ``chord`` then simply becomes responsible for passing a message to +the underlying ``Task`` (s) or ``result`` (s) (to define more) that would +essentially make them then send off another "message" (we'll call it right now) +or messages to other components in the actor system that are then responsible +for handling that message (think of ``on_chord_part_return`` here). + + + +Rationale +========= + +TODO + +This section should flesh out the specification by describing what motivated +the specific design design and why particular design decisions were made. It +should describe alternate designs that were considered and related work. + +The rationale should provide evidence of consensus within the community and +discuss important objections or concerns raised during discussion. + +Backwards Compatibility +======================= + +TODO + +If this CEP introduces backwards incompatibilities, you must must include this +section. It should describe these incompatibilities and their severity, and what +mitigation you plan to take to deal with these incompatibilities. + +Reference Implementation +======================== + +The `Reference Implementation`_ has a nice sketch of how actors might look in +`Jumpstarter`_. Some of the kinks and details are still being worked out, but +that's the place to go and start taking a look at the time of writing. Further +buildout of certain aspects of the reference implementation (which are also +related to `Celery Next-Gen`_) may be blocked or waiting on some third-party +library support. One example is we're waiting for an `APScheduler 4.0 +Release`_. + +Copyright +========= + +This document has been placed in the public domain per the Creative Commons +CC0 1.0 Universal license (https://creativecommons.org/publicdomain/zero/1.0/deed). + +(All CEPs must include this exact copyright statement.) + +.. Next-Gen Celery https://github.com/celery/ceps/blob/master/draft/high-level-architecture.rst +.. Jumpstarter https://github.com/celery/jumpstarter +.. Reference Implementation https://github.com/celery/jumpstarter/tree/actor +.. AP Scheduler 4.0 Release https://github.com/agronholm/apscheduler/issues/465 +.. Next-Gen Rationale https://github.com/celery/ceps/blob/master/draft/high-level-architecture.rst#rationale +.. Actor Model https://en.wikipedia.org/wiki/Actor_model +.. Actor System https://doc.akka.io/docs/akka/current/general/actor-systems.html From 34bfa0479266a14000713d0743d3b883c1987ff9 Mon Sep 17 00:00:00 2001 From: Micah Lyle Date: Sun, 6 Jun 2021 10:53:59 -0700 Subject: [PATCH 02/14] Update draft/jumpstarter.rst Co-authored-by: Omer Katz --- draft/jumpstarter.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draft/jumpstarter.rst b/draft/jumpstarter.rst index 3b78fa0..23a201b 100644 --- a/draft/jumpstarter.rst +++ b/draft/jumpstarter.rst @@ -26,7 +26,7 @@ Abstract 2. Resolve long-standing design bugs in our implementation. -3. Modernize the code to support Python3+. +3. Modernize the code to use the all latest Python 3+ idioms and best practices. 4. Do a number of other things not entirely in the scope of this document (see `Next Gen Rationale`_). From ce78fd811db3afdd3a0ca8dba7ddf70d78d675dd Mon Sep 17 00:00:00 2001 From: Micah Lyle Date: Sun, 6 Jun 2021 10:54:09 -0700 Subject: [PATCH 03/14] Update draft/jumpstarter.rst Co-authored-by: Omer Katz --- draft/jumpstarter.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draft/jumpstarter.rst b/draft/jumpstarter.rst index 23a201b..7364799 100644 --- a/draft/jumpstarter.rst +++ b/draft/jumpstarter.rst @@ -49,7 +49,7 @@ like: Also, we want Celery to work with the emerging and maturing asynchronous python landscape. Celery is *very asynchronous* by nature, dealing with brokers, -queues, results, timeouts, chord-like joins, task groups, you name it. +queues, results, timeouts, chord-like joins, task groups, etc. Modern asynchronous python frameworks have provided new, innovative, and robust solutions to many things that overlap with Celery's goals. From 709b7c0e9bbdda02eaf478dc4a9530865e2dfd49 Mon Sep 17 00:00:00 2001 From: Micah Lyle Date: Sun, 6 Jun 2021 10:54:17 -0700 Subject: [PATCH 04/14] Update draft/jumpstarter.rst Co-authored-by: Omer Katz --- draft/jumpstarter.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draft/jumpstarter.rst b/draft/jumpstarter.rst index 7364799..78f3515 100644 --- a/draft/jumpstarter.rst +++ b/draft/jumpstarter.rst @@ -50,7 +50,7 @@ like: Also, we want Celery to work with the emerging and maturing asynchronous python landscape. Celery is *very asynchronous* by nature, dealing with brokers, queues, results, timeouts, chord-like joins, task groups, etc. -Modern asynchronous python frameworks have provided new, innovative, and robust +Modern asynchronous Python frameworks have provided new, innovative, and robust solutions to many things that overlap with Celery's goals. To do all of this, we propose modeling next-gen Celery off of the `Actor Model`_. Namely, From af3ef492e68dfb2ac8ef07f90f4ba2e8c83dafa5 Mon Sep 17 00:00:00 2001 From: Micah Lyle Date: Sun, 6 Jun 2021 18:42:54 -0700 Subject: [PATCH 05/14] Next draft of Jumpstarter (draft 2) --- draft/jumpstarter-prev-draft.rst | 219 ++++++++++++++++++++++++++ draft/jumpstarter.rst | 257 ++++++++++++++----------------- 2 files changed, 337 insertions(+), 139 deletions(-) create mode 100644 draft/jumpstarter-prev-draft.rst diff --git a/draft/jumpstarter-prev-draft.rst b/draft/jumpstarter-prev-draft.rst new file mode 100644 index 0000000..0eefad9 --- /dev/null +++ b/draft/jumpstarter-prev-draft.rst @@ -0,0 +1,219 @@ +.. vale off + +====================== +CEP XXXX: Jumpstarter +====================== + +:CEP: XXXX +:Author: Micah Lyle +:Implementation Team: Omer Katz +:Shepherd: Omer Katz +:Status: Draft +:Type: Feature +:Created: 2021-05-09 +:Last-Modified: 2021-05-09 + +.. contents:: Table of Contents + :depth: 3 + :local: + +Abstract +======== + +`Next-Gen Celery`_ aims to: + +1. Move Celery from the past to the present. + +2. Resolve long-standing design bugs in our implementation. + +3. Modernize the code to use the all latest Python 3+ idioms and best practices. + +4. Do a number of other things not entirely in the scope of this document (see `Next Gen Rationale`_). + +Before work is to begin on this next generation of Celery, it's crucial to have +a discussion about and carve out the building blocks that will form the +primitives for the upcoming Celery. These building blocks should fulfill 1, 2, +and 3 (especially) above, and also help fulfill the goals from the linked +`Next-Gen Rationale`_. + +For Celery to move forward into the modern age, and the future of computing +with increasingly decentralized systems, it's important for Celery to follow a +standardized asynchronous execution model. Namely, we want to define things +like: + +1. How does Celery interact with itself (its own internal components)? + +2. How does Celery interact with others (and how do others interact with it)? + +3. How do Celery's internal components interact with each other and their outside environment? + +Also, we want Celery to work with the emerging and maturing asynchronous python +landscape. Celery is *very asynchronous* by nature, dealing with brokers, +queues, results, timeouts, chord-like joins, task groups, you name it. +Modern asynchronous python frameworks have provided new, innovative, and robust +solutions to many things that overlap with Celery's goals. + +To do all of this, we propose modeling next-gen Celery off of the `Actor Model`_. Namely, +we propose that the Celery Worker will be modeled as an `Actor System`_ of sorts. + +By the end of this initial implementation, we should have a proposal and reference implementation that: + +1. Models Tasks and other key Celery primitives (some to be implemented and +further specced-out down the line) as Actors. + +2. Can give a clear overview about how these various Celery primitives (as +Actors) communicate with each other and pass messages (referencing the Actor +model). + +3. Can enable the development of a future version of Celery where it can be run +embedded with ``async/await`` (if desired by the programmer, not necessary), +and can have synchronous-friendly workers and asynchronous-friendsly/purely +asynchronous workers. + + +Specification +============= + +TODO + +This section should contain a complete, detailed technical specification should +describe the syntax and semantics of any new feature. The specification should +be detailed enough to allow implementation -- that is, developers other than the +author should (given the right experience) be able to independently implement +the feature, given only the CEP. + +Motivation +========== + +TODO (WIP) + +This section should explain *why* this CEP is needed. The motivation is critical +for CEPs that want to add substantial new features or materially refactor +existing ones. It should clearly explain why the existing solutions are +inadequate to address the problem that the CEP solves. CEP submissions without +sufficient motivation may be rejected outright. + +Let's start with an example, and then generalize. A quick search in Celery's +GitHub issue tracker for `chord +`_ shows +a many issues. A number of them (of which some have been fixed) involve complex +cases involving non-trivial Celery workflows. While fixes have been released +over time as these have come up, many issues stand unresolved to this day. The +Celery team could continue to try and fix these issues, or we could take a look +back and think about how we want to design Celery for the future. although +there have been a number of difficulties with getting started on fixing these +issues in the first place! I'll try and list some of what I see these to be: + +1. Celery has had to support, for a long time, both Python 2 and Python 3. +While the codebase has been modernized to a degree with Python 3 nowadays, it +wasn't originally conceived or written that way. It was built back in the +Python 2 days, and had (and still continues to have), a number of features and +ideas. It was (and still is), incredibly pluggible, and supports a number of +use cases and very high throughout if configured correctly. However, Python as +a language has changed significantly in the last 10 years. Namely, proper +support for coroutines in the form of `async/await`. + +2. Celery, as a whole, involves a number of different working parts that are +integrated together. In the current scheme of things, we have workers, brokers, +result stores, workflows (``canvas`` primitives), rate limiting, policies, +signatures, settings, periodic tasks, scheduling, ..., and many other things. +Many of the primitives for these integrated parts were built almost a decade +ago, when both the language landscape (as mentioned above), but also the +*library landscape* was quite a bit different than today. Celery came with a +custom CLI parser, custom event loop implementation (which it still has at the +time of writing), and support for a number of other things that are today +implemented in multiple different solid third party libraries. + +3. Given the complexity of the mentioned issues, it's not easy to get to the +root cause of what's happening in the first place. Because Celery is very +*asynchronous* by nature, many of the tests are wrapped with a ``flaky`` +decorator which means, sometimes (depending on the arrival of messages, speed +of IPC, speed of the network, and many other factors), maybe the test won't +pass in an expected amount of time or might not always succeed. Testing and +modeling asynchronous processes is definitely not easy, but the python +language, tooling, and libraries have evolved considerably in the last +*decade*, and Celery is well positioned for a large restructuring that allows +it both internally take advantage of the latest Python features, and also +provide external integration with them as well. + +With all of these mentioned, and given the chord example, again, we could +continue to try and improve and fix things as is, or we could take a step back +and reflect as to *why* there are so many subleties and quirks with the +implementation. I think one of the ultimate reasons boils down to a lack of +simplicity. In Celery, certain aspects of the codebase are responsible for +a number of things... + +^ TODO: I want to elborate on this more, but I'm not sure if it's appropriate. +I think the Actor Model and modeling the worker as an Actor System gives us a +number of benefits, which I want to succintly summarize in the beginning and +give a lot more detail as a part of the CEP. Specifically, I'd like to +explain/say why modeling things as an Actor system will make Celery a lot +easier to reason about, maintain, and add new, for example, Canvas primitives +to (or even re-build/design them, etc. if that's something that's desired). +There are clear advantages to keeping state internal to the worker, for +example, adding cancel groups, and other things that make some of the more +asynchronous parts of Celery easier to work with, test, and reason about. The +main thing also, though, is to really separate concerns and responsibilities. +It *seems* to me that some of the current Celery code is not very SRP, in the +sense that it's responsible for calling code at a number of different layers +and doing a number of complex things. With the actor system, each actor gets a +lot more specialized and I think that makes the implementation a lot easier to +both reason about and extend. Composition (vs., for example, inheritance +currently present with ``Signature`` objects for example to then create the +canvas objects) then becomes a lot more attractive and possible. To give an +example, a ``chord`` then simply becomes responsible for passing a message to +the underlying ``Task`` (s) or ``result`` (s) (to define more) that would +essentially make them then send off another "message" (we'll call it right now) +or messages to other components in the actor system that are then responsible +for handling that message (think of ``on_chord_part_return`` here). + + + +Rationale +========= + +TODO + +This section should flesh out the specification by describing what motivated +the specific design design and why particular design decisions were made. It +should describe alternate designs that were considered and related work. + +The rationale should provide evidence of consensus within the community and +discuss important objections or concerns raised during discussion. + +Backwards Compatibility +======================= + +TODO + +If this CEP introduces backwards incompatibilities, you must must include this +section. It should describe these incompatibilities and their severity, and what +mitigation you plan to take to deal with these incompatibilities. + +Reference Implementation +======================== + +The `Reference Implementation`_ has a nice sketch of how actors might look in +`Jumpstarter`_. Some of the kinks and details are still being worked out, but +that's the place to go and start taking a look at the time of writing. Further +buildout of certain aspects of the reference implementation (which are also +related to `Celery Next-Gen`_) may be blocked or waiting on some third-party +library support. One example is we're waiting for an `APScheduler 4.0 +Release`_. + +Copyright +========= + +This document has been placed in the public domain per the Creative Commons +CC0 1.0 Universal license (https://creativecommons.org/publicdomain/zero/1.0/deed). + +(All CEPs must include this exact copyright statement.) + +.. Next-Gen Celery https://github.com/celery/ceps/blob/master/draft/high-level-architecture.rst +.. Jumpstarter https://github.com/celery/jumpstarter +.. Reference Implementation https://github.com/celery/jumpstarter/tree/actor +.. AP Scheduler 4.0 Release https://github.com/agronholm/apscheduler/issues/465 +.. Next-Gen Rationale https://github.com/celery/ceps/blob/master/draft/high-level-architecture.rst#rationale +.. Actor Model https://en.wikipedia.org/wiki/Actor_model +.. Actor System https://doc.akka.io/docs/akka/current/general/actor-systems.html + diff --git a/draft/jumpstarter.rst b/draft/jumpstarter.rst index 3b78fa0..755d87d 100644 --- a/draft/jumpstarter.rst +++ b/draft/jumpstarter.rst @@ -20,175 +20,143 @@ CEP XXXX: Jumpstarter Abstract ======== -`Next-Gen Celery`_ aims to: +Since Celery was conceived over a decade ago, the Python landscape has evolved +considerably. Of the key recent developments has been the introduction and successive +improvements of Python's ``async/await`` support, with the growing ecosystem surrounding +its asynchronous/concurrent programming paradigm. -1. Move Celery from the past to the present. +When Celery was initially built, it was very innovative and forward/future-thinking for its time. +It had (and still has) its own event loop implementation, and supported top-of-the-line +asynchronous programming models of the time, such as ``gevent`` and ``eventlet``. -2. Resolve long-standing design bugs in our implementation. +Enter the start of the 2020s decade and Python, along with its ``async/await`` ecosystem +has been rapidly growing and thriving, providing a number of advancements improving +Python's asynchronous/concurrent programming model. -3. Modernize the code to support Python3+. +Currently, Celery does not natively support ``async/await``, either with queueing or +waiting on the result of tasks, like ``await some_task.apply_async(...)``, nor the usage +of ``async def`` and ``await`` from within tasks themselves. For example, without using +some custom written code of your own or a newer community-supported project like +`Celery Pool AsyncIO`_, you cannot define a task with ``async def`` nor can your task (because +it's not defined with ``async def``) do something like ``await some_async_fn(...)`` +unless within your task you booted up a modern ``async/await`` compatible event loop or +used some other workaround. -4. Do a number of other things not entirely in the scope of this document (see `Next Gen Rationale`_). +That leads this CEP, whose purpose is to provide a foundational asynchronous programming +framework for the broader Python community modeled after the `Actor Model`_, and also +provide a foundation for `Next-Gen Celery`_ to be built upon. This will, down the line: -Before work is to begin on this next generation of Celery, it's crucial to have -a discussion about and carve out the building blocks that will form the -primitives for the upcoming Celery. These building blocks should fulfill 1, 2, -and 3 (especially) above, and also help fulfill the goals from the linked -`Next-Gen Rationale`_. +1. Allow awaiting on an asynchronous task results: -For Celery to move forward into the modern age, and the future of computing -with increasingly decentralized systems, it's important for Celery to follow a -standardized asynchronous execution model. Namely, we want to define things -like: + .. code-block:: python -1. How does Celery interact with itself (its own internal components)? + await some_task.apply_async(args=(1,2), kwargs={"kwarg1": 3 }) -2. How does Celery interact with others (and how do others interact with it)? +2. Allow definining ``async`` tasks that can utilize ``await``, ``async with``, and all +the other features of Python's ``async/await`` programming model. -3. How do Celery's internal components interact with each other and their outside environment? + .. code-block:: python -Also, we want Celery to work with the emerging and maturing asynchronous python -landscape. Celery is *very asynchronous* by nature, dealing with brokers, -queues, results, timeouts, chord-like joins, task groups, you name it. -Modern asynchronous python frameworks have provided new, innovative, and robust -solutions to many things that overlap with Celery's goals. + @task + async def my_task(...): + x = await some_async_fn1(...) + async with (...): + y = await some_async_fn2(...) -To do all of this, we propose modeling next-gen Celery off of the `Actor Model`_. Namely, -we propose that the Celery Worker will be modeled as an `Actor System`_ of sorts. - -By the end of this initial implementation, we should have a proposal and reference implementation that: +Specification +============= -1. Models Tasks and other key Celery primitives (some to be implemented and -further specced-out down the line) as Actors. +Motivation +========== -2. Can give a clear overview about how these various Celery primitives (as -Actors) communicate with each other and pass messages (referencing the Actor -model). +There are two primary motivations to discuss. + +1. The motivation to build `Jumpstarter`_. + +2. The motivation to, down the line, use `Jumpstarter`_ as a foundation for parts of +`Next-Gen Celery`_. + +For the first motivation, one of Celery's main use cases is to build asynchronous, +distributed systems that communicate via message passing. The `Actor Model`_, which has +been around for almost half a century and is a tried and tested way to design and build +large-scale concurrent systems. It very much matches what Celery aims to do and has +shown to have great success in projects like `Akka`_ and many others. The `Actor Model`_ +also works great with Python's ``async/await`` support as messages are able to be +asynchronously sent and awaited upon very efficiently. + +`Jumpstarter`_ comes in to fill the spot of being that fundamental/primititve library to +build `Next-Gen Celery`_ on top of, while simultaneously being a modern implementation +and interpretation of the `Actor Model`_ (and an `Actor System`_, or at least blocks for +building one) in Python. For reasons why Celery would build its own library instead of +using an existing Actor framework in Python, see the :ref:`Rationale` below. + +For the second motivation, certain bugs and issues in Celery resolve around things like +chord synchronization/counting errors, very hard to reproduce concurrency issues, canvas +edge cases, etc. Looking at these issues from a higher perspective and the current state +of the codebase, future versions of Celery could benefit from code that adheres to +something like the `Actor Model`_, which really helps to eliminate race conditions, +locking issues, shared state issues, and other things like that which are out of the +scope of this document. Modeling workers, tasks, canvas primitives, and other Celery +components after an `Actor System`_ and making them hold to the fundamental axioms of +the `Actor Model`_ will encourage code that is far more Single Responsibility Principle +(SRP) than the current codebase is, and encourage both designs and implementations that +are easier to reason about, easier to test, and easier to extend and work with. The +design of various Celery components using `Jumpstarter`_ primitives is outside of the +scope of this document and would be addressed in future CEPs. -3. Can enable the development of a future version of Celery where it can be run -embedded with ``async/await`` (if desired by the programmer, not necessary), -and can have synchronous-friendly workers and asynchronous-friendsly/purely -asynchronous workers. +Rationale +========= +A quick internet search of Python actor libraries and packages returns a +few different results. Before listing some of those libraries, the main +reasons for building our own `Actor Model`_ implementation are as follows: -Specification -============= +1. We want a framework that is built with and for ``async/await`` from the beginning, and +that takes advantage of all the latest abstractions and innovations in Python's +``async/await`` support and the latest general language features as well (like +``typing`` and other things). Many of the other frameworks listed below were built +either before ``async/await`` or in the earlier stages. -TODO +2. We want something that can be a standalone framework, but that can _also_ be informed by +the needs of `Next-Gen Celery`_. Hence, we'd like for the Celery organization to +maintain and shepherd the project. We may find that we need to make changes rapidly in +the beginning, and we'd like to see the project evolve and grow quickly without being +blocked by other large dependent projects (like some or many of these other libraries +may be), especially in the beginning. By Celery creating a new library, we can both +enable rapid development of `Jumpstarter`_ and `Next-Gen Celery`_ now and down the line, while +still providing a framework that the greater Python community may find helpful to build +other projects off of. -This section should contain a complete, detailed technical specification should -describe the syntax and semantics of any new feature. The specification should -be detailed enough to allow implementation -- that is, developers other than the -author should (given the right experience) be able to independently implement -the feature, given only the CEP. +With that being said, let's take a look at a few existing projects: -Motivation -========== +* `Pykka`_ is a Python-based actor that was extracted originally from `Mopidy`_, an "extensible music server written in Python". We wouldn't use `Pykka`_ for two main reasons: -TODO (WIP) - -This section should explain *why* this CEP is needed. The motivation is critical -for CEPs that want to add substantial new features or materially refactor -existing ones. It should clearly explain why the existing solutions are -inadequate to address the problem that the CEP solves. CEP submissions without -sufficient motivation may be rejected outright. - -Let's start with an example, and then generalize. A quick search in Celery's -GitHub issue tracker for `chord -`_ shows -a many issues. A number of them (of which some have been fixed) involve complex -cases involving non-trivial Celery workflows. While fixes have been released -over time as these have come up, many issues stand unresolved to this day. The -Celery team could continue to try and fix these issues, or we could take a look -back and think about how we want to design Celery for the future. although -there have been a number of difficulties with getting started on fixing these -issues in the first place! I'll try and list some of what I see these to be: - -1. Celery has had to support, for a long time, both Python 2 and Python 3. -While the codebase has been modernized to a degree with Python 3 nowadays, it -wasn't originally conceived or written that way. It was built back in the -Python 2 days, and had (and still continues to have), a number of features and -ideas. It was (and still is), incredibly pluggible, and supports a number of -use cases and very high throughout if configured correctly. However, Python as -a language has changed significantly in the last 10 years. Namely, proper -support for coroutines in the form of `async/await`. - -2. Celery, as a whole, involves a number of different working parts that are -integrated together. In the current scheme of things, we have workers, brokers, -result stores, workflows (``canvas`` primitives), rate limiting, policies, -signatures, settings, periodic tasks, scheduling, ..., and many other things. -Many of the primitives for these integrated parts were built almost a decade -ago, when both the language landscape (as mentioned above), but also the -*library landscape* was quite a bit different than today. Celery came with a -custom CLI parser, custom event loop implementation (which it still has at the -time of writing), and support for a number of other things that are today -implemented in multiple different solid third party libraries. - -3. Given the complexity of the mentioned issues, it's not easy to get to the -root cause of what's happening in the first place. Because Celery is very -*asynchronous* by nature, many of the tests are wrapped with a ``flaky`` -decorator which means, sometimes (depending on the arrival of messages, speed -of IPC, speed of the network, and many other factors), maybe the test won't -pass in an expected amount of time or might not always succeed. Testing and -modeling asynchronous processes is definitely not easy, but the python -language, tooling, and libraries have evolved considerably in the last -*decade*, and Celery is well positioned for a large restructuring that allows -it both internally take advantage of the latest Python features, and also -provide external integration with them as well. - -With all of these mentioned, and given the chord example, again, we could -continue to try and improve and fix things as is, or we could take a step back -and reflect as to *why* there are so many subleties and quirks with the -implementation. I think one of the ultimate reasons boils down to a lack of -simplicity. In Celery, certain aspects of the codebase are responsible for -a number of things... - -^ TODO: I want to elborate on this more, but I'm not sure if it's appropriate. -I think the Actor Model and modeling the worker as an Actor System gives us a -number of benefits, which I want to succintly summarize in the beginning and -give a lot more detail as a part of the CEP. Specifically, I'd like to -explain/say why modeling things as an Actor system will make Celery a lot -easier to reason about, maintain, and add new, for example, Canvas primitives -to (or even re-build/design them, etc. if that's something that's desired). -There are clear advantages to keeping state internal to the worker, for -example, adding cancel groups, and other things that make some of the more -asynchronous parts of Celery easier to work with, test, and reason about. The -main thing also, though, is to really separate concerns and responsibilities. -It *seems* to me that some of the current Celery code is not very SRP, in the -sense that it's responsible for calling code at a number of different layers -and doing a number of complex things. With the actor system, each actor gets a -lot more specialized and I think that makes the implementation a lot easier to -both reason about and extend. Composition (vs., for example, inheritance -currently present with ``Signature`` objects for example to then create the -canvas objects) then becomes a lot more attractive and possible. To give an -example, a ``chord`` then simply becomes responsible for passing a message to -the underlying ``Task`` (s) or ``result`` (s) (to define more) that would -essentially make them then send off another "message" (we'll call it right now) -or messages to other components in the actor system that are then responsible -for handling that message (think of ``on_chord_part_return`` here). + * It doesn't support ``async/await`` currently, and hasn't supported it from the beginning. + * It powers `Mopidy`_, and probably a number of other significant projects rely on it to some extent, so it wouldn't make sense to rely upon it for reasons listed above. +* `Cell`_ was an earlier attempt at an actor model/framework for Celery. It wasn't very widely used and developed. + * Given reason #1 above, it makes sense to archive `Cell`_ and move forward with `Jumpstarter`_ (`comment `_). -Rationale -========= +* `Thespian`_ is a very rich-featured "Python Actor concurrency library." Of all the libraries listed, it would seem the most promising for something to use and/or build off, of, except that: -TODO + * It seems to have been built out before the early ``asyncio`` ``async/await`` phase of Python's development. The ``async/await`` syntax wasn't quite around yet, and libraries like `Curio`_ and `Trio`_ weren't around yet. Python's asynchronous programming model has come a long way since the 3.3/3.4 and early ``asyncio`` days. Along with reason #1 above, we really want to support some of the newer asynchronous ideas (and use them as a base) with `Jumpstarter`_. Given the large size of `Threspian`_'s codebase, it would be very seemingly impractical to try and tweak an aircraft carrier (metaphorically speaking) to fit our use cases. + * The library seems to have been in maintenance mode for the last few years. It was originally built in house at GoDaddy, and the original author does not work there anymore. Scanning the release history shows more maintenance releases than new activity, which, given its large size, possibly external large-project dependencies, and reason #2 above, makes us inclined to still build our own framework. That being said, there may be useful things that can be learned from `Threspian`_, whether high level structure or low level details. -This section should flesh out the specification by describing what motivated -the specific design design and why particular design decisions were made. It -should describe alternate designs that were considered and related work. +* `Pulsar`_ is an "Event driven concurrent" framework for Python. It's goal, according to its README, "is to provide an easy way to build scalable network programs." It was built upon ``asyncio`` from the Python3.5+ days and supports ``async/await``. However, while it has a number of powerful and interesting features, it has been archived by its owner, so discussing it more does not feel necessary for the scope of this document. -The rationale should provide evidence of consensus within the community and -discuss important objections or concerns raised during discussion. + * Additionally, while it does seem to have great support for building generally network connected programs, a number of examples show how to use it to build something like a non-blocking ``wsgi`` server. Celery does intend to handle such use cases, especially given the development of the ``asgi`` specification, and many other modern libraries under current development that are doing a great job with ``asgi``. Similar to what was said about `Thespian`_, there may be useful things that can be learned from `Pulsar`_, but it's not something that we think should be built upon, for similar reasons to `Thespian`_ above, along with our general reasons #1 (``asyncio`` only would not satisfy that) and #2 (`Pulsar`_ seems to have been by and potentially for a group called `Quantmind `_). Backwards Compatibility ======================= -TODO - -If this CEP introduces backwards incompatibilities, you must must include this -section. It should describe these incompatibilities and their severity, and what -mitigation you plan to take to deal with these incompatibilities. +Given that `Jumpstarter`_ is a library being built from scratch, there isn't too much to +talk about on the backwards compatibility side of things. It's an open discussion at the +moment of we should support Python 3.7+ or Python 3.10+. It might be nice, given +``trio``, ``asyncio``, and other ``async/await``/event loop implementation improvements +in the last number of Python versions to rely on 3.10+. And on top of that, we'd get the +latest improvements in the ``typing`` world, and pattern matching that we could use from +the beginning. Reference Implementation ======================== @@ -216,3 +184,14 @@ CC0 1.0 Universal license (https://creativecommons.org/publicdomain/zero/1.0/dee .. Next-Gen Rationale https://github.com/celery/ceps/blob/master/draft/high-level-architecture.rst#rationale .. Actor Model https://en.wikipedia.org/wiki/Actor_model .. Actor System https://doc.akka.io/docs/akka/current/general/actor-systems.html +.. Celery Pool AsyncIO https://github.com/kai3341/celery-pool-asyncio +.. Akka https://akka.io/ +.. Pykka https://github.com/jodal/pykka +.. Mopidy https://github.com/mopidy/mopidy +.. Cell https://github.com/celery/cell +.. Thespian https://github.com/thespianpy/Thespian +.. Pulsar https://github.com/quantmind/pulsar +.. Asyncio https://docs.python.org/3/library/asyncio.html +.. Curio https://github.com/dabeaz/curio +.. Trio https://github.com/python-trio/trio +.. Trio-Asyncio https://github.com/python-trio/trio-asyncio From d45bcc30451f36f33fe5e3d9ed9ca634879e7666 Mon Sep 17 00:00:00 2001 From: Micah Lyle Date: Sun, 6 Jun 2021 18:56:33 -0700 Subject: [PATCH 06/14] Fix Thespian references --- draft/jumpstarter.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/draft/jumpstarter.rst b/draft/jumpstarter.rst index 9cb0946..76927bc 100644 --- a/draft/jumpstarter.rst +++ b/draft/jumpstarter.rst @@ -140,8 +140,8 @@ With that being said, let's take a look at a few existing projects: * `Thespian`_ is a very rich-featured "Python Actor concurrency library." Of all the libraries listed, it would seem the most promising for something to use and/or build off, of, except that: - * It seems to have been built out before the early ``asyncio`` ``async/await`` phase of Python's development. The ``async/await`` syntax wasn't quite around yet, and libraries like `Curio`_ and `Trio`_ weren't around yet. Python's asynchronous programming model has come a long way since the 3.3/3.4 and early ``asyncio`` days. Along with reason #1 above, we really want to support some of the newer asynchronous ideas (and use them as a base) with `Jumpstarter`_. Given the large size of `Threspian`_'s codebase, it would be very seemingly impractical to try and tweak an aircraft carrier (metaphorically speaking) to fit our use cases. - * The library seems to have been in maintenance mode for the last few years. It was originally built in house at GoDaddy, and the original author does not work there anymore. Scanning the release history shows more maintenance releases than new activity, which, given its large size, possibly external large-project dependencies, and reason #2 above, makes us inclined to still build our own framework. That being said, there may be useful things that can be learned from `Threspian`_, whether high level structure or low level details. + * It seems to have been built out before the early ``asyncio`` ``async/await`` phase of Python's development. The ``async/await`` syntax wasn't quite around yet, and libraries like `Curio`_ and `Trio`_ weren't around yet. Python's asynchronous programming model has come a long way since the 3.3/3.4 and early ``asyncio`` days. Along with reason #1 above, we really want to support some of the newer asynchronous ideas (and use them as a base) with `Jumpstarter`_. Given the large size of `Thespian`_'s codebase, it would be very seemingly impractical to try and tweak an aircraft carrier (metaphorically speaking) to fit our use cases. + * The library seems to have been in maintenance mode for the last few years. It was originally built in house at GoDaddy, and the original author does not work there anymore. Scanning the release history shows more maintenance releases than new activity, which, given its large size, possibly external large-project dependencies, and reason #2 above, makes us inclined to still build our own framework. That being said, there may be useful things that can be learned from `Thespian`_, whether high level structure or low level details. * `Pulsar`_ is an "Event driven concurrent" framework for Python. It's goal, according to its README, "is to provide an easy way to build scalable network programs." It was built upon ``asyncio`` from the Python3.5+ days and supports ``async/await``. However, while it has a number of powerful and interesting features, it has been archived by its owner, so discussing it more does not feel necessary for the scope of this document. From 1558f0b0afd4e2e347801b8e62f855d82a52fc80 Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Mon, 7 Jun 2021 18:40:41 +0300 Subject: [PATCH 07/14] Turn vale on. --- draft/jumpstarter.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/draft/jumpstarter.rst b/draft/jumpstarter.rst index 76927bc..c672c20 100644 --- a/draft/jumpstarter.rst +++ b/draft/jumpstarter.rst @@ -1,5 +1,3 @@ -.. vale off - ====================== CEP XXXX: Jumpstarter ====================== From 13d9e88e21b6f637580687e238c9b0d912f09c66 Mon Sep 17 00:00:00 2001 From: Micah Lyle Date: Thu, 24 Jun 2021 17:55:01 -0700 Subject: [PATCH 08/14] WIP Specification --- draft/jumpstarter.rst | 117 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/draft/jumpstarter.rst b/draft/jumpstarter.rst index 76927bc..9c6e9e4 100644 --- a/draft/jumpstarter.rst +++ b/draft/jumpstarter.rst @@ -66,6 +66,115 @@ the other features of Python's ``async/await`` programming model. Specification ============= +Jumpstarter is a Python implementation of an `Actor System`_ (which utilizies the `Actor Model`_). There +are three fundamental axioms within the actor model (quoting the previous Wikipedia link): + +(Start Blockquote) + +An actor is a computational entity that, in response to a message it receives, can _concurrently_ (emphasis ours): + +1. Send a finite number of messages to other actors; +2. Create a finite number of new actors; +3. Designate the behavior to be used for the next message it receives. + +(End Blockquote) + +It's important to remember that, although that is the technical definition of the actor, the interpretation and implementation of Actors and Actor Systems can be very flexible. Namely, what constitutes a "message" and "state" is very much up to the interpretation of the developer(s) and the system(s) they're using. + +In Jumpstarter, we've chosen to take direct/literal approach to 3., modeling the state of an Actor using an actual state machine abstraction, namely a `Hierarchical State Machine`_. The difference between a standard State Machine and a Hierarchical State Machine is that a standard State Machine is consistent from states and transitions between them, but in an Hierarchical State Machine, states can also have their own sub-state machines. Hierarchical State Machines help both tame the complexity of large (non-hierarchical) state machines and more clearly model the relationships and transitions between them. To give an example with Jumpstarter, we propose only a small number of parent states: + +* Initializing --> The initial state of the Actor when created. +* Initialized --> he state of the actor when we start it for the very first time. +* Starting --> The state of the actor immediately after calling ``actor.start()``. We'll have to transition through a number of substates of ``starting`` first (like starting dependencies, acquiring resources, and starting tasks), which we'll explain in more detail below (think of this like powering on a computer. You typically have to wait a few seconds for the computer to set up its internal state nicely before its fully operational. It also needs to connect to internal and external devices, and be ready for operation, etc.). +* Stopping --> The state of the actor immediately after calling ``actor.stop()``. We'll have to transition through a number of substates of ``stopping`` first (like stopping tasks, releasing resources, and stopping dependencies), which we'll explain in more detail below (think of this like powering off a computer. You typically have to wait a few seconds for the computer to clean up its internal state nicely before it can fully shut down). +* Stopped --> The state of the actor after it has finished all of its ``stopping`` activities (think about how when you power off a computer). +* Crashed --> The state of the actor when an exception was raised during startup or shutdown. + +Within those parent states, we have sub-states. For example: + +* Starting + * Dependencies Started --> The state of the actor after all of the actor's dependencies have been started. + * Resources Acquired --> The state of the actor after all resources have been acquired. + * Tasks Started --> The state of the actor after all tasks have been started. +* Started + * Paused --> The state of the actor when all tasks are halted without shutting down the entire actor. + * Running --> The state of the actor when all tasks are running. + * Healthy --> The state of the actor when the actor is functioning properly. + * Degraded --> The state of the actor when the actor is not functioning properly but is still able to perform some of its duties. + * Unhealthy --> The state of the actor when the actor is temporarily not functioning. +* Stopping + * Tasks Stopped --> The state of the actor after all tasks have been started. + * Resources Released --> The state of the actor after all resources have been acquired. + * Dependencies Stopped --> The state of the actor after all of the actor's dependencies have been started. + +In order to effectively model these states in Python, we propose using the mature `transitions`_ library, along with the `transitions-anyio`_ library. This gives us: + +1. Mature Hierarchical State Machine library support thanks to `transitions`_. +2. Asynchronous state machine transitions (opening up abilities for concurrency, parallelization, and the latest ``async/await`` python support that's part of the motivation of this CEP in the first place) with `AnyIO`_ (thanks to `transitions-anyio`_) to abstract away the specific event loop of choice (like `AsyncIO`_, `Trio`_, or potentially others in the future). +3. Native support within `transitions`_ for integrating with ``diagrams``/``graphviz`` to generate state machine diagrams (like the one below). Additionally, `transitions-gui`_ provides some interesting and promising capabilities for future Celery Flower-like projects to be able to visualize in a live, animated fashion the various Jumpstarter Actors and their states as transitions happen across all the various actors within the system. + +For a high level view, the parent states, their substates, and the transitions between them can be seen in the diagram below: + +TODO: Insert Jumpstarter State Machine Diagram Here: https://user-images.githubusercontent.com/48936/107506089-43225a00-6ba6-11eb-810e-0ac14bf0e1e9.png + +Also, in that diagram you can also see the ``Restart`` state. We propose a separate state machine which we'll call *Actor Restart State Machine* that models the Actor's state as it relates to restarts: + +* Ignore --> A special state which is ignored by the Actor (effectively meaning we're not in any sort of restart state). +* Restarting --> The state of the actor once it has begun restarting. + * Stopping --> The state of the actor while stopping during a restart. + * Starting --> The state of the actor while starting during a restart. +* Restarted --> The state of the actor after it has been restarted. + +With these states and sub-states, for both the main state machine and the regular state machine, we provide a clear public API for code to hook into any part of the Actor's Lifecycle. Similar to how, for example, modern asynchronous frontend web frameworks like React and Vue provide hooks into the lifecycle of their components, `transitions`_ provides many different hooks to: + +* Have code run before a transition occurs or a state is entered, or conditionally block a transition from happening if certain conditions aren't met. +* Have code run after a transition occurs (we could use this to, for example, fan out a result right before some hypothetical state ``"task_completed"`` is exited). +* Do many other things at various granularities and moments. See https://github.com/pytransitions/transitions#callback-execution-order for specific details on the order and timing of when specific callbacks are invoked. + +With that base API, Jumpstarter provides a solid foundation and a lot of flexibility to help define self-contained pieces of business logic and facilitate communication between them while maintaining a separation of concerns. + +Three abstractions Jumpstarter provides that are addressed in both the ``starting`` and ``stopping`` states are: + +1. Dependencies +2. Resources +3. Tasks + +Dependencies +------------ +Actors may depend on other actors to run before starting themselves. In some cases, they must depend on another actor if an actor consumes messages from another actor's stream. In `Actor System`_ language, that means that the dependent actor is a parent actor, and the actor consuming messages from the parent actor is the child actor. Just the fact of depending on another actor means that messages will be passed from the parent actor to the child actor (the child actor can also have a way to pass messages back to the parent, but that's out of the scope of this CEP and is something that may be explored as the implementation of Producers and Consumers is more refined). + +The proposed public API is as follows: + +``` +from jumpstarter import Actor, depends_on + +class AccountBalanceActor(Actor): + def __init__(self, user_id: int): + self.user_id = user_id + +class AccountBookkeepingActor(Actor): + def __init__(self, user_id: int, account_balance_actor: AccountBalanceActor): + self._account_balance_actor = account_balance_actor + + @depends_on + def account_balance_actor(self): + return account_balance_actor +``` + +In this example, the ``AccountBalanceActor`` maintains the balance in a single user ID's account. The ``AccountBookkeepingActor`` is responsible for logging and auditing withdrawals and income, possibly passing these audit logs to another actor responsible for detecting fraud. + +Resources +--------- +Actors have resources they manage during their lifetime, such as: +* Connections to databases and message brokers +* File Handles +* Synchronization Mechanisms (useful for short-lived actors) + +A resource can be an asynchronous context manager or a synchronous context manager. It's entered whenever the Actor is ``starting``, specifically just before the state machine transitions to the ``starting -> resources_acquired`` state. +It is exited whenever the Actor is stopping, specifically just before the state machine transitions to the ``starting -> resources_released`` state. Given the asynchronous nature of Jumpstarter, resources can be released concurrently (even if there are synchronous resource releases that are run, say, in a thread pool). Additionally, any and every actor, once resources are acquired, will be have `cancel scope`_ (acquired once ``starting -> resources_acquired`` state has been entered) in the that can be used to shut down the worker or cancel any running task(s), whether because of a timeout, a crash, a restart, or some other reason. Even if the task is run in a thread pool, the `cancel_scope` and fact that the Jumpstarter is running in an event loop means that more robust cancellation of tasks may be possible in future versions of Celery than have been up to this point (see https://vorpus.org/blog/timeouts-and-cancellation-for-humans/ for some helpful background on this). + + + Motivation ========== @@ -191,7 +300,13 @@ CC0 1.0 Universal license (https://creativecommons.org/publicdomain/zero/1.0/dee .. Cell https://github.com/celery/cell .. Thespian https://github.com/thespianpy/Thespian .. Pulsar https://github.com/quantmind/pulsar -.. Asyncio https://docs.python.org/3/library/asyncio.html +.. AsyncIO https://docs.python.org/3/library/asyncio.html .. Curio https://github.com/dabeaz/curio .. Trio https://github.com/python-trio/trio .. Trio-Asyncio https://github.com/python-trio/trio-asyncio +.. Hierarchical State Machine https://www.eventhelix.com/design-patterns/hierarchical-state-machine/ +.. transitions https://github.com/pytransitions/transitions +.. transitions-anyio https://github.com/pytransitions/transitions-anyio +.. transitions-gui https://github.com/pytransitions/transitions-gui +.. AnyIO https://github.com/agronholm/anyio +.. cancel scope https://anyio.readthedocs.io/en/stable/api.html#anyio.CancelScope From bc4349bfa0b8c8cd6e0da4728f86d6d7e74e858a Mon Sep 17 00:00:00 2001 From: Micah Lyle Date: Sun, 27 Jun 2021 09:09:12 -0700 Subject: [PATCH 09/14] Finalizing next draft with Specification, checking formatting --- draft/jumpstarter.rst | 79 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 11 deletions(-) diff --git a/draft/jumpstarter.rst b/draft/jumpstarter.rst index 91aebfb..8feb0cc 100644 --- a/draft/jumpstarter.rst +++ b/draft/jumpstarter.rst @@ -143,24 +143,30 @@ Actors may depend on other actors to run before starting themselves. In some cas The proposed public API is as follows: -``` -from jumpstarter import Actor, depends_on + .. code-block:: python + from jumpstarter import Actor, depends_on -class AccountBalanceActor(Actor): - def __init__(self, user_id: int): - self.user_id = user_id + class AccountBalanceActor(Actor): + def __init__(self, user_id: int): + self.user_id = user_id -class AccountBookkeepingActor(Actor): - def __init__(self, user_id: int, account_balance_actor: AccountBalanceActor): - self._account_balance_actor = account_balance_actor + class AccountBookkeepingActor(Actor): + def __init__(self, user_id: int, account_balance_actor: AccountBalanceActor): + self._account_balance_actor = account_balance_actor - @depends_on - def account_balance_actor(self): - return account_balance_actor + @depends_on + def account_balance_actor(self): + # It's presumed here `account_balance_actor` is an already existing instance of + # an `AccountBalanceActor`. + return account_balance_actor ``` In this example, the ``AccountBalanceActor`` maintains the balance in a single user ID's account. The ``AccountBookkeepingActor`` is responsible for logging and auditing withdrawals and income, possibly passing these audit logs to another actor responsible for detecting fraud. +Instead of returning an already existing *instance* of an ``AccountBalanceActor`` in ``@depends_on``, you can also: +1. Use a factory method to initialize a brand new ``AccountBalanceActor`` instance (since every actor must inherit from ``Actor`` we'll define some helpful factory methods in ``Actor`` which can be used by all subclasses/instances). +2. Return a subclass of ``Actor`` and it will be initialized for you, proiding all the arguments are available for that actor. This uses the `Inversion of Control`_ pattern. How this works will be left as an implementation detail, but Jumpstarter, given that it knows each ``Actor``'s dependencies and has them all in a graph should be able to satisfy dependencies and inject arguments as long as it's able to find them in an accessible way. + Resources --------- Actors have resources they manage during their lifetime, such as: @@ -171,6 +177,56 @@ Actors have resources they manage during their lifetime, such as: A resource can be an asynchronous context manager or a synchronous context manager. It's entered whenever the Actor is ``starting``, specifically just before the state machine transitions to the ``starting -> resources_acquired`` state. It is exited whenever the Actor is stopping, specifically just before the state machine transitions to the ``starting -> resources_released`` state. Given the asynchronous nature of Jumpstarter, resources can be released concurrently (even if there are synchronous resource releases that are run, say, in a thread pool). Additionally, any and every actor, once resources are acquired, will be have `cancel scope`_ (acquired once ``starting -> resources_acquired`` state has been entered) in the that can be used to shut down the worker or cancel any running task(s), whether because of a timeout, a crash, a restart, or some other reason. Even if the task is run in a thread pool, the `cancel_scope` and fact that the Jumpstarter is running in an event loop means that more robust cancellation of tasks may be possible in future versions of Celery than have been up to this point (see https://vorpus.org/blog/timeouts-and-cancellation-for-humans/ for some helpful background on this). +The proposed public API is as follows: + + .. code-block:: python + from pathlib import Path + + from jumpstarter import Actor, resource + + class FileHeadActor(Actor): + def __init__(self, file_path: Path): + self.file_path = file_path + + @resource + def log_file(self): + return open(file_path) + + +Tasks +----- +An actor repeatedly runs tasks to fulfill its purpose. Using tasks, the user implements the business logic of the Actor. A task can be asynchronous or synchronous. If the task is synchronous, the task is run in a thread pool. If it is asynchronous, the task runs using the event loop. + +The proposed public API is: + + .. code-block:: python + from pathlib import Path + + from jumpstarter import Actor, task + from jumpstarter.tasks import Success + + class CountingActor(Actor): + def __init__(self): + self.i: int = 0 + + @task + def count_to_ten(self): + self.i += 1 + print(self.i) + + if self.i == 10: + return Success() + +When you start the actor, specifically before the transition to ``starting -> tasks_running``, the ``count_to_ten`` method is repeatedly called until you ``stop`` the actor (which in turn triggers the cancel scope). This actor counts to 10 and prints the current count. When it reaches 10, the task stops running as it was successful. + +There are two types of tasks: continuous and periodic. There may be more types of task in the future that either Jumpstarter defines or future Celery-related libraries that work with Jumpstarter define. Regardless, Jumpstarter's public API will enable lots of flexibility for working with tasks and even defining new task types. To give a theoretical example: Consider a type of task called a **A/B Task**. Since most things in Jumpstarter are extendable, we could extend the task states to include two new states: + +1. ``started -> running -> healthy -> A`` +2. ``started -> running -> healthy -> B`` + +Now, suppose we have an actor called ``ProvideAutocompleteSuggestion`` whose job is to take in some search query and return some autocomplete suggestions. Maybe we have a new autocomplete engine we'd like to A/B test, with 5% of the queries going to the "B" test to see how the new engine is performing, eventually ramping up to 50/50 and maybe eventually replacing it. We could hook into Jumpstarter to, when tasks transition to ``started -> running -> healthy``, either then transition into the ``A`` substate or ``B`` substate with given probability, and then have conditional task(s) that +run depending on whether we're in the ``A`` substate or the ``B`` substate. + Motivation @@ -308,3 +364,4 @@ CC0 1.0 Universal license (https://creativecommons.org/publicdomain/zero/1.0/dee .. transitions-gui https://github.com/pytransitions/transitions-gui .. AnyIO https://github.com/agronholm/anyio .. cancel scope https://anyio.readthedocs.io/en/stable/api.html#anyio.CancelScope +.. Inversion of Control https://martinfowler.com/bliki/InversionOfControl.html From d4fe9fc887642897885e81d4ceeb014fe484085a Mon Sep 17 00:00:00 2001 From: Micah Lyle Date: Sun, 27 Jun 2021 09:42:29 -0700 Subject: [PATCH 10/14] Fixed some formatting and added the state machines diagram --- draft/jumpstarter-state-machines-diagram.png | Bin 0 -> 180235 bytes draft/jumpstarter.rst | 43 +++++++++++++------ 2 files changed, 30 insertions(+), 13 deletions(-) create mode 100644 draft/jumpstarter-state-machines-diagram.png diff --git a/draft/jumpstarter-state-machines-diagram.png b/draft/jumpstarter-state-machines-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..b10ad06a0e0f8af4adfc70717be1a94cca9249cb GIT binary patch literal 180235 zcmd432T)XNw=LT0R!|f$p%O(zB%8=d0YN}Af*?UuKyqwyQnDmP$w^Qoi6qI;tso#- za;C{SXK3iYvr+v2^WSsct9rNItGBjQySnL>zV*#H#~fpP%TGa0^29O9V+aJ|gw#E8 zB?RL57y@zVJn=#JCi?+nAN=pg6B$Wy1fKBU`?BP>2*gE%l=vML`UbdG;dYn>;ZEo3#T;tx^ zj&+kv>0?rc|o&nyCK5H^XN?z)+r79{#$^D!va?1M4!{nNSc zCS|H7={LrxD=1jhU$4Gp)OM9N*nFVWq2sf9Wo4zBj>}q;8*b&$BkQ^__Kg82^9OSO z?C;Er*fx4F=XqN0`LFkP#?Z+hKiW+G8d|ERBctzgn1~gyo#k~u>~s7=j@4LgS`6|2 zZWf5u_C&j?3kH`jUpDE@Hyx=86d)TP8_P3lXW`>3a#$JP+S&>w3g^@rND%W02nguw z>oaWql%Z8(JNWHIu<-VC;smq);_QbeE8`7^4z<5^ap#x*UUM{!=)-&y zbu%+FRaMnHckXP=_s?`@Vv3P7{Z}L`XZEk+o1(Z5yCY}mqUhbbcUwQnQgIonI6Uk5 zYN-6_eoa#oCmWkdcaGk|K-oDC&GVv@y#)(dx)mK?w0bih6}(}P^d|o#7t3$fS4du7 z6-YI*WIxxF=d?bnuA;I!U$VfV@ipcB`^P_D)6;t%ICSKG46kK>F%oX;X?2jSj7;=3 z-EyfxKjw$9C)Y^1AcFx@GkwfX{&nByr&C1DgrtnPk z^~XnR-m!Smf(nTWS(kz!_MrV+5Eh9M7U@BJVd{Q2`|WjVei>xo8I)z8HA z^^rFx#-q(i>0_)L`AmDhGGDz~xL8h-J}vQg7K#$nGfyKVQ;{Y!0~{V7U4N$M%q1G=j%` zAk%d%eP?Iq-Me?SBaxAj^q$J{LTkVJ&+OmuH|;JRcFI6XE*5t7SYa1O;-SiOI-ix3 z8yl6WxJ`)ZKWpT%p#0&qKIF^G%QtS^s0yaTe3W|o$gC(SF>%$aX7U$!+K?Xtbf%*mN47#9~uEBdpp z4m zzdO6$YrX*UqE%i*$bNCKcDF^Nz$`W{PFTM_qGSQ(1WynmD6@3A*7qa>#Gvg&tlg)N zACJ=sJ5RMFv1@#d5U?}b+^8}P#io>PPp8wltTwwJICSdtY1U3m5n5wxSWiz+fU|7o zU(qTitCNv-_RN``m3TZG2M2EQLoiG5&NvU+5TJ-_$O5KMfXA z)zlPxS{2Z#?PNOBk+Fcr<7T^ab?k?{$jhU+jBT%UBcJH%>V~3E{~hn;li{5qp}7$BeqaC%oMjru^JVo)cSxWu0j2?+!vv>pL~_u2!Q$+;9X^ zihZnu`r4b#CuN^bjS(=KS&&G6Gqa`lak9L&sq{3j6z z70G?fAqsz!14+varlq@;rQ<=%an#bC|d8k`^uzZ4Ebjd?{F zFQP@I-_!gDUkxI5XLRt> z17%n{{yaLjaI+44=X@!CJ081mfybjRl+A-ah z>e9`qg6M(|*5@TVd0cJ#y0Dc_ z2Qzaw_ilD+5T?jvb`IT@nZDrk^N@0htp@QB%zY8@nL~(gLw9xNh|dI9KZPm4ynjq# zSGw#4okz3W%Q*a&tfJx)Dsv?{8Sl9AGrnwnyVPFLbyAepy*AWN_Amk=nfo#2ki}~P z{>;j{HvOmICuo-iybPwG`Sz3jQ9jOUS!{QEwQmFI`nvUlRtesyW%d!)Y0ZV~C<5W^ zvi@g^y>~2f?V1dwbIC#H-k9kWIHL=9=y6YH&KJ`C4JhP6Gy*{vZt72b7r`wBLpiaH zmd`)K?8{HgG3;JChM7u0)2gbTDv~WoBH)#d^2O=I`duGPc<|&R8>0$ zzkB$
E>0JpB8p`o^xp5N_< ziXy6++zhqoKfxHFgD^QAnA^|tog_QJ92Yf&+7-x>WW${sm5cN#d(=j%fX zgrAz>+ftoc(#pB8=W|*To

|$um!M9HJ~eqh_kG!w~RYX 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

#HfZSRz>*5YLxV~kkrWJ_ zGt4wHfq%P4Jeu9nifBSM7}mJ2_h6$2zQ1c59zL3@11`_+(>jy5Z8JcjYNMqL1Y_Im z^_5aYi6RK{UG10x(v`f9mTyT#JgFjA?AkGXO+!_xmp^L{eVx;;KsG5{aW?NRXQ%L^ z9-PZCLK^RQ-9K-rkvEZToNq&wYk+}3nlMGKk^a_CPV6o88|8i8O1q<#gq!G-CTi!^ zDytsbGLv{b+r*a9o}*i*{*-F_I^_gqFZGXklgeWXvVZlHX+J26sgA+X#cltRpUoA! z8Uy0Z^{*%_AmiCmMa>Bj!U(QqU#U`i@5*g-VpMMS$_!F;JlEN67JPKP5KV`_qLm+? zZV^qEfQ3$h^h|m*d2a5Ka3Jc-lMw9SLFe5+w2T9cj42H^Iv14E*Y56^P<(ZDbf{Bc zAS`d(J0S2wRyGE-{^4|VqZg)wr_{GO_zEG-%nhvVePmotU?4SezV{oXNFo{J!dw|x zBGE98E^XsAwB*?|6&0a>e&^<5_^(_72u(o&%iIxaym9vPC)X}~&Fh-;7Axjl_Vwif z0ue5bV0SNaXb71f%I(>t&Oi#srTa?=cKW!v)u$x=oe7|-m)sms)~RnlI*#(VNbU|J zTDdxLov)XN&T+sscXF@93+WpLw-RB;r(+jFFyl>}91}_{L@GbRq_gq8yRI2o!lF^r zV(Uu-#i3js_m{lP270S9R=r$5&FpOVD2>F;Y{e#~jat}ES0*ZDU!jIybV@tm_n*|> z_(fF4HTY$pY3xz%K68NqYBm{u^*x~aU1{ct-p-v$O2eSwAjn5+?f`hLo=ag05|3NOm z?;J#-0}4CHvXnr;<99g(Bz)jXbp=E|PoF<$R4dg5={|s-eGdr0Ex=p?{3h5}AQE^7 z3@-g501q&nh|g)gC#J;mH8%EHH&rScw6(2mw#vf9+}sUp7wDgF=wvBE-d;dD3Yd53 zP)ga9LX`sWH|nfrIj1GLwt>fzC*U6eKZx(UIJuyMFayRBV5n%q3s7pMk_;v;^L=s* zs6_K@_8^UdcJOeg5QX25``QrwGLbeng~wjg`^=u&=v~v={8n#jvgk-f*z0QmP-+ED zxIDSfU}=(6-IY(N?L4tkXw(H{HhU%>@2Lm%6t&+63lgrh8Ec6}QA`0b#dE6N!e5*B zdQT9ptEplbEg#CuTLzphe=J}0f8U#ah3%FcHlaFl**iv{lfAH{KyM%RE0(H!BgnGu z?T0UAFI5eDF{ckj6q+NyDR(tfgKhU~2S-A)f_hu1TlI(A9yft3{5E<2yX6++WDSwj z@bLPqZKhJ46>!Q8&1_n1pl9wgxd`6%I?k=0+4251Lm?r&oC$ z@fY(jNez9%UnO>2Uyacm*ff{1auRRv@Ch-O-llYuHaBmQ@L%p<9)Tvg@HJ;)MMDEL z^Q!WFU??y?@A(6|5sVk&fg5+vnHEQ;^G+&{P#F?o zHXYc9MFe~{M6B8+qa6El#WzVb^dLiS#C(dX#HQSP=GMe{9~}y9QCCTbPITFF+wgUP z{sDdZR^?3o^V~+R7MAxs{Muv9Z9N$AS|^lR*|MdkV~0oMhXy)cvIyO^7oP`z@}%z1 zTy`dDRMqbkb{jnt^+rklwNk3-HBz$vt2qWR{;HjK7Pjv5PN-Vc7w$sx2KGGf#9jpn zxUupr+XfDHU5DbiS$EVoP_>S%?wbfm0Nb;KyBHJQ!D2S5rt6>(uHU+@e7hX75oAYrvgV3HPa=z-~WJh!d>RSEDG0|S&)&vSJ{ zL-G*iUG2bBqg-(|`*ge5f5(snJX+q2nw_sx77l*vRiUE}{=0Ze#agKz zAtq~*yRL5T8e31V#n7t)Gs<1(Nno89+AFGitC{i#?1oiwOV_u2DN|uovB#miR~U@S zT^oO&L2|tp+z9;+0uRe|*jBtghTQ(nyL&pDEoJhE*$1B+_w=!-{4Ax^>!nr2CkF4N zd7W;~FNN-NZx#LQf!*CGja4MVvVDP_02gwGII7m?XEC(qvW0J z&`8Ogy94KL?WUK;#bIB^G;TOvwPvn0-RxQ3+UqNUfpOiL@3fL1KgNNSdTZ)sxF@42o7UxQ8tV%%SOGBR@gAc&ZQ82>E_&V9+{)zV0y~5?V=vQ#{fyE0Br~QK|@?zT+YP1%cE7e zC?1&1Y?;b27_v?Sv5oh`oin_?{`KJ<5s?l!1&ie5-+s9&esDkVQu90JvOndr{~o<* zHBjqZ`6gaE_c)&eF;P`qFP>V$ zm4q{g1wC@%Q+JWSCnxGEDugyRpvU<{Legr?Mg%7VK(>ivq*91de<~NGb}cv`noCfB zf?m6%gOC07>sOf+{yG3Y`S|#>wnFoi;EBaxwI{?kEtfNnJ;{+xoiMKgU+2Gh{HxY= zJ48~E9I9OnffuhS))e_sXBT=*e^XaCDPwbvZSf>=c~qTXXj(h$aq3K)+ix^A@gUM_ zm~<{T>2R`z{rXO3O5??$T%AoXt)7rgE3JZ)LmgrhYrNMhO+As1NXm~h8)UOf&+LQ~ zSBoS)@0T6wpPfx8r4Bd>zkI+)7PH*X7(3K2+TIE90v|t@fZMWK=0Se$Jo!iRJb;+! z+&FWMdXu9m#|=}qv&Xl%bE_ZaLKvdWR#({Nc0Wt_`62^zClDrc)ri9T(Z;~hHI`39C#0vm zM6R}F^_FrR zl%=PIT-cjsmZXYMpJ^}@!FHeQx)yz4O(_9diJVS zW!Gu=%5iy>I_-jA=2{U|^2Z^8grKU6Jr`nQWUjAJD94*kf?S^$PT_(u zcXxEufzc$K9wK+RhDX|7+BKZ3`Xsjx^fxER$JZAJ|A;b|a$qRUUQszTC%I9b8#qbs zfah91v@^TOuwec+BzjX>yRb7oSI{_Y4!?z48vX4$f%ui!ymS^5G5ruNW)BhxT?k1G zHa{&L0?kK;k$eQwbB~~$p~j#;bBcxwB8K~K+4HV`f%kK!TNY;x+kiaJ1yMgUZXKLu_TEDUdFZ6=LMyU;v4iLI3*{p~5 zv$_{X#*dF@s$LjfnS`X=$GWP%->Jju1s@G+ISv2O-=bmPESo~<1pYa>J8lUQ7p|vx z(VvY!wbm6`3p}Mydh^(&0@!cep3mCgiHbU@@s$&cGtqzdJYI7jEBM_Ns6q?!KFzG> zhD1b%?RYe4*PZtJ&d%0dT+omT{J>2F`PK4+1Rb`qhNo`u8Fm0W5A~xkAndIN64ullI~U^yS!#ULukRcyPmdDg5X^n~p13^6VWM zWoZ|rpOtW#V8+6Jo)c?KowT3x+YWkf=#CCu`<1tT2>#k|+}Kdwn0eLBnj9cm#xG*r z-w~^=-;1N)oBbA9um|qCk)I3Jdz>(;3Qi zb8f_o{JJl7d07Pq=l=d4oG!Vf*Nyypd$Zt7leVNE-r?Eb|N71sfTQKR+ml=WzFTH$ zZ*OmV$zFG=R?v6#JK*RlX!neoIFo$8cdgQE5Cu#!e=sfp^b6mwU*q5tuYlnKRVJ=M z%E9U+W(`4q@D=~$$IX)HkK-}u4Eb=|PgvseG9}K1Q6(kk;bJDuGPuK}Y<6yXaePd# z)Mynf?J5sJY{m|A%4$=}>eu>P5(vYXyz25EvMIP!gAH_p$o;Ym!+AVdy;`Ol3}xn4 zhNBYt<7%coZ)=&rzFpeWkSIjuL?p!VHXq82z7cpV#p3}7f_Xgzy|+)dEI{VrVqHZ{ zB>JfBFNmF_B$rkltH}aCad?*lj?Z?Mr1UtbZr+kPc6a}f`*U=J-k;EMc9c$z@jr?i zqF-jsd@VR>RX3!$%#?@+vJgoh&ATv%G#W z0}WQEV+)ATjP^cxRAQx=z54ojky3#dAE)g|J8+C^ysZ_GB^;@I*s<^(@zY+Jn)uew z7Xf2mJu>3#IOek8ZZEfWR-_5kXE{R34-lnRP0uSBa!4~WfFekL%rCzz=4XWM5*0;EYuV)wA})duQZJQ4xBCl-vB{gj?3ZhJK`@mpB{|{LClk% zA>-^$Rqq834ONkeF(*Gm(KY+{Ei$MZ0KH&@DJO91W(EBU?-ow71<8C_IXA8^5dvOq zR$GeK#!12*!yx&_zrQ~7wp{cwI2q7JHepMC78i*_l<2Z9rl$5f#AvDa8~mt~`}px= zi`N}D;jPVMh@3Z|+GIZXJTmd-`EzD2g}Cz`FWO_2B}L(+Eh?)-s3TnsnNY(uq$pdk z`BdLZE;s^WPh}sL*5YqpEM`kDboF^*l?Bnnsy0KGUQ0~Vy%uR_gn<={bl@?j$(L>j zGA{I6?1T_C-8aU5#u6>ft6NUdj|S;xbU}{bhrmFSD;l>l9|ou?-cF|l8(EnrYVAdOU!A1n2*j^#5!?8a&3MLreVyI&2X z)L1YTD->epGytL);BsELVD7PWGV=V%)8$h)Xj$~Z|^@D6lB%K9Ay^;oGJYsj+f?1EQyoT z?adWI0;D1zM#E!7BeSMeLq@rb=d|*bgQw?IFf4?~5;?`HtwJqb={ZMT!OiMp z0vdFt+N!}~b09KP3>}XE{osFc0qOuegVj;wzWD9OX6BltGb%B+DHsSIjHF1G;qX

}ysQ*erskZLQ?w4bf6m|7pisaR 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

_m`Il zja3=zcQb*%@4O85bq>*7;re*enNl3q&!0boP!BjXxL1j>uzHI$c(We3_JhgG#>&b_ zslLQt!N}DzkpP2QnfFi`mHRaKJEl*g_dNBpTUuQu&ifJgWO#FM4K~zy|JqOhD<{Y1 zyUqv9gn7}%x_V=6KR6Urc0~t0GmYMu^lk-~TPGWip*o`isDA^7B@O%E{Nz-Pb($+l zbM%wreRvCo8OmRaX!FbDXxSPWjV>Dk82uOG;-*)<1D3Pp=3V~{aUu09T<3swVS;sO z8y`Oh(@;QYHU{#CK<9fS&nS-7kpS>h$hd<<%)j{QrD$@*6ELEgTX`DKl8Nurfku_p zb$2KS-^U}5z<6PmlqKP_ZOK`EGYmLawvVP@n~*bUf*V(*Yp0nChJ&8KIsY1>zf!T+ zlzsMW02sD9IGS-De}_k>;5ndKl2Z3?g~HV_NV8ap`U??t|BWj(Fz$MhoGcv|Ygu34 zdU0x{T9J11`ri`+z>P$zY0JGR{nyz!N;1W5>3%b)gKcGNh!e&}+%B?!;qXn`EH%=#>(zUl_?5Fr?SXg?{OFngaSCWf1o zuQxXC6pw%`uY0)n#6)4nzteVO&na6D$C7;gYl_y5CJLtN$1?B16*)Ka0b2kLKlmy< zZkh(a$k*l(uK(!7?rp{OdCL82;`?`PAl$l>1+>1r1={Z!&l*@Tuo;FXCjMn8r!Dl? zhWe~)=FhhBkBF9=xL#QK8SNQAzW&SuGoh+)!hK;c_EzrD-2D4a0=sV+bWsmVxj+vR zTw#P2pZs-QWgnjA8VOjix_xi2U_7RjYQ&GJ!Rz^n`8w`yid=4HA-eBi~trU`$1OAVLzkaO;FgAd(xmMXb zv;eQp5_Uw&8N?H)f*U9t!_!wIwcQ@nMeL~Grc6JW?Q6>WlTf4J^b5)KD1WJXq{~^E zW4I0$ER=__%DR4j6o**CffP9FslL8w_l9$NN4&h~ZQMgGgRt+%dbuWRZLY_0Z*Att z9VXZyUB0=GmG;$1fy05Jd%RA^`KLeW1B}_bw3WEWNT@w*?QLio(Q`yeA#(4oRwvOx zpN|_7YmUS4VNuGbkLV)Qvc5IQ^`c;$ikG95^P5E|tPP&D--%W6rl+p7U4!eq(vf}a zI>B=X!v$-ySut|;+t(ZgDpQ`j?q$)Cy&%L)m6TpmQN9z;7IwHvZ}`W9nQ5BmAF?5D zqtie_d|rSL`e|{8I zfBs77wHwI8qoV*{lmSErKrahR)4U`$Ej_&%1hM8T6)z&nhx?c%@8A2k2HZ+YN^5YX ztt+cD$e<^goGnqC|(_9e_!R3xq}1!^Wd>SeO%ftJ?X zre*~IoT|CnzIklTkm9r5VReHN9zIGfE~(xFc@?VH7A5GYa+Lb$q4tE%-V}z6!Ig{v z3rj~|ztt{n)f8-C0HA;g1z2n(B(k*gu7un#GCW4I`h28`1kx_der7avPpGLXk;4U6 z?eQ+AO_OWet7@wDIIX66-b9h=IX0WFqJPONdvY+j+CosP*%Dl4!qnFA;gioj_<=d5 z!V#{#kA7seYl$<+7ZgsYewxEX$}UH_B~3ZUbL*Rca;7ZdgLD)OB_AIXR@V1}gV%|P z-!!_t0HL2L`QK;x_B8DIbD9T7s?5kaM)p;03x z&u_#Q57I_7;%Dmq*{`l4*?Q2>6>N`luMBCiW@Sb7Xidt6b7Ok%=g4Nb%vADhP_=3t zgW*DuxfyQ)uT^3W4fFJl&)DFag@%E|?#94f&PwvBr1fFTSV@g*p6wnWS|~lJDw?C= zz{7X`x|A5YVK=HfEscb3gpK01p#Je%T_OjCFg8w>zpu!v{u*B(&b46^71t}IiJXrJ5K?qX8=GYG|b(TfIFu z{MXGi3uBJ@)rqRqey4s<)i}N`QTEEYB+Sdg==UEN%7_@MXkAEz7bB@|eX7K1cGrYy5AGsQiv! zz#2`e7iVFxb1b04kp}S4t=qSO7C->lXGdGbmjp$2YM+&7K518h6YNybN9yzl}#dZCCHpZ;$&8|s_JaN2ee*6a#yJkgmNXvwk zDIN;Bjuwsg`?^eUa{Sq(lW`vNkSBAqI{&!eDlK5d$|~%7`lwjVpw24YvE|N(D$bn~ z^}pdb(6Hf#d34uhYDy9to6>yrSVP)ofYd`kw(-H0V=37koW3-w#oIB_){W~?-?<>3{+5ER<_6JW&nUs`}zjE6&X+oZ!yFS;gb^R_Jq2J%Pu zZQELehQFkiOW+DNdj|?N+420{q8`24zRc72Cb@`np7jsQ-wZ6yT03^Rgb@`)dM{Wk zMCyHsfFOoEPneg6Q_GTLT3utfZu= zkh%lG%*aBI=ekUF;q6T(Lba|WrfOkEQM62TiD3V7a%JwxidC1z`WgK~ zu(y5NjM>1 z)p0darzdUw!;J--rM&cXuR_%h97c|l4bF}hza|`dnSy`Sn?j^7qvN&=v56@SiW)wm zkX1G-9`7QaZWC?yZKrXa!%QeED|0CPqLd9*%Qp1&4~i;EK`FzwBNQ74!1$Vl6( zOIK0Rc3^oM3uBZN`&EGdUGB}4;5NU1#Xy6HxiL{2v-XhZwmU{D4Gow3vocYPfsL`K z$+GBr4u8pev~C)^>Df>dW8&fC|Bho_f_X)U&GB5ds-o1?8AvHqiRQOkjSLHW1Hb@G zEx^E4rmPYCb}*>u^OzH?c6e-;N$%f)fL4`g$QRn*+bb(Chn#U?G$_aF!521DR;B4B z2PQUs9FukvXn!I0@ciNea)uOW2B55k|KVo{whnZirza=%g%q8o-@kuHZH7@VM#zVS z`3PaEXg;DX=%cX9h9>DWqNdo4rH9l+@3F0Na!?QC_CUt!#`-!0kcGy?KzcM6*=W5p z=h-2DLVP^1Kqh2>YcQ-zviv*R8oINwoM{5p75DOIl_=I zISG>3L|a|c4w4j$oY6#E9morZehbnn;9(%!q&|HFc99=q8HE`YXrd}A>~;v#sHBtb zL*a4(X5hZme0+6=Con@db!?IQCS3%qzGzSPV05RTpkQ*ibB%U23nK6D_aNS^;IWp* z0C8_;FN;r&J~9i2HrA!c7{AB9d`Q@QLRlu}USF5;NmM#oAJq7*Iwh(X(suo@3H%Iy z#WJfF4t90XQ&Z8NYK7Eoe85xvI#oDSt@mYz1O-X%a3ru9_14%d9l1sO-%p5{ z!MPm!aprC`)tmB(S1DIsRYk?@{0O%;HujN?%^ui2)j4;!f#F9FZ1jLBLfCY?PVf0c z(48Wa*{3J(uH`2nkMr&b#WmYKMsj5B&ljwSluuc{Z!^sAGImlRUg+UNa~rw`G66n5 zlO?HWeZx3&-FaW7PQi@X@2##KeorcQDH!BoE;# zX)%D%0Q7#azfTvRn5S5%Dul?`C{Z>wFu=WkpUGzN7tmf1iHzGtcjymkKLEU4UK~xq zX$B@P#p0Pxx{L~~h_oa40~oWhhIxSJQwvw8w9RvV$Y`@!&Z*3~)|#3!P3csa+&nzH zj&*4UB)-%nB;SUIxnNaTSat!Dn4Fw!9ed1f{16ky-Rl}IWQ`{4YHDlGQeXP`Yl2EH zJ|O|Zh(mlKLulta`O@W@_XSHFh! zO-u;z@Kn5|k7mYO-zAKXdh79NMp<42p@~=9G&eON&NN6*PD2FJtgNgw`(U^qB^~VU z8jn?Oz@e_bKL{HNLbxx3H8s1_J=KLMdDm=*w?tMIQ9$?AZ#`jx2bXQS+2DwcY+x_EGX;$v0_YI4CknxRjqcm>-6c z`bW`LbSL?JwPRJS>2;hF=@>47RtyWJ<~Q_I@R7L;B$s71p>@qK$>qvX%GZhKv>?LA z$H&DTf_pU$Q%19$=~pMCR-L2Z6}p$~I&43oa*L^Fa&mo;FT=&liy+hCOlhcqb^P}2 z8$i~e@p3yHF`(;&gN9}X_*po%5%T+gRZV}DId&2+6%o6Cn0SpCNo8i;rx@JG^W~1Y zdZ*L*iZlqpgWZ6G=2->wCBo1oJ!WWcxgeSn-2i|8G%IVXGP2gK z=j^E7@tZXvP)++Eu7xy?Rt(4*G*Wbvwej&~_vh7sr>Gh9E0c{%dRz5k$D3udRT>lu zZ=G`V@Pke_C(bvxU2;3^ zFT*_#!EsP_wYRlFHX#bsR+S}NGOvB9HzEYVEq^(=anZ}qbbzzm7N-n3! zu{>@E)a65ox)^&?JS|YSKIg{Q+bAiM@+nj4{yK>+MJ;bhcss?Z_vb?EfiYqoCd+0y zH7OM2ZFA^MrKDzRZ2T8G%Wk8EcYn_P>Y_3|_as4JYQAbJqc02Z=1t4P`+v23NY67L z-2KGvy1FJEBq{u|UNuV3!h#qde|35q(n5)~YOEKc90J6-23FmP1P^z1n3aGiF-}dy z{9<}T@=DY3A8xaZk)&#)ck%8bwpD#J%58tu*<>QNRN%6Tt4Ya@Oqo878cSJyn46~ z9|Ga;=L^0A?WG0cnLO^7e3*&+&e8fKX>Cftgm-tlJ9L61%gfsv<>vK8tqS7-9^lDT z9K^Vp770x4O`MxlGy{j2>hCn#@IPB#uZL2 zzL?iPq%3docb0a=v(t{2DJm*L=-N~B8lyf+h}bDnUSC@~8`5$wp-V_kZUoD57^zWK zQ{(00qEoMy$sZ`COGrw(gcCwdMFjww0R0i@iXfrg`TcvS-3*~sl+CpTD?wqokow+E zTH4h}*l|#?XJuw8w6yJPrG;bmK&w$Bm1?tnbU)93oZH4aOA4~HiafuVj!SVkY4#9H zxb5qy*aOB7KME3afboXlKu=^ead1=7T=@3k22?!&Ie^jUXLgfl*<6>gLkZ{c$j${g zTN&KqqN4|)h>anL+zy=poMm?J8))5e4W6XI_Qtsy85=tzq#r6!vDp}9A88aY$A(Q# z+gwDgW%3|xquA_jrx=5iN?u}T>3WF3rE#$|M$OL83nQwx|8KKa=+ zh~1qPgX?PoHi&I2=LkfEaZqs|<0+jSAF8#8E-l7PCh3^%k_0;xZaF zY03@ihZjfJrKO9??sv>B59;LcMg^`#8rLJ_qHq+pMocdk0?+|E43Jf(E$c%$sIEQ^ zXCTywj(iNF+xmWp>it!mYlEN#v-CIZ@YN0Z#R$Ben7#5x$Rc)n$d=69LaHvsZp$x~iH& zRjnHI(_tqIuL<>|;>XDPnwhWE2QkJ$Ss!00V1s-WaFzF9?6U(kwk)*DfapZ-?cMiY z79EPd?71ENEa0Yh<2aAz~Vt!4@#BBCV-y8#>WQf|#tXAhAUqoRnlW13EX@wn! zTH~HKS13?9V5B7)=#S!ok)}ZHtL=y-R%42$B&KjZAtArvy&N`Ck-zWT1?!}sAPAD} zFHZiV{Ss>$5q<+7kE8oLUigangT}YiuW%IkrzHv~+d_yN0g^-@-b8!=q+1b+`Ur`L zAe3z|8RPBkc#aPz$t@p@GH&iPn4?7B#cDT?d?2AxCD9-PXpNp;hHNf4@1{M&Sh9q@ z2IUm=F(Sgkuob8u`Y$gp1K(x8J^fu>^a)uhj`-rBX(jVhN1n6o` zXy)vWjq_Er9uN(IP&FlfFI@HW_Nq3;Lx%>tecMGj04wFqRJ}e@;mExo*KSt`5AMs# zczE-6=hE*kA|Ck?>r6n+`}1RZ;@R5>IK|t7u}@Fa{`$tkPa_v{xrVu5(hm?brA)D+ zD`*gTVIrN2i;IbgiIX#Cjf+Pxe;^o-HA^@ENBE@*d|OK8D=YBO0jGxxaS1kw3lt(1 z9cg!4EvO{j#NxpwI4(XOo)Pm6Ts4RwVQVofz^N8D02-2GsE;g$W5WB>CqB1x_#6I! z8$J{tKN=CE{-VGTM2qBDYf1QGD8+DV|m!3{u6bPP?a8_%* z-^)EeFV67dUSmDf1Iv5U9i3*)`eSxu%l}*oDgK!EZVF}ezeUR3{a}!t7sX*V`kCLk z5&%B4(Q3=vLkTJER7G-i*e}bQT8js|Jo6uSIpM(nK8hm96o4NpmwgFCF+Zd49yg zN4Xu_(=5~6{psEHTT!DCwz-T}L>Zq5V~Xp4rEci_|iIwUyR^ee&GHod);n$~-bTIRRNsMA1%>aW1YCcFEt zq_cN%xLwQJS((T~$0R%!Yk3OA@HfGaCS=n|p520T!9-023=bmZx#hMjz*>G$i2Zb@UQtk@ZS7ijaB z6mdH8zgIoGnWlJM$4>^sLIc|qyArE|(;1=JO)~l8EONdeSVAQ_GLS4+mK*y0B@3LJ zq`>q{5PdLtklyI(La&-sIo>M$t2vRu14|nlCFymW9SSwOnYcd>k1DWjU#&dLRU696 z1kVot^0)y~TDE`jAS8KLRAywCYl}DN8LI=7%sTW+r>CbuUu3&6Y6l_;#HGjcX5lF{ zbu5$i3#hO_rr3n&I$g8RFB}9tk*{kc$H$Szd>0ZbA;>wz)tl+GBckSn7rvg(q}$ng z<3S(3H{Y`%t9`HBZa-=F$ml8r<9k7Ln14-A5 zuLx?Lu!|<@Jf7XFEB)sUA50|B{H*@mX1h=A_rQ^JX$S{E=*QffmOUplp(y$}^2ZMTEIMXu}}< z<=>O!`QGXByd54zTZ1kuK6pu9nRz?m>APz+=v2B6MK=VwADIkIAN3Enb~m|Oo3+AG z^>bm(#oR1>W~~YbLi5br$-q zlmKAZpFCuFK{_NjO>8O^%tI;i|CATs#uENV!GU!C5|(BlM~Rkrpwj%VCbQm;`vC2N zAQytFK>Hv{hoj`?4bemBkGcNz_m|HqszW^ra&KDk$R17qQP`bn1y!%>p7|@+yZW+MeeWnZ zR-aDt&+gpZ+)UG~zd1SSqNIe-P#`|v2z-wpX%&vAWQm5rJAVMrp;V*}t0C#+W054 zG5*UA|l1jwaC-u5vv7@b-IDia!+yOB_}r;31-_;PM%}SYa3Ix z^~)84UEF7n47{EI=S*nFQ{YI%y*M-C^Rpl~I0&!k2|}@~Px^4<;Ewt(olbB1A6jld ziNp(XzVVwkE;5}C1G~DHI`n{kjp!)1=EgWMj*>_SPeZvUCoGg>F-2Jzy|r%or=kAO zP|Vis3sfope+!j|jHwk`tZ1ZM`8@siP|n@}4N>#3L}2xA1&SHP#L1og{W_-uW0>Xz zQ)jS#esk3rb(5}BL{#+b__(fg@Z#(UQOSYE#mmbJp861|7f6UOfQ3HV7(0RqGk^z+ zVXXsj83F&{#N>C}etWz<1L*%_ey4H>c6s}D8hWc**E4%E7BC1+1Ls4ihCy%lS-|}n zBV#w@Aw#1K(3MMl3_iOtxcWENrLEJKVgE`N5MW@~1lv$l^Bp84OUZ;JO~(a)$Ua}S z9Md2nUHYIm5k6ZfxBs}*STI(TnF-a16?g{CSQ z`-jrk<9m3hC%{Qzf9z%|GdVp?7!GlDEYkRu3YFEG7+p2`t#4?OA|jUyomcK%OM9qj z3*Wy7%Kwb$aFosc(-UT()1>ij)sLR~&va0~9HqC(8f% z>OTqzZ^pG$^C_ghNSDnUcu%81ntyV-CD)3kI>tLTBvh}eGTlz<3dkaY?8L>5f$ven z?L-qBMwnQEl>$79Hs1vX*JzcBUW=lzE&!NENlxAm$pp}@ z3>9lpLCtg~9m_<@&0Pc4D=gEKH0WaJHS1!1;p}xVACqrmCkOwcm^Y&BuHXHg7O3cZyX(u0n&t*VbTBE9;kkvfA2}>lasq4AW-BP zNo*vUCy-zqlCoa=kUe77K9nY5?X?UJt1;WN#Djf=_Cj!f0?7oSGP{i1sRqmz&zJ(< zQ=}9g6QfznJU40DRPyb?u&$0OARxb?eMp>e*EC@pt>YUgGsrtTiV6#RkIRUa-2JB9 z_*FuM1IJF~ul zAtzB(s$d6_EjgGZbH6xHN`Nx|uLf7Pd^;PG2fx~a`d}3>5ltg^7zBnrdLLm_2k0hL zFulhN_N@pa25zqX8`8H9sYXYfA>hIfKZ6Mrnjs@mDp}aL!CHC8B9ztR_N%KxJL54@b%-5YjzUU^0r^?$ff+QLtmWp z9Jab=QeyjPuke9R&rl zIS>JpOb@7$JQ!qv8o_z^sM4g}F4X_~gHSVq(!=!rfXMqVI^4sASxZesb<~O?1jQun zO#9cQUS;rAl>CZcqdWcmQpdhd^XNkf6_5s#3q3t*{yw3wHPg27-o@+Ag#>N1@o^1N zE>2TcRdPK*x@el)DJ>pr< zJR;3eDjwzk4!R5Yq+~y<%(Y@(=~(N;^R{9wnPz=NSrEA0y2Ab}xe;DKzz4hI*-ieW z2)1?(7#{%nrfGC8&OQtWs_!ze|LYRwlXYT3P*k(Bvul*<`IVLJ!EIZiy0NAKurip% z1{3k~FfnZdK155zQc})t09gAl$f@A9UDu35m_~8QI$qX&5qr=EWA-H2eg@Ag%{rEN zt=FYS9H>v#{53?mOVryxVi{?hPPP1aC#l0WB)AnzaN9jW{{7p9m6ZWYK}EH2vFFJ`5`T?c zmL3K~Fzj^~s56|N+st((1aX=_gl}p4P^9EPWJ`rMX?Q;e^HNWKCLQV<4OUtyG6f8H zQyoy75u=d|F(wtGvuVsx;s|q1@aU}56$T$FGI)EZ)+|m=P7t>api(df3&j5g0F%e! zH)_;3!4gYH2MZKrfRN9A9}r&yuoW^IQBY98;6iPr626)RiG;A!hWC9bcAy@UM`?&% zhaK(!%~kG#t--BUx(r+;vHV#cyt;O-T4X8~qV`1t;G%tfLFO3DL->rPbj_7>Ui`O- zE+VrllJ;JzA^1$xRK(M};xMxv%13|o0G(`<&|4D;e2Da@P(>|Ld;wMC>h3}vvHLF~ zHfo2Tkxe#B$3;cGDrK+jHzT`}Eru&-yHOft;RnJ;Uiz}KLfPq{LzKRAkokKZv%ZfL zyXz5HD#3e$i-Xg^f`T8?j)-;Yl<>!g(BQNfaFYP`4_Xy?{k2v98`}z( z`C<3^-`AF-O!O|g4Y?S-S&t$*7C+j`l#&EA$2EX&00%ZcuHI!5qLe3}2N$Tfmlt+D zD0d9HfeFsYa7V7c?pK~rmHkzO znD0G3q07Zqr}9){7Si1ycr5OGT=)F99nP^&=!}`Q$yi%?n};(M<2$N4cQ|f5F!sVq zCPt9!SHVVFYLaGOv;I6YqMb9h3fPo+tmlOnD;jM*?H<=P^V#=Jp&9ewlIw%A=)dO1kF` ztirv<=Y04&(`m0U%&dd>S$?A0i9KD zIuh>dc0A+L-!Bhvd&sj>!*3qf02?Mv1472-e5W01&lvGc07K&8UqFz>%+eCo{W~zo zscmRj4OIyoj*XL@owPh$To38_Kv4p6kt&^56h_8kl=EOXdD+-@cH*g|KV7?~etRbJ z!_$%5;oUFtI1|Z(_xJB>B#U5hyir6gDVA)wF}`A^GA2$v8R-(RMzZZLOkn~@3UX@_ zif{*9}Im&eco5ZUqo8YmDRduZu;2Iqh#GMH9)#RN(E8R}Jpt|1V{k|5 zln^3A=uLbLe}Cp?WaQ-JY;-xX-syz@Ujtvr5->tj(R)$Ye$=3-gnI_+KO$cH^)mrT zZ=qoXcr{^tOOZrUj0}DC?Bt=L?_ZW~Q|MyoZ2v-P|Ae}A zZ_G)6Qb^LqRIi0|ng{(H;HP{IHItR|>0!A>XWMPo%B8<(pN+7MCr7wSh?8X&^q$Z@ zyO^4`+fjS?lYOb6_YG!nduluy+04ZA@xLo+joK_p3EjY;TL)_rA3uJQOkj~+2`6?l zG&H|l<;(lG5mVgBucuaJYS^lVd+YnX`Z33g7iUeFXWVR&>D1NM_73VPV7&#b=Y1O+ z1)7sVnhU|YKh92fSWw|Qy1#L`$34XVTJ>^^; z1r{T>%IZrka-9%HoIT$zktZ(<2#4O4QRrD z&#b$*+kdnr0lv08zC|odRAZHTW6_bhkwk(kGm-XDpD6VwgMv7I}Wl|AcChe@2CKeP`)NN-y^w zLNJMRnpPa8X6QLd>Czlrb*UWjsE{HWF8hVo)61`f_;UMG?9GbG1;8 zrY)S33in;>!W;%ozD^f}JN^0vmh?^x3=DxuXohc8MO-{JhzNNnp0Vs-uGABKKp?ij zQ$1(wXJX@#uiEp@h|TOKV|YhZU~guIKn@?uM_O|y7pQ(NSJg^`sdQ1bO3TE|7j-TT zg(ztBT#hn(>v&Ia?$y<|YPpaa_WObq!cOGhKH$%kr-272BqmOdipm@?t_haIp$nOL z&x6t*?>bfqWYkNm%K+@vfqf|*@Ww*kJ61~m`cAB_ zYR{J6YDZ0N0C6Y?G4Cr&OJh}hOfk@We0ovzQUTdOqO%@gQRUK%=b5uS5?<8uxw|MR zzCYT28jJX#Pw?>>2R(k8qZV_s8V%qw_pLOV8?UDt@|v$B zhlAP4^%4gnD+WHL1jH1v9hS%Sw^O881)LTwV!cr~mD-J5jTOaPB8x!(jIlHJbzo|1 zE?KeIZ1@Z5P>roTVabT%k@V>VFY{H$)Se0Z5&{lf4)bQoZ(Kc!Kbjv69hOU0{Yr0V zPP(ur%r94gi}fkG9}J+r@Gp2yGj(sd}ev%6x$;=*QDhYGsNcMcEuyB=@gX)4ew z(k|{9aTYy^yb)DOvhn7;@5l0kB}SMXukcEqiXX_Q-9Y(Db5VKwF;)NwjbqmyLT!=` zwTV!RgY_)WE4%O8uNGgk7+5dA#-~_lksUM>4@vnn*TPCZH>#)Z6Sx-I@0YjUN2MQ{ zkiZLkB)u93XTE{6olVuE=Ab$i%@e;@e+rW9%A5wZFb*5+Y3+W-TWU>Ff|rwWgNs*K z80OH5?VEeLXT%z+!Oo7qMU4mgdZS<_2`NQX&t(P$_X?>GUv8G6vf;g@>jsk66M~|b zf+H8s&uTJD%Jy<|a0iQW7DjOO@@nF(%s5?rwAZ#UcX!nqbK4;r?Cq zucD!mw6)#;@g}`URK)3MecWJqN%kIV(Sz^#pU7U;IuY3)@WrED(ya{E|6xx^I6e)2 z#H=HnsVqvY@pxzh`@$0gJ(A263;fs7p0f_3?06fUOXo!-(zpRd6Blw zQ<>UBNVPK8;LRp~Ho}pue|1=4_tt-Rw`aWbw6{CaA<>CTzpE%;iGdgmJy+pgUr@cE zMd#?7UEGK{hW@DdA^2$M;`)fq!R|tOd+>}4!QVZSg7x^Bi{rO%9~AA> zZ=0zZtgN=!J$4k}Wejl>D6V#19p7Y!n86w>tjFp-N`D4U93$Al_ z3`o8lO3w8gl8tvDawU3+K;-?&7NH?w6kTViS=b+yWR?NLX5B-%fuf$0-?rH zLO)VYR`uqpSmVJfYKq9sf|TvMwrjjjbw0gMa+m_vQixZ<3O4aNFPm+Y`e}`vBmv%# z6^*zg!ANE@FS~7&Ez0`#_RLFA=8%y#k1Y>!NXRi!Y?2}P_vggSLQl-7wX z(6^+WzuA#d=faSU{pxT}=jds--vh#~F3`t}Te5Lp*~|(tnyg6?^3ML(qRm1qxDiy1 zg;asYy!5{9OE!eJ#k+>vPRo*&@M{NGA3ah|Rr&*-#)#&s2?xhGBK%lNO8s_^u5g7( zg{W-0e!t;UV3^|WEj&x{Nmw~$^FNIzGEbdnB@cO07{6AK39w*ay0a1$LGz8N3g+-T zaB-Cck~h5!7^~*?t+hpmvvr;)n4y$2)ZE&{neNHuP$Vy+N<-pTP||VxnZG1M(0v!< z}C+g zsbkAGk>mp)^CJ^K2#uTVJkIqrd%J{E_fe!Cfxo!i=b#TNS4|2+L%=@1sJ}W&pK`lO z9W2R249s)K6{v=)3U-I|7PdYl5~^xQKi1fvrCFeQ0FaSuh~SOe^LpgSj3%_$_o{!( z;S1GI+LFw%lI_uLI9Yn1yo$^FKXiR%RF!KNt;fJXML>`cP!Ld3Nokbs z?vn2AMrkRLZV&-!DQUJ!cW%17yYnveobTR0_Z<*wC@k1jf$fJ@^Z^-NAx;o+v}n(Qx-R-a-D&K5smO32Xm%Lnlu2qKS%qZu7ia zIC(|fET5EP?W5`U6fG=nsQtGr-inLhyIV`o1cK-)d>&%_LLf4qH5ro~<&owO$)=Ly zMoaaJIhDnjwWY({a(=-vE|wW3xD`J5F`B*jE2$;aZobCrJ}@MtSCv0T^GX#ho}&ogN@3xbeCxO}^uKbJQ zAZsyvC0s5kEQMbFeM9^OF??nV0$zKdv@Myevy-lWQB9rxvt+Z~El!VPG8^ow*5nbe zw$AhPps`|L-WdNrm7e7OM;;H?#%=q6h{%0DAA#pS4)6siJ4|y{ink`dTWXh^i(~nXI8Wc5mIlTT+ zY4_rv!8__z?iCWc80b7Xk<$5+eFG0mJ!Q-DOP!!v#jDfjaX$}hdnwEBd`;~)NgiO) zm-j$zy)R?LIH4&I#fYwZI0j-F>_9A@KHigXb%ngSA{(~SsnF2Z6Msd7hZX=~pf`W* zAey18a@sbSICkRYE!TL1+G1}F*PU!1F3kUIn)SNu%WE=pFG(>w-PN;po^PA_5;hq8?EbSKBn2F}(dYVXj{X;Y#RW#hUmhtuU!xfMLFx;fp+}{6 z?%l(>b9gxkTJ(FR{s~(1z6t=tB^$K7<4Y=)*B9@SSSSb5bd6@F`Cq%t>93sQ8mwU! z#bOe9|EO@BjEfb!spM=yAS`i7iv|lSW@dOP>)ZDBkG3sqE@K$r*xUzBwL)qET1Y31 zF4RUT}cYnH~|Ims5$y056I=hPtjFR~6L>V`_IZ{bC3|-z(<#P#< z0uKK*AuS0lHVTKWq_yuxTK=EKWrUxz*btBWsKdmN5)}>1C@OE_&ZjluMRAeP-vQe; zO9I}Ey}}%Vcyun(_30y&>NJ<9f9}E0FBX63k`XkwvjSAggf^GL-$N7q+`ny~R|Aed zV`gstyl&~As)!WHMKkk||Ds+rdy;v*cDvj%@qe)RphP^UnmwAIytM*6qAM;qK|Ze- zW?8RWh&>_EMx%2xypC>52(QJBc#ahQ(d7@LIB8!g#Os;uE#e8^eS}=(mv;j&>we@k zGjl)re&jT?XU~&atRU^6R^}&CJZ86glRN)sJv|hFm4{mFF4O#=USnNhLv(gQ6YRvt>ee-=4E=XRr=a-#ho*&0x+K)O6KG6KqL z*o;61>))siRBE2ZPtdXO?a$867TRKDj($Ock0Woot(V!peVy(}NN*sW?Ko%oU9*zcC{#}Lurj=*%e+}3^rM4S z`Kc$pyfxF?W@g4XGqIYpCtLxSC%QJ_LBGp9ua?WS>FpQK33jn}h9z=QEnGZkm zsb+MMw8W1lRo**vJ{dNX(z(PJE=lLN!GjDC>}l zYAOA|_`Uepmgdz)!gSbE-R1DS&-L0aA|-2ET&hY1D|*t(>M^|$Vz|fDM-**0ulG`3 z%US7*hz3Si(8?3I>io}J-mM8|=idex;TMUWE@JBpg4_~sTD{j4wx?r+tg=MEc#3v*C^PbzDUO(x3@_`YaB%OXXK*=Nu6QE0>A7-325q@R zBc%upTdwXINj`n}*F!+R9(-P7==CF0Kq>T`2nEID%|8QA$J5#b()9Dvyg@UqiP zC8&*$g7BFs$o*-g)2lMC2V9t=+LUe9eRa%U71N&R=H>?J zr#Dx2lKK#8&ffoZN>j`P$we#zujoq!Kip<;qp zh1QQqs3o!=pkMRdbVMW$><~v)P8?Vx24`swS~vRbG+sB1JbBexL8Bl=`HJwBh;eaM zG_Ly#`ouruhtI&!$Uf~?GD~of0^-&(p3CkVGYSacZ=Ga_o#d#L3giBKOYFFPc2Lx+ zyRp5!<6h%Z{`k()uOpGa5A2F$I3%;}kOAnrbA&|THas`}_DpO3P4_#gNC2wz6R zAcmkWy=Q7_Dk6n?Wdv&mK(oJGfGc-DykgW9*-O+g6F$q7HFDyN&dJSfr5CFI9L1Xx zi^CZjsThgF>2K297bF@lI4w#RTzBDIxaiwyCvA3K$z*Q)t6jA>?OUr{pKwlz(%yI^ zjY#5zq5k^2wn=92eUzNSp|6VBzvoJ=wopI5ie=>zZkn6Ms4RT6VOJ~s+_*nIU5@?d zNnEA*M3F*%nYa|L6ULuWa3vW8@=dREf{j@uy+B6_MS+o_A!v7hbbJh2T41My_+1jK zfbk8B8x*__H#Nsvpob=ar(w-H!2X{ox7N3^+WsmOb`D$~;==FW-{Ft}hE79c*7WHq z6B84Le_dna0uX=rjeQ>NR zs=_rU&4l}|{)<3w0k!^vfcm_=JWwV*S5=?Ie+$nh#@)-;7ZWOa#x`hZ z1gx?;5!2f+(McyM=-3o91|-bZB+|Hc9Bn3boK{Cl-_zM`EcGTD4-9uEj=9x;96(Vf zsB}lH9ZZb49vc>!*KD~Te)1!%Z*;eu*$}bHP7R6-WYea-@pi687+_O&1jXQ zAg;i|nyWNRsMSwGDt~|1QR7;n;=R1oEN!!`;{5MuE{i~qvT)tWS8)ny5_fdeS)Udg z^L@tQ|Ky9G$bh{ogRL6dgobZ$NY(a1T5;f^m#fTz*(&Se@w^6)cw$tB?qXyk*R648 z+i?kk6VoM*>EFviS);1N$}7FbV%dbo%6nb8J0st3SNPtz!)M8-eeHZ3|6=KQ-_`!^ z>EZeNizF(9O!Tx)Miu+koPC`0{j*GMM0FUaJ1(xwp{%8?OsaNBhgxCEj>p=y1}}{= zC!LM~C7~Bi`y#n5?pE_XHJLkRr&T*@Cy{;_o=K-HjvdGMT`zFxIp|+4C1{A${&HY^ z{u>HaAQ%FfpcU}MKuaw6>@!%CL*Q;UT)YIs9u{RNXk04Yp#bP_0F4EJmM08pA2K^? zefS7w1<2ms@Iu>Ks#f8&9v~Cz>gl1}yvgNq_!8zUtYUofmr_S#d~5|E4^+Y@LjhX@ zewYmX)^+~}WE1R^l#n7CGLR~j&l0@?^J17~Zb#d5P&oNvHiid@zocXr7*mXS zgg_b%wgmd1XNA_EFkT1Y+aO#(8rceg9a3w0hE`}nKx?wG7)?|X+y+FGAdQvEMshgq zLL(%HB7@Kqs9^3wiT)WWsp&*bHQXPhE@s_d>VbAt0SZwNhHh?df`Alk`sbliljcxe zChPvnk@`v0lumE#Gx3X2l;YiWpPE(n85@KhBZfq>(m9B?64!9Rc{KpuY!%x z>sN(&*(Qq$Q5ynP#9zWnr%|Y@Ub|Y1&B~;b?PZTy{l1-!q;*NssO;pdv@^F5u9)78 z&=+Z7j`RyEoICQwR&Q%-MjNMJoFck5Ep3%?W|7@@IfH$qc??*a^TyF=KlC75?1wKW zF|hxb-A)hTp1x*eK!@%Vkok@QnF{M7-3Eky_X$`Zgdz~`Fsc17tCAo-1{P%_$QD25 zNb3;R9y|g@pVw17qZ#x`j^gY#N0-_9ZuA9=?KxH7tcnkb94n=oJo!HNYUOhdtDFxs z@-=8(T4=PKbOAJE=aZ93fYx%vN29jrs=7ijqD9eThuw@_;)vs zXFC}SabM$zk4i+hozq*{N)4+2;^L^@)VzasKVh+SdgTTAzH&M1iTj?KFfRjof^uQj z)+aX^iL<5QilY)S#GniSsHj1s z1$h+;rW|~=w5n_;XBGSOp zs%o>Ae{6etnasy)EsnL6zlc99WMduS)Es15nK*tP;J3S~Fgu4I<#u{hU;8dnccR2R z>}@Sto8shn98xj_$hMOb(mer)C{s zKp>4ufRqF4!OK^#a9OOLq4V+bhFc6!WH)D<*%_$1j((>=$jcpIt(5VabD#oxO0sAhP}JvEpD`b0YHg+^qrupLSfO zB)`~!5<~e$vh_jehW5Bv8Lz9xCm~|6wzsFXUboRu%q)(g@i9=coAE}~oN%A0Zw=6lrghpYjA~|ITa`y6$db-3 zRV$YsCClKta1m|{=4B`{9zYQn*VD4xK)F}=@MGWVD$L;CSm9iCXpHhfy;`}vG9WOB z%dofMEpf94DSUv$vWT4MF;LOWRLq)8P+4Yi5{vprfg@+PEItk z)>rmxj~ZdCvYFY|txiS1vU?;e-+Df0FPYmSaX)||TfJTIiG`6Y0(mIK%S+{K*{+wb zt~TbPj1y2_!dhy~WMyHcI6E_=?zQ`!;Gr1BsuvBaRpSS zq3{ff3@QwN7#p$EA34Dq0;`tBC!NkxeMO_w|Y4j`XA?a z^BG4VswXGU5C|cx{-N4gGcr7k5z76fi@Hw?RRKq|v?@6{`QeG8A^S&R_lFVZmb9I} zNyiiAE4T;+G7xQ&eYkFm6Dz))?N5j?Q>5h0+}z&FziT5QW)lhfxhXq#r=JcT9cjfx zJNj(#;GEZnd3UbCQ{ujcKi2KTwCrqs%$HOzCLC&H!j1|`$%c{E=rIv4wHP(DkaEy6 zGL``UwSshS83~+Mk}p4ha&ws9g8xAl#x86zEJlU6jlyf)?+7P#EcP{3O zQgPAI&&bGXhR)eu3OD!+Y zpxKfPY`4+P)r3dZ%;RTf!oA=1V+M%G?yXK{Ie$zUxR`tPwT0Zpo#X|zIqWC=F7tzX z3u)Pv8*fD|<2-)dE6prn+1iruM;kzzC~W5nAJ*7F0RCJ5VlCJFR*`<^IxtMQxw*lu z?)-G86S!l`ncI4VP@}BlWlwbs7IT5ryx}r6KMgaoeZEA@R?|jkvFYBiu zg@IaK3@w0?r_ zKGSvr_BW-s@HK8(+=zOc!rRu~?!O3}I&)4W7*l}*Aw=`Qz;V4eI{*^|cT;arxIhvC z)>2?H7=*`|Wnon!{Rk;W0c@UwJZG3Fx*s|hlvIq>tDcYbJ8^3H`JHXJhW7OK8uxum z!5=}##@^q^0F8`Me~wbcUGv<-d83Wkr>|ahkDcwQa4%2TcS*c!BmYtsPE6AjBXXVB zW>R`JP6C$Fnd}h(6a@>svTP?P$bbr1)H^78TL8{BHMaVky$>PC3sTGwgWD1mO zY8)^mws7?#JrBVh507 z_$LCVNb&~qRl)ATa#0R{t7~Rx!iNymraETAxnI%X@&_({=A61@80g&vCwvn+rzI+- zdQEfU^76;buS`6Mn?*(a3@)mjj}>}*twfkhlhZ^H`0RskiI28M%X6b>SIn1lR}`3; zGu(aVu;`|@j1R}5D`WQ&wa78W2gN46{l)*bKl4S=h| z!^7cB(B8DEx%sl$V)=zA;pTLG0OZcViLV~wJUghJ%l(*hs8@7MUo{VbtB{Zo2)ohG ztT83j*qrv&N@Mv`kL)w5_ctd_6mOJl7EWzNS1)K64_{Oj!YX4fL1~@&ZYmNXzu_2v zNI^@?PWbh)Alf;-bn&Ds`P)cd$xp*1MGKXH_Sfn}7YD z7JQeix_3Z3iAhgy9p3W(VpOfVDUphg97Zum<==69WlqRG>)Y9abX1VOSc>t43yfUNR6s)G62U_w-4Xi|oQ(~9~}bGMC$ z{GFUN4mh79qE$Of@pn2!7b>pQBTMp@es4xEuKdIIBV8X+Y}Af8$o6to8Ovs>)&AX~ zp?Tq4F1*!HXFhlBGOdGB2gHZGFf_laK)M!5qn0I|Ip3MIF**4pteF*1kWzCEVr6Lm z1Pfx}pF=SctiDLl!A#_V6aXwxWcYGoUfbD8OG&u`miu7#-qPCY4A~qQi2a!+hK7cG z*tQlH(R8}P1_p}|d4k_7=&>NYlp+Qh#|Y@PTFUc*pW%0CW){1+_&MiD9OBBl!d0jT zgMb@=Qs~h=2*?U>%mtr6%u^~NgI5C9vi|=5Fh?M;TpO=Gfs;>|B%Pm3eg5<*nM*Si zYr;fc0)@D+v{XVu;sRVbfye<;0Is9iFt9CLv0HA5pyUOp<6gO{`e@CkQWS<TGo__m@A?5o|nwu6B0K%!bKrSLS zepg>Ff9uNfGSu&L&v{K+YITX1-)RS*{@grK)nn%sOJV4+{fvp8g7ZXeW!b;N=zuLS z^8<#{z>9w2^O|Q7!U%9oj?|5!R?*Yf*VofyvYKrIkbA|Qrwf%ul&W*HS$-I8d9A4=o6?da`K3Tzh_)I!O2Qsa0ao(ItXg z?RGZ_G2SKEN2xG>u%0WO9Yx3{Z{JNERc?K9u`AQ*?jv2mi;70j@~Jf`Bh7VrVc;8o zP)d6oYEV$XC~unlgnuyE7yQsrs#a_R2IkZ+evACPUJ2z#l_-$!`E$R_*9Y%Tg(OZj z<6l=7Sggs`M~CvINQf&4(ckd8*Edk0-uc)n#B1CUe{?qAZsJX>lJZXJ2L#9G_o=L0 z#~92*rl;+I>6#c<=`#5fJT-bY5ajy0X*#;?M?0P3w#&Pweb9;^@=MrWRXA4ym-(Rk zUk=I@$vZdh=&DZg5P!}{TZzQEeI3X{{otlGak|panaX5GVDqlw>cJ0c|L5;ACQ`LC zpyH8c?DiObH-C#n`w9LU9<${p7u@zsKh;4m*e&In{lcC;$#lrft|GlCC)hzUqx#6 zVT|}2fLVnu*3A}mn2~^z>>}17Qoi)KMu%>#0CJ{5HJY~%6frk%`htDy^N1EuQeR2| z3E1ppvyot~48}jli>V=Y;2{Wp$Y6>YuZg3eaA}IU4p|^DeZdJ7G&#=ut1K>u7MH$q z0MG8PD*0$aqZHS(FQcrfhd86dQNb)aeGHDLjtwJUcXN3j56|+#K#Y8pKu`t z182B<&=LgHuaFE67wLz{QjijZwgmjGlR(b`V$g9|-2exMHOojxM^@(~-?ePfUqQ8= zIF6d;8oKRb*RSsGE%49-6U{A1F7(@DVVk4#(S$zHD=RA^yjxpa@XU@O+71{!fXzMO zwdDstaCyY_IRbqnpwPm+AaDx~3b^Efj+7Hw?5|%KBAiK9BcZM zd0W%YaesZB*ui|ePI>VSWd(`8-)uqH-DpwT&2?^2F7sLH&-xndKi94B>h{q#AvWJ= z=KsSsOsB*v{kbqXxhAZ4{*|`POhJdY7i2DI#^a}{ z1Z-~AZq+f_D?dWGB5!%~_O&7R+Qm=+ki@64oBnkzQ?l%Ev71s;v%(GlD@P9J8ks9+ zxne7$L!))i*k1^>76O_y0(PWU7O(dfyT6%^_&tA0GNWp-Ne&5ej7%z0StQNS>Ijy` z)AdnYWX0aDc!CYR+@s90J!3_sF@OJ~nf}~F@Y~5(Dze*Kwk3Gn0VYXj&0)TtA6WbI zs_p7-k#K6bOVk*XueiVPZfK}qs|RfQFf!69xO9sE=)`cyYN4E-Z^oI|WFj+jZQHdF zpC*`X*8^_;;(chl7s*c2o5qJpT$ryQV5A*^ji1rcS-NMlaFUVgsy{V1! ztR3xXM#sRx+PF;}w-(MyEMv}?s+QS!dC6MHChC9@gZZfGITc}&1g|_zhhgV5Apr}P z?VjG)dV+(C+k0W8R@--9-&5P(l(WijJUq0anY(hU*7B{ajAoN3?JoHC1NQf1M$LqC zsQM_7Vb)Qpd81j~IZ}HSC0ZNTF=`nW2YS0J)kAI7VwpoT(m7t+5byTgz(kEHiEHg0 zIf%WB|Aa0AyHtb!>I`N;4e6KosLWTT>plqx>EAV^!~>CHC3s@9X)A9|LYnF6R+k+p zimYNo2&Fqq<3hQU7f6GvTvB8GWjk?gUhvPnB&}kO49@$pu0idR4E5ocCWGJYoyI7G z=!Wf2?WHQtNtC*OX^$QRQ)f~4RCgE4&)Pcnv2>8NOf)6ZSTzr)L z3QM50^5pvsR{W~DYf*`Mt*B(XxoOVP8M0hrZMc=E!_^umTMk(36q{YNw4rjn*KWQ( zloBERPRqExlQCe<^jKO(2dIS}bX$Liz3kN(BV_EO19y?zre;P52_lrVn3Uk(^3dEB z?J?L0x{0=RY|Y$LKi=WGV7J&953pUiJ8mVHnnB*08^(3Cr|>>5E^)@xZ8cvYs$$J1i zf1YT4l}^mfB_nJ2et176;Xf`wyAcCkJ6EYPEzz6?dW#INYJVTHwBhLdqJf``n1og# z;Aw&?<>Wg?2ML}W4plEbd`!zmIUodkGzWT3R1~wSjU3#OJbTpJ4DvWEsDrm&Lg>yHoypN@1 zkEaRVXgfKD^RY}~Cu!=jI1q^jIi>s#^anUw)A&gN=M?gQymWt{5JQ=Z^*ag6bsopE z&$*K9A43$d9$x1amOx4!mQLe&ZHv=1ULtp`W{TUOv$I2Q_FKG3nkQ=o6;5y0 zZ&`y)WfZAo&3gXVsCamj+bGLFi_(AQ8q&|+&novLeju%E{7 zw$W4Jok=iIPC-LLLgJm`9uS`!khNBSn)?rnf{4` z^G59J0vqa;rDm&jof3ZS4>SMjBn}#w>9UArKBRGlT$nl(WYi`SjO?DBXG=4mFNBu^ zQpanfi9|Wd-tEWakE(d#*=xkW@5AZYa2qHfS8zNm!M;vD+tV{Bj?wv|Ux!Xf>GX3A z$lMO!b22N+$Ay0l4({jWGyIauSWu87Ep+vtiJ_Q{Wuwt7tO;bq#`N##=tX&V+cPIU z(HPN!{_GN&{C;uWZY!mxHaUf;X5csdL$BqKG>9Dgv}q8mO(Ij{aVdkiveD|L&(K-W z%x!#7-+A@e=h(i)LVa#}=1I6!LN@W|W*ypalp6c2a>e)>$0E&2T@bW2Df>5N?e)? z#o+>;n7PMgSMRtdBK5zr4ZPqq(KcDhao&38Zq#?3jW)07@h9uLFB7W+B)#Ie#z zpUwJ{QHc_u|C*nD2}V?7YF!nK2zlz%;SyX!Lo-PvD6i;cmi+NMxd`MtCqua&Hkz|D z(?=YGo{(VHleygKZ0yCS7nS&f?QsHwSzozzLFeha%Yu?0_N(6BzfQHXGdRWbdIm$avpc_2$`R&U~ z1r7zN2uZg>N4xJxpYk5Dg>+vUm%0zFo!L0IG!j98ed{`pFWSXSTMX1%U&`%xVC-rs z+1Ydd{EkjyQT3Pnx_J&hDSC#c1TNDiE4NeOCVd(TQ_dHBqJCjfCThmP==aD9&5 zeqLr5wDMSz3>4Ex3!Sh7JvDBNj#nyznEyejLEWw1661F8LvY!Pu$bgdWwjl5{~p@` z%%NJX-t(#l+MoJ4U%RXO-3}0od!U`eWB~zK^SiL_8*c9Lbg`kC z23?87oWnDF=}cZ8-`G42^BUtQopE-}Bu*FR(!%Fsz=41&f=dC*a|J0$>@@`)N8!ES zNgJS1E&wizs($7()@ZhV#)8q%$KXi_kE;;LYveqd-APnZaidk^h@JiA!BWtljq`OX zTcWDdw3jMq08wSBKAxWHl1qrkzx=21UzVuPcKss_MJ2`2;UAFjyc4`3jLc1PPm*L( z$occWuiW+7nEGXJ*^IF92jRPVv5*jj`^9LQND)9KHBKc=oa$YvzBWjTov}(%4Oi0D zUSBYm(sfr!193VHZBorRwrsyQMJ#P8%KY=8xmEYR(PCyGl5os zb%joIEsf_37=+$dFdydU`zMsrmPh7VTfbQTT}yc|Y?fs$&RDbSl0TsZ@u#|-Di&Dl z?-v^m$z)I*tZ6^P2s7+$vtRq1r%Z~++V@SKdU~goJ~Sw(y+KUHjrBprj*gCF|6G4Z zSST04t+6u0fFMx9z_R|nfBmhG`%A`;f2gYfZ%?`EsGQ^-e8=6tH$cj6aAa|@9yO(` z1v7j6PnCSU3fwdh9#=rd!8i5j!FQu%N1{Ccl$w_0R_e6dqzq)h%fihK*!MkQmM9T_+V&a&?BPHW;3OLR44# zH$C3FwI3(ChhLZXT3yVzVPt)L^P4%*aKhqK$;tBJPuj%s(FBYiU-?mq=$-SdBPhqV zX5;0u<8yO{ot(gf{k0tlofWXw{#&k|qu#Au-P6VPi<^#2#v*`Q`Tda1PA3FEs?s8b^%-whW$93VuHMKGe{#{6 zMuXpp@5=Wo0b&Rh7Uy;r#Kp8sUQu}N*`uWWSZg<^%(b@asq5nCs!$4t;zo!4ogr4b zw4ZY9joquKCh>@i-b;w@-R405lu&2;&8o!ZX!|{wW1k!?q`r|`=ik{h7x4Vxb9TD( z^Nr_!inG>EaVJrBRwMFBD=nBM1AU6pyO!f@T0l!ATS^;K=JEU*spq;?^TW+} zxTtKK#k1k`QVsLY;4aDP2=m3VoT(G*fRsm{MB;3&MiPfz4!lnQk<++8a&{eq@)~k;vwNiUKnXDpKb?H=Ux*V=Oj#YTd?Ctf;CJ8zjb5aC)}o^Wq3X)X z31DO0za#$&ISTk-L17yxS|)?VOSA|cCYlapl~Hs2W8QRWLbM`dOVQkx&ej%T=VSIQ zO+R+Zkqogo+c{^HAX=@g$M3nJhJj6`_|x`*S(6UkpQm@Pp#h9==TdmS{PM*0_gZ0) z3ji}y+f#@0663&v0&o!si=l_WUe%ZGE7k1rKb8Tz9Hg`EYLN+O%~*X|79 z@5n8`C1bgwsI=A;h3*wh!eVC|gYP9LCcgZ6#PoTo5xEzSB~Y%%-?`t>)Fw+2p}KJO z8We-rd?8+li zY7I^0$9SklPUu{`v(f%!sub5re3(ZYtiJ^{HWv@d(Oy;IVxKggJNDMbM6)ElXePSZ z7zR`M@{j|Izzs0fhlx>kU+aoW(y14BLRo4F8*h^$3UWc+3oUh>3kt7Bwy%_wb%qPcbD5^l04~ zMB8grfs^UJVICOXL*Zenuy^jsYE8F;~8X+9M*6tSIB#QuqYu=*yfa~U63AyZ{wB@<{Wn3~cz(M$BLBiTwOKz^dm7`!|568`A!A! zoL%gxx9KGV8|}K6<`Z}C&XpV?74OY)rheTSz44(35@EL1cncAbOnQ7aHd8j0SX+<6 zyPIRG^@?QPD8Toml=Q}e(Veo6zi=Kb1>)g&jOfrI-1DcyrPltrN+9OqHrC5ER)GcyXX~r2qbaxoP-JPhLy9CjQSG zCc>b_%!aYG?u3T_Ztll?{h80fS&b9+Cy!1b(*8NVT@5!1RG`QC_Z^cj4o7HISM+p- zfOW_-Q)rMdUH?(7lGpQQT%O{ud@0WrUbzVVH@gk4`HDVY>_1`C2e>#?G{=ht1xkG7 zn7a&ge)={F85~Dg@0dI_jJA7CELX2Sb-(}=itWeX$Md3OIrv!hlMxp zz~|q9YLpW1KZo2mpna_IK=7rj1{Qt@IUb`hBrf00HEMis4j6JiTZYy!a@m4ZOlsA! z8}kje@mXRC0;~8lNI{+~g@^W^RQatQ+#dJ*)VQHLWi>0;HoLqBp*cW-Z|LSwf!B93 z_@e{XTa~a6&R&m=&DUS2D<_y?cQlAPp7LUANc}tOxgDh!*KZnm9U<>dju~7kaayo~Bkxa|ja|jc@r{l7_jTyNvIzH3Z?sxa{LBaAXyhZ<1OjY$ znx)zG(A6@Q!B85P?=o0#3DgwT>u5XLmATyJrfSQ@cm9zC=wuY3!C>>v;LrkO>N8hD z=MghVMPkAv#d}-cI`iHtAKd(0+E&-DlL_>EL0FjlF?;tw!{_N!nuo9O=qqZyq2hxvrrAk)9|>dLN67OIyEiI2rl$Ca0rmu&fPO!X3@ zFVL0{ETl_Kn(Zy8SjBHN6n@ljlS*LGrnAjTR$e|63GyO`KYKF^ zjeS#HcesJls2|N4$rzGR|L!u7_egntD^24yQ_RZXp`QFSBysfGd2ajR0}Z1!`MT|( zO~a^pHSo`W*CQ;HDHU*tqpyooR(y%U%n2;67|Uiyy42rcBKKXP!iv&b5J#3xc)mj??)YI>q zFieXq=#|HQkkHO^ys;MZz;R1aSu_s?v-jV@_0v}Xt|0KGdi%?+5cpfkU>yF!cW*kX z9JeU>eF_P5)UMtzvko0K3Ll0fJh(fN{~ji6EmxRxv|x1Rmi z+Za|F^fXB7aPR7Q!gY99)knt)V^ejpJ4cqfvO&%q|H0!*{rcGSZA`$c;VR5Om7VHS zFj~{L+?}Gihl3Ilt&UAY-m87t67Y&-^AJt|SDyUBy9D*8V*I%_TixG>`8u!SO-zi; zcmK*yx~bX`s9=Enzi00fNP#y20^o1YUaq6T6|~?_)Ys1zbM&`D=Hw87AneK_3L zSJfVOW31w~^T9l%&mL_77~-Glym^sj!B;ox2U_+@!^x#SilP<#u{wYl#yiyDt7$F- zT(ZjTWAU>qO1B4!FzlXrZ{n(JXNoZg;K7^16U@QQv;OyuT&d!RH)6T-{Ms9?%WvHb zjAM>+IWKn^W9>1hOLBo}e8)p~$L%y!-|z(?S0Z$ppzDdPdnBXxd`Pou*f%%L(AHRc zD|2^n=zduxC2S@~=-Y>Imf;w-2i@6M>(^Gl!c`!i`9jsKb69ay(5Ux!UtYOkNrSYC zHVU&Job%7I{sMU;T?=&m6u1APA!azGh9plv=c@?t;uJ=@&wXU2>)CB2!hH`N-X-b4 ztJ7FU{`rvYH0zzJN1V00g*GhyTbDV}XaN)UK}puoKvsI>VB@wzX;IkK!Z0RM&KBA1 zw!;te=}6`1p%RANaX}-`0^@(r{u9fapL$w5K0-5@=yL6#Z!jGe#Nj`m3CU44qqC)e zuGr+$C~-;oqm>F^Y6_5cUeV9Wmj_=KZVF|S5#G<@GO3BobN}j9Pf?`Cr}szv{jJBL z&OyYaij=80i@6H}KPC$IQh?niTM+wa*#ZU5&zWP} zjI0T6j0c1$*-~nEH}4LD4E4_raK(KFU1p^2%Mbs0a^x~bH@)sY3=TGyW*ESLPQUYi z?A6nN5yvk*!Y>_%f?@n(B6_9i-zOs(^8#rUir%1vi*k$(-+QeGO`ms9Hs&VW;^@s2 zceC>y_V>ZN$^7UM%`H|NCgI`zeRW&90PQN4CLv*GX+-Z=pRye$6^=A%<^m*CE9s(MZtZt!4$WzzLX zxnkWFcS|)whR2}gvUkT72UPl+&HjoW$-_1{N zs!FM=i1g>9F38C=WE3GmFOB(k8J+Z${}V3Z!18hH&oiO8o|u-lTepJ5^K;?6?lKp(=qxhoVF|)oq4?DudaU6 zZ1p;s-3PoeDx(LXk%KsV^50M81l5(lv#&{Oxl||%@iKa)?>&>h{1VNnde(pc>g|Ed z|1OK?OW!wt!MeuRl(pQKbD5j(mme=#kv=}7$+y8DVgwk(F>Fx^xp)I9E%C?Am~LYg zP#@``+j-_AprolY_F?7urg|W*x^dAmb0OxdOAvk1vw@_6hid0RE6V3eGa;=ScG*Pi z&r#UK5+et6bm9@U7)m()%R)Iu0n|ouihUR=eRKscXHd(;{yMcm7!xBMv}NSu+vOx1E5IJi6M>s6Pk^c2Q$jhw(lP?cCJ-hqx2EgC5ON?< z`uRh!Ngjpn#hmDfD}xdzQ7p`H4K%RZVw4wc-~oF@E)rLxt0l*YvS_)&m#Q08 zPP~kmgqW7(ZKx$Z+ZJpD!nv_et*~SJ=?cD4|JY>+b@bC=te=ne{9DerlHBqqu#>HO zoh_}AoEfcP*K+gEq~zwSyX8G?ITNT-+A&i0N`GE-tIYC4M*`&pud#{veRRM)Rc}5m zSFJG{tGIMy6c+jpF3wP)20cT36gb-RUdwj*$9s zTH9f6^RFZ2d+2iXOqP#YN9*PZiDN1UN7bmT9|}9l4v9;{Be^^##e{=mpJHquX(DLqk+ab2M0i@cKr7q+}%E{fepI6nkCa0t5D*ec7)UV|{7k}?}`8uae>*KXp06#d~H4h{~`F^OKv zbCSUR86@>)6?Ff9`F4i4 zWDw-4Q(-&*AELejEUK;h8v{`gkWi$RMoN)xVE}3APU-Fr1*IDS>F#bBN~F7_VQ7Z# z&To(0_y3*eJl>0O=FE<@*IxS{6C5m{c-RcQx&HpO2ROFf!;K%fE#&WIx-sZ9K1FDMz{A7y)qUxUsKwaZvm9b_ zb90lu(O?FUTcCOZjF>2!0u1nSq= z5rSz5LNl0Fc#Ik!Ay`;gZAE!@fV>5E1wZ5C+04ea0E_yOXPkKZNGll`=D%S$&wut5 ztP4}Bt1MZr*Q~75Bt@Hq!}|6L6=4J8q@`U&LQE2PWY9$X+w&2^S)VYMM?3k?&qQnH zGr-o)gV4$9v}X?_I0K5&aNN7YPoz{+uwWg0TL$O-z)lM2IPA{Uz6XlMKzgJ^GnIB> zB|1`jGOtnv2(h7JZO=8OY~nue2Y5K}1$!M(zc6Qy<}+&b61}H7TnbafV=7l;82|cI zpg_*xXfxL9bf*aq9NX@lyOUi2e&;T*s$E{T2RQyY&r5_o0}zDB%gY0>!liv@U?_x8 zmL*I3bap(h-O(ySff_%1=GxCBxCuhVYyn!j;ydJ zvUY>(DCj|Q@{Cv}ZQwu(m`MO`2YR?xqgWk~1JHqg2q*{w0q$+EX$F{kU{9El@fjc+ zgJxLCh8f}jiyLt5-@ktkRL<$5x_~}DLJA{JQUn6NtC4Co_?K-(UFC&M2vKDOY}nFr z2QYUXa^CQe$ehZg&zQ@g78CxeeL|xbwgvo1hVTTGU@}ox^B%z?9k*82jKMl}CeF^NFFFb)Z zI*=t1-U05VK=u4}`q`QDYzvTr9=@HZ+dZS%xbm9cjT`7S@3VAe5-`5^`ju4X6IWO7 z6$nIOPr9vQVN&2oT1LhbzVH>MEISa`@Fhg3EH(G>N4yNdHDba0nHEVmm!Hcw#id?# z`R=*$xu5-vyY7V_Cadm}OeUQ+&OwxtCqYQaI5+Je;WYi53&!eNB0^Oh*nHcRWDR-z z^0FH%$5R(#rcZnn4sZ+B`7}`v&tq?5M1t};F;;O_pCCfb})Rd0fwOanRp zJP5*$(d-n+FXZRu(p+pC08y40e_J~{m*g7Hs1M-e9^=@V2XNuk0OJ*`aD`1C3|=>f zDYyG!UcCwIyD{pPoccG9IHv;r{5-Z^V#HO0)dYZpGc%XNmpXo(939z{MN)KetvS}w z%5BoQYABB4{Azz>ryubH!kV>gX+&(?wL7nBlr##EV3_<@)`08+sdPQw0R99(v+5Ke zVymkG8>`Q-LbW5n80b=ffp<3VgSq8+iNzE`W(BeTGP0i8nIt125u|zXk~~S;NJ=Us zoo0+MHZIQOT6DCR$2&72TU#0X=ijRWuxJVt{GjE0PieG;<bd+GSi z!^|f-MRA)W)wl58diwjheHM$ z0Pg|ptc#6;Ik(-04idMmC>g$5@MFW#)iH- z04Viaa83a@BWD9%Hx-qYV2jd72xRu3Xu-txm;?MxS(g#JG69^$fS$5iJM*2d$y*ak zAB3i{5Di*LQB7>S4Og6Y^7Z&2L{1j5R6(g6+LvTz2N!?B$);Sr++9^`M^O_LU<18F z?jn5|5mp)BaW=i^6~mMSp5$PGN?|b>1}IYuuRYn@4!Ru9f1mg}Pn_nBtxQrrqxuWa z&7!Gkt5`sS*R(X;77!BQdRQ`MmBXou+IE$8cWMu zcXuAd9uoJxW~Rn7J&>ia&)Uli3%3EVeS_^vH#lEYIXCre@&euh!1(ccIZEc`=b#r1 zT<5}JMRxFhP=rhbR_efX3Aif(qxBrgxZ%G+B>nlSdf_fJ5r}~m(%*$9+`mj_bnv6#<^YIs#kN^@8ObtiF$-Hi>D=Q6`J9WS)s)E2^2i8zmU47C`SHk1& z8F-by6yBPb!MPadC*uafMj4>JfeY9G$!31YWF2@{JWG(h>AEGwtjP4+*1waVk;>@5@`U#2oFzsW|{J&{`_oE?K ze`|&%4w(>J4lpLeEC=0$TkxKTO~Fo~=nW-FbKB+YTuHYAo^#DGBC|=0Rqv{GzyE-fvN{d$)}c-tx7g3@JiqPfvNcOT^hAS0BQo{={GQ0 zq{^qhY4oacZl|+~v059K({n!*3nW|oog_PSzX^^mwIgeLj81I>kD_BIH8r&<-qRTz z;*&pUOt>#za1n(f%wmB*SBETLU1w!DYE?}3yFNtn^hFB`CR2u?->e6X9EHm?TL ztLf&rWWoB(_z6(Yg~rXMy#cEI8Q-zk`gliBfi!zpZY-?^V-DH!Ahdm-#F>sk#E!U5CG14Gpn zaBPOudBJ|e*c@UH!ktJ>P*70VJ6j;f0W#8x?#?zaO}NTx7Qgl7PyDRAT8X*w!bi$B ziAP9Fg}tl)9cyKPSxIR`YOe&}!vYbq?NLf1MYH9#bku+5SPl^lu&$rXi>@0uj8`F;Z;u7WF<-`#8C z(<#HPt^ESNQMO?lcX-U&uQ_GX;uXFsM46TYU+{DX+!vw52lXz^@MN@x8z_tUPm8lX zU#f4cnA5vnOh7;7Y}P3Whl*tlqB-uMX_cO<))|=dREByHf3z^?uV)7-(br2c2mrbK zT8U9V*_|WhU9{%{kSy1>=gKTb|op8djQtF&dU zlzH-luGyAVrTF0~Z8LgW{&!ZllQ%cUXtDuDV!bi6oFkM**=xPwiE)v1LiYL}i=Pg~ z(Q+o7dLy0&E`ku#HK+;4%g90kbW2L`8bFg6|JB|wS zYPasJGcr9uVTO*5&Z^;f49w-c($esE)nG*f1iM=hD=k((iu*)o$W5~!rXya9Au$OL z)%*zvaO91yt>)FlPi;Dsl@aDNs?(r8;R!s|G8%AY+5vSiC@?UTyAVs+T#+X!Z?Vob zG^B^y891yq-QHYMH;FGn&lZE=eF>+3oF^*{FG4kc4@4GSCP>%=;b1&{wXV)qDjrGNm=Mgc3yj5v5YhlPJS7?0qt z*7X5`R?YAfxMBYfU}VGi>r0gh&hEUwe->DXN1d4nKQ~~bW*UL+*{ZWSxDHJmDXC@mJYLe2|fs^NGyKsBMz}s8`TL-B)XWgT_c^Q@Sl>G2Tess6bHZESVRL-gsixq_Gt~4r7){MOFL#9_S+R*b zAs)|ynf%LsD2|bC1eR7qet^~o+AX9JFc#X728T^0!x7kfC z^gl{l^@{i|FUN0BAszt6nZuJbQsd7pMWF4!jNrm;#o#GSNnVYO20>SCcxkcP7!5~} zgE?XL{hW(&M%Y0z{ecrDDci#mJ_CF`2L~#^=0WcZPRIU_!3a}vT050`p|8HQ%06=n zyPnW%&V7u3UAi&h@>(97nUcCzE{sFq-I2Id@z9DbWitI zhnV>b57csb%FEcC2dDh0Dg%g8=qI9t-O6=jo^R87^Qu--KRE%zf^142g7{6WEt-zI z(?M$jRI~h$CqxTI(jkxjy*UyDq9N#Q(fWAWAFKW5dIQYtSnY1R)zW$%o8L$#6L0x= z8_orFds%JLtrlB<|IOR+Bc+lxZ_HX)cHtg5d4}v5US|Os{UQ?mI^^J3Im@ASL=?RI zmodovnPeA;k#$^QGq!&zxN?0lAaav$s;sl#D4Q-^n_7G1Zs=J2l0ySO8A}sl)&BfR zHX$!8TCP(OIUR}Y7Qa?n9rZ9FdU8x7_P?Oi_qx!`(f4UV`?r69h&@7gwRnr=kJFtI z7cmUo>~ozdo&?FP5^FQ600u$fG|F9b-VeJYanmtw329lRfu4w;^xK=QM^8XL&s_egOwpCQ)#^SXE zSIye8MYOE(_1ft8M`mgXAx3eC?SLz?I$1?qHR&;GHKcjfpjxtP^5}mrAMy&k{5^c7 zkS9(!;A7@HRdmxbN(c8l`11>tXy-f$-4~E8S0&4|`E5F%mHqk||4W#+r^ikzemRAi z@@h=|r0jEoJ%h1+a=$`dvaN3iH%4ykm*V~jb=%LY_>+-zurkEk3rOh0ze|dB{zzOF z=bd`lHb}=hncv|kfKIH?60P=2JPHgRX3A1F=TbQ|QiYa$6Nrq>o?xU-1@>y>L-q1c z;|?r{;Zse~978h!nm?+;=?w8)BqW;`W1qB(A{HzW2V6u^G=bNbLD!cFU%x>0z8`GY zfI<^Tti;x=`qqf(+GtP(yJ7)enkXjRq6XQh_mxJ|gFBfRWPf&}YoU_3jU>?w`<<^Bwv`ie`OGopZJdhX0`awXUKf zWwyhvphQKyA;nY_8S-@DtbTKhfA1aA`wP{JVOH)Ip_KM-GNp)T9{;J;0CN!BA}+O1 z^SF!a)356zoPI)EqY_(l+K5-3B=C?0Bb_;T{{6tSfoahY)1&h=G3UDQv`8;B7p@L& zT#nGuo50wU>jOw#vzVYfW%9q*g;2hw{VHbBX}6`TgfjebNw!u4eOvxMYrI@h*X8Ko z>ZhvFZ%3&w#`I9Dv1HSAB*Gkt4G`nvIYq&>u{quF)2=So6$CyJT$Rkans%wA#uxFn;OafZ4jB2ao)(FKqgkt}+`xWFGdvH{d*4 z3?lkm-NR_s8kd$g5!sb2!b%ukGWG`24>|l)ot;-f?T}65LyD zstJ2NPF8Vu$~V9Kot3qDAC$A2S#2+AQ-QJ z#RK93&fm2-3zW)m%lIMoFqKL&t889LBTPX ze7qT-^tvVg-QCDbr0?Ipky-?mVUPwtZn(%FtSXqODVeBaPlQJi&JREA(luu}G9GbfcG>eCDQ;Lafp~~U)y(gPZQoTPMnOUF8MWkDixp3&FZ zh;~mMx{Ckx0>i98nQqRD)bnzCP=aZnlT&XOrdOf`%7kFPY;R|X;>fO@!}}hfY>jIO z5kbo!&0=!$4>3aoBwrb^jTVYFs-acp8V>X&G&Qm{tc?}!?1%nCYs~*u zy7kS3;IdSjN)?a(Fx4y$p{Nmdj5d{mWt@#a!W>%@523nrU_H?Y?WCKimlVe}Cuv^Q z)w>^s{c{Qe?%2rY~Wo^qT@MEWrc8>WCp>qP+2an{z z<4A7X<#COgkDdvBV%Q`c{~n2ih4n6Ub6$$E2xj%uuTei3bnsE zA3ldC1g2jfMOB+dL!Ha67W@)B$WJyX!EL|W@50lOB)SHh<#jNfj}W~&orSyZec)p# z!uR%jbogSZu|(`JYChD7<`X<9pP1cJZSOME`<9NV7l&)(U!R2}xVSG3gqpnAflVDm3)GA`nx&Wcqces$58 z^C)>~$}Mta>-d5ggXqD3-9bn#h8Xm_FbuMcdJWAoLCvZ+dtSGq@$E+XkK5YxY|5-x z;}TnJD)Ci38!xqQQ6=LRn@+XhtpS3-(*d9VZ%_`o4biA&>ax~82C~0DY_iE_aZGqT z)9FGv;a;#%IfAf=Bw#j@x|#{m4_7UqRr+47rn$c^UQ~R>GCGwzw5+DdnfkrDtEx(E zw&3fWBW=}-XNk&_eC3PH6;LVAX^-wIYnNV7=wMRIyVwv4jrMtt~9{N`%dWbr2<^_D76 z&Erk+km553#rGjXt5}?{J_<}6UhieY$OJr1NlBe_<GzNerCa{2%PXQ_-n9txr24#l)I8P?jfi#?2>Ly_Eof8rNkbB1=ulPdSfnPG z&Zt2H_^fd2$C`D49+#+XZSErNB{>{P#a&U+=Z8K_^{HTxZtm38wzi&W-Xm%siOU~r z<@O)ZjDB%*m|YTkdBUs8vD{r5x{q=9{iJn+&8!0xRwf$6TYO)z9eJ2q3+3jk$?FTD z5nc>UMRPefx0g+XW;rHLx-`>$REm}39@yduVq>VP-oN~pAAG?XWTo}kZ%lGsrl#TP z!0hgY%krncdvzCz+ZM2K+U`AQz4xG#p#OCD`!_im_% zf;}ox()z#~bc}Oz8-$w4^};^KcJBY%4%XPUT+_-OdpIj`X1I&}#Y=jDim2%=7F|(Zuwn2Rs-%H#l?tu81uP-Q#r4Sn(UubLFbOSMnR4}6tyICsXQLCDDUbt1@*J~c!?+1yyDctW&m z2$rNmp6Z8Gly8ULY{cjg8+ixe%|=)hOe93%ZShFxIHUgC(Cl|`6a)TzrE8OJq;C8J z=7S|-+0CzaaY7ywZXej-7S!N|6G7W^F;?Vik_V<#bWCLa2Djtc4pagVE#FxZnT<2T znv-EXNx6D9^*$USe~r6ur>hqG4vvMe?Oq{M1$usuoAao8wL`;N|Q zzQzjG0CDY6cujvXE4E->b!XR{w2HPCls_ah0EE8vNcgB<_E8p*JMq>+g zK~C^7VuMXRGbfV3H3u`z*{p?&49qvKMFTdvr4XB$u2}>q83}14@rRb0!x!@RBXQyI zlXmXJu?Kfs&K$OWL!7|CZ|P)U=a!wmM#yFi1n?NO3X4>i)GK^XUB8p?eq+>Bk;Uri zA$M1v?yVQDbYuKZ*O^SR`$>&+mSqmsv{0s5;J+4k0uPq7Al>!9`-alwj#{OM_puBj zE7IT>4y?wxA2bVwqQld^+xO+r-2+h~UR&7%ip_SET0FKP-Z_|$?(#YJjXvUwk4Aqf zCV4j-;?E;le&|geIc6B9Uq9)xsv8*;;Fw$+x4bIMJ)j|3NI3A2DQb(Sg7IHSlC~2L z$RiCGgZNZTwQ|QOA$wUMR=Y})M2aT>dOZsTdehw#71VpJIG_&!+F|2h#gLyBloG()^a~_6ip6~K|+6XC5bqy$$Ja^%H z_pS^a>i}8EsuVV>{Xg-%nA2?T2b)bxdkv37+Nk(LqP{Ef-?H4bMP9v2;8O9R8bs8c-+-OY1o?jx*!GS2|;+~ z_2IuEC`@1$;F`0Ag0{e-2>8rM1$Cywkp{E2wIT|NIO;~qsR7kWAb+T!pm65i$l?3i zp?mCM^@Z1==iAUdr_WL4ljZ>R176xB@4d+x(yunsJ zCb_ssyM$4T$P-Sy=n@mvf{OMXj0AW;JwHEeza6-P2N^Y99n^>M7jrm=`zNN;l(nBr zpYxmaH(dIJFe`ez%vPoAf#}C(zV<=U=Czyw>f7ozi&Ns-=TUB6SLLQ~9jpFBVqXVa ziZ*VtyOuIm3SN@Vj-th)^(A4cRMUJys5UqVEYcx0;Qu#FI|r|z8{?y;X~<74QV4#a z^QIQu6N*M}$)WooB>(i~_4I--Swa3Hb%6T3ioV*M+d zUb>Ie?k4}5Djl3JBTm?Mz0R7aQoLT1wg2o}3H;1s6h>+mzdFLyG2d7dCJ`j(0lRN z%=T@63#u|+xYq3VVnq#tl`IJ_opPogG4(=>w5Y^*><$F)M^Pj@i4r70U1aB-mm3gZ zgC1o?#pAseO#Z{I3h9!ZmRcW?oAvJA{_UhLhQ-(oUQum=SclP4cb%T!d;T0?0e~e;hyF zo<^)A$D1v7t3OMcq=U=0%#{=X zD9KTXus%K8yxqvf-y|55V===4%(ibYk46TXj^u#rLwyFf>Z7>B0!O}v8vU%2tHN)+ zn03J~=et6k?p7X9PrPKE-Oe0_(ICoCWC^YlgN0YsAJY@GGI}D&1CLDy2Qf?+j@7cv z*ItA9tUviTY;2*Dkt>-KWI*pqbnNze+uzfTGek@lF0;8UrzRP}pgs}ry!-mmhHPzk zs`__>K-ay}G6be1>o7M(=79v3w4U$qcUbsR5J>uL%xIOJ(s=)MaYOl5>@k{A{Y0Hi z3P5(rq_8o(e*GFYl*CbA_isESgF1!7Zo|}6Ra)G84<{Jy$*vVCZ+w-B(0?m3NOYN{ zJO)TSmPEj9F+yd~e1F)1@%4wb!LJT$zq#z60eJ_WWM^&hC4@H$CArAfboF)$Kp`D-83wt5{1fpwWzh;%D9 z9Dg_UZd@V}L?z)dXGM89D`(K==b=39d$YYd@_h8IJ2d)H&ZUEJz?QE)gN|{$$&Z2$ zeJuB(rd8}kL(ltIuAr{LiuK+U*7XT^MayjLQIOEn$C1&4FJ_}TU|k>w^C#MUZcf%w zM;5)nBdJfct4nhQGAwK82#dv^?V6^&KWGibS3aev_ zwPZvm6oF)JUL^BgTpT0TlG8aqqXDXsN-n?hlkM;6WMj4Ojks&I(L1^VpVKkozatxc z`{F6l&rR!A?nJ8bwxu|?F;&2|bNRaxE90?M2E_T>xYK=Am*#F=h1U}ws7t2z$e|fI z@|0v`MB}#H6}yp)?UgnM{))si$gOXW-?u7HBhACm&>Ur-1h&StR0;-)9#P~dW-RBq z26K9-O_MH$OUMN$3Cg9ym?U*42@Y@7Zni1v>cHMnz%IY2h}h+PB`B7@_DCDElGNR? zzQtspqj=3*my@^uY%bH!?R1-acPR|Oa0z#RO8+mrdyjxfke}=n6{}z+v-Yr?M1o?2 z$C0s;iu2mXb`?*)o`KkY{uF;usG9yIJ69jo zlRtnv9`2zruB}_w+pfl0F4&*Dsm%ZCsB_w#ca%xyncO_SIUn!}b%J!j$4A33EL|Gv zk8*y0#RzS!vl}2vfYFMTc5pM^4X`gG{z-US^#YK%Wu7<}$#jCd@OMvBQ7S_us_2bn zpvgDA{AT=Y)uJx0I8RN*rwvo#MHIDP((-*}3kn|Lv&P#7S81S%6&n%_z?5*uG)myh6tZZjQ z(@GQP^c*5Y$B@p@Lvb#T!95}_E@;)bUI!;h%k6X=5?)j_!s0%_vre35NOs9~UX2?o zmX+15LLaR$myM-==kq}?cx9#RWLve)v9L6}%3}Kd$hfJQ*{$`EuuE{mSV8O|jq+6B z>`bv{NWS#1?P`E)2JjS@eGGV~{fNdY-R1o67*3R$wQLs?@j9<6&N?SSk@}^(nkXn1 zc3`o(PF5HLAy6gPC`^7DLTD8h+mS6RjVQ)g(|sc1tjCFp^V`M_^IJ_M{I;|lbl;0@ ztiV}^z{rz__isT*wucf=t5CyS;7Mpr>dtNNZ$--0gv6vfC~sZ&uBUhFtXub<_ry?B zCh2*Y+-;Mr)o=oXz+FY^^@IPM;;jc)O0p#(p9a@1PyY(nNr1a6_zgx3BI9j>=xA{6 zfVfxt7M$ilp%!f7r7`H}D=+-Yt1UR)uIN68)UCz?{8=Nx+j$mArHYy9ypdG_ouif5 zlIhad0Ba0exaxjor@Gx3hG}`7Y3uf#fTtz;V7#7BIn%K;9#j?XE+R6u%c3#`v+@rh zUwSTtNuZ{w$qt5DOGyD&9G~Wp)X1Cr@Nq>Dx_t8yc*g>%$&v!7iHgJgec$XjUx%GC zJYG`*q7EX-Qqy|X&zYScQE(ukHKH@L0H@S`_fTAn32W!m*ehy?4nxEv<}X`0ojs5U+ie}Bo5i5i(XsN!_J>Rh?7 zW>xpmC1^uSMziUdDwCF}YJ=@58xom}hb6r!Od$FluWg;L=cM!lbX^$A(@x`iad!KE zu=;2icj~Mcu7LwzcR@)zHxYBE#yZ{Y*?e^vT@5%nB_|W=#U+HFWlw zJplKcwI7j6;&y5TVgB~!vRJUqy04_t|NSl(9vWyx!yE8R4ifkj*d60RxXOk z*?O^XdgmHE0}v-jcC87J?)Fcg{090RgGsHLRtX%2$Xs?bfK;=pRx%(a+rwPYdl;5D z_~?QLy0KCIdbGdo?m6yDI4)8@wwPY7wF}9AL$(+dr8-?b!o+G6i`~t96pnT#!B#g(P4K@iqOo)Y8 z8{h{((3$nRy#_D>fRux<*smcD=z-hmB>WJ-Hha6J>p&L*3GnRA3lviKy+I*NP0#Zc zfS1#*GF99H|H7af0AB1*LeMQ4Q2jc&E8O6Aev)TB+TsJec&jCFmZ2yR;XyU^x$d%12Hf-)K1YcWt^_^)|OB){pp>dQoabXRycMjk%V^aXL z#yI>FO{M8*KH#TKY@Yyj4G%zei4qyUY&VG2jEO^BE&z+=d9j`YsdV071d2hRetEkC zFoOWK1vIY3AOK1p$Xk}4zLC9?&u8Qm=1jjE&ZM7kH7z` zf*^5Vhu#$m4xyWWDJ6a&qun3LITRCH{QY%t(g-byD@lN%QX78aT7;45a0xBmoy@SB zOb7SwR2IFe-i14)m6{SH?0ozwV3oRZk4ce9ckWcU=uc{Wxz2@!KV5Tqd%~Wk&famh zUzj={9x=dw*qb#uS&Px}#Ba8HW~_Sq7cv^)ECEfs1S-w7F9d2E)29~4J0%59+lu#T z)31rFcA~xu`BJU2347fgqk$&oaFJ5L>8Hpa(kDY*%NNO3e9`|_Dy8_DY*F#cY!k{F zlkA0YMY8-++$hNcszk+y{VaV1ny<;4iZ`-#v%1&yMLG!e$EaVHys~Ni7oQP{!My+B zV{EM2I2!BvXrKs_=qCpG@tY!fsj!}1Byl?bsgp`AM`$O3mDKRsDIlHTa}b3V78U}a ztn@#C`V$b7F0uTIv>M|50TYrBI9Flvo&6@E6$+1!7l!}?V6LevfT4}osYtRJLY8`V zx!xHS0W+CMz2&>*xeM#5(ep$Y>-C3-Gso`kA6AXBG4v7e{uL0*Z?3@&cIy88>$@5+ z3nWAdxqkR}vVd}fAArkhGtGs6o>@mBJCo;m z+W@uC0Rc^CXUovF9=4!Q8KgHq`wt;|F#j5lWV-b z*c9nf9+9%M`{f#4;%>6tnAKQ5Tduu)mb_Dm7B$7A5kATEn*6I6b<@8?RzxodcyKs3 zn-azgI+Bs83yu^yRFdS0x_5Coe?%Dt#TNW{`thWf(~xKaxp$#t>o!UT9AxEcd2*Sw z8(4LDBHCGVYzo&7r!^%aGNQ>u0-J2W?GCWA0M^wmjQ3^3yyjrX!$v|ObBo3cP3icIkX%mHYDuuO9R!O~D z6mk7vU$m{NxbEDy;G1On<=nfIKG0SL?lXn1C2H8MzhBiM|ow(-214q$l( zD{{a=@?aHRO5zNzgx!-Tf;E<)@CVQh9RxX>hOeHvp08}WBumIx1%8w^iF3ScB<9}W zRAKJ}T$3rC6{x^U*w<_Ri&JG&-LFgBT-a{EMs8xpbNslAI^%+wg6{$W_?1ApQX_Gc zKRuPUr%g4zNLI)<`{yI#7>a)x^iyV!i?Yb&e~Gjq0k=LW_=B8yk++7`7k);^QPCW$ z9CDF~K6vIl6QOk*v&p1UOj9R!Z$zY*Sm6^! z6#;0!krA3E6dc8&8YMR8WU=l*FN!rgT;t%J$?U8l{@72KFjZAU>YxS{bGN`Z$qMjJ zo!18K6SnoUQ8zCDu}vGub?b3zKkLZ&zs4Wzec7SPsT-hhs;I9KxopZZNg;>M>zqkZ zYaBGHCiSjML6SVT09P#Xz2t~^WKgwHh+&&*)@tt81|40G?7HJ$D2kd4#zQFnwtPoP!j%omx`QvxNvzk~kih z1Hf#!8kS&U(5iO^Ojd|}Gculr+jbR56#17SAD;PttYq(x3T;u`rM-070aka+UNdy> zv4`aojH3-qq0TV03x$v_OEeNy-Lcs3^@9JW4w zZvVMZ+UVI(ZJBh^!_>UnNG`lEGOUs#E$D|)=;5ZM0uBwRYvUX3;3eEdqQMcxQ6`bE z_Ec2`FHh+CQ5Rq8(xDU-{}-(Q0g0POEHs`^tY0pJmMRXSkUP*SF$ie;Q~Qe+MO zQl-1`K{MlLzHND)dVoDER4&bzCc9MQZ8_Fk7CM*Ww5k<)tq->Dgod6*+Y*rb@5e``69autg+2So<ZHE!k%%zFTzM-DK;mH!@Em|XyYEbFJY?&HeGhw8!Z<1ziE>=llg z_veXFo_)7&ue1#{4kW20Fr}&Am<@wod8!D>5S^d>Xd7s%-Wqj^CwtTLqyw~YsJnaj zDO1Dwb&nOBebEbyyR2q#nL`X4>i8V$SmhY<0Od$3p)!OJ>|{r?B>Hs1{m+7*#-t2@ zEHZ)39hCq2sTMfA3Ilx}bsfT^ig6i(LN}hZ#7#k3(x9`p!zqJg;^l zuI(e8ikXR9rm`5z(?F9e)Q;oP${e$kA4wCn7*-=U1MqL3xyx{p!~&>GmC)`er%1+@ z?xt^2;@_O?%7CdSBK*DavtOfKPNPR1R8ROUBkbdN0Q|g?g^xSI!03>Zlb$!h zi^Zhkm8FSeX?yhnHCayd6zTbzZjH`I{Fm%jbT=(~%ii_X*O$NKBJ~nN+Q-x`N7M)2 z$@2U;%iwmup=4^*N}0%a+&MpA8t^(lDkyuOa%DO-;^xID)%kI{$;50cAibqbx7n#j z%Ol6OgHgt?JypGUlfyo>Y6q4w&ftEra)6!?d3bnmd1UPEMr3q{AN%rak%N!iXQ1=h zDy({4$wu=qVspGcP4;i4oqNpeg@jBn{0A(_$$&JxScERD{ z?QrAu&y}8Cz-tOBFaOqQl$^t6)kwvEJND;KK@3w9=zdXs0~?6d_RRTMe^SZmHdv^d z3RUf9^A)u*@#VITwd(Y~E8{kivi0Ve#L}zU%7}Hv`k;_v58MJDqV|=G4yePlALePh z#`*%92d{o-AOBUU_3cfG-_tVFQqAa;+sQ_cSVN;Q^N;QSJ3I$NMj%KJ{@oZu33YNa zl+A6wHY4Cg40(EKntIh5O*SJj7P7tK`yyM1J${{CA2wEF(vv z)fv260i7juD1Sfc4{1-=J|drVJDN7HC&w!w91ZgCzdg@z)yjK0Qmwf7lRWaN5gge~ ze;Qw&mywNdpbzqbRv!M`oDjQ3@N(uelhcidlXJy;yzA5G=_dENRY#nm!fC4MnPUEi z^Lp&3{mF07draOJyX@ck8^eUcj)~ob>%Lxhk6He7yZr%%5fQVZXNjKn`OW*1DCtjyAobVIE(`d_J-u+ma)mvt( zo2*;c!Bt1E{gPYvtKa+`{fQAnc^;Ef#}(8w?DGTTq3&0t)5?YCTM;H59zN2X|Ba{@ zBF{jCE|f}`&}SLhW$*3|4n)mJ|1;4vmz(=3mTA1FCyXlq#A|?Tx!Lm>EL)26EhAg) zU=dw@-exyEoPKU97Rf@v(ATYeX+HlOWxUwK^>DSR(kf-!`q_|wVPO^u=1%Miz1wWZ zk~%6HTB0-=K}6j79@OE|fKxT{rp$7-{_BJ3S`EmN%IQu@f66Uz;9@%6vG}rrq z2Pl$>y)=SkiStMRD{>Q%0jda)9Hnt;k)HvV*-!_sAm5Fv5r4%vQYbxN=g{ zvt+|Uue*%tn`6*CA9KUwwY|OSNbUwz%M>#a;K{1%<5;XA&kP^&g_ZqpxwS@}pRpWE zd$2k9`Xm+V?xM4yz>ImR_~{4eoNA!B0g1KWcAZhANDiB=>Np~iil!hdFIx-y_7W@4 z7mIk_zmeiGgktjo)UmJ2XPlb7CpgD1-62QYobYEu`T6;HAddwK*js`f4rhXpADh-! zuc_h3#N1R48$am90G^J(NB1dN;Ik((~Lsgj&Ez6 za)uP6pFqDfMFqUp^<^YV#kHXkmzAZ5G=$=QPp$3_raTR#A=8O%$(r7fBdjXQH>4S2 zq@h;$)U2bf^IBT@UYx#&EClz>v+$3C_bCKAtuI7>1kpUMOiT)gpGQO=Zd>hM?^L`n zi>R18-0l#1tnGQV9@(2$Fqe>&81q8#V_rlI?AJo(v|shQG0)ikdkzPV5$=g5TyZ_zw-g@i3_0C!@&5FPL&Ts!t z+2`!<`D{Zi%@5N+RJdwdUxpL7e0l%tV!wCB#$)#OC}BO-#dlFf?f$nuL`8>+pxxV4 zgZ*+-q_7FDBQB^f!Xm*!S~LCb?P4xO--_FPqp$TmLPCR!U7qg^)u$EDMFhK3MvYuIHSu(;I80)17XN{;buIprjwo+>DTb*m#)8fuyn zN8fbwEB^I5O{(*|Yc~pnFh)*J_042>ucV>js&jnx6B8&>p<99`Rx%=3NSC?68rFB{ z&N5e4!uLxjYE%Mw#k#6AI;y3$d2_f?svQsug9XWk%actb*#p9y-$x?d5+@irBU^>k zeY4M1%k7)DhO6AL<@xi50X~;R5XJzUB_q5;Ze6eW_^Z8KDQ@VVPpoZ2jb(k(ScC4& z-0*T^byQ@Gr$NN+O?{urj_+HQb1g(MGIFeqi-xgwoXE(SUuW59ld!LDY&QIsxItj z6i6toz`>IALg(&FjE^tZ$X>k?%DHXNPL*sh4PE;bW1hJ8H>#h~)Fhn*!k~n`{diHK zFm7Nkru^PyOIlwpIWblQ^NbuPF8DG9u<EU1+e%iT^*MmszKEcrec*pt&dCQZ!R`cpFUlF z({TD0j(IBC^Kn1HdzbUeznkQwl|E4XLTEiKur-IsnsI}o} zfSY3*bXO6ULk?8ODKn$FAekgx^@+kzGYY${c+)>%fLvDMII>0&uT&u7v2B^{C(0)p zmi>pfXVKy8J9Kf8PlL=zRM}j=@xnc(|K;ON4%W1ZY=#=TtB4bWA3%|21jG9io?2BB zy(k(rHwI~Psny#>;jw;R>_2Y$&Tj=ZmD;gF^ySd}s4F$&pUli{+?z((n_r)Gq;#li z=IZBIdepAR@_Q_cm8pCV5TMMg7q#)BuKQ2D5fc@a(tplw$tFnKcGg(N^{SWtR9utV z)vjja^KOKB{$V|JJ0EplS5Y_=0s|R<=QHBXxDEk%VQ9H6VQPHZM}c?7j8ye#C~+0X zKR%pG+hPScb*0*22WzkRA2tD78kks6>FyF@!M8?JY+Yc9(--fjR zI-kJ2IA-W~k2qTvUn?si8y0VEcoBAr}i15(g_4O4sjaP3p1J z?VR%jOG{nd=!`#1pC^IRs-F&|3u_xme8}O6q1^&C)7>*CJ%^ynC*g*rG`afYH_S{( zIL-Icn`o4?(J}JUalPwzuXf^L`cLTa$T|twYK>5H>uNZf79(Z2g^xU7{jZZIaU4~C!gpo8+ryb- zKiL*|A55F-g!Z;@9dgRjfyC&Z6uY;!?4?*EUhXWI`9yqU#ggiK0fqv&wZhn9ge?(r zf+PTi#7IZgVgo|M_-Les{s&2L~@#5SdK8RN!MD0E5BiJMf>o{Dw3LB-qoJ`XTuU{KEJp6Pn(I1=U zzYTk-()2?+Hq~B@jEY);e6oqH@kO5OSLsD2grijnw#waG0730WvN=L?cAi3l{gYB0_ugc~sINn!_?S%B zwSI^3st_rkg<5!Iv7K2u6kv`TYg6b5>!QgAc*d)?z0b3eytm$qJ?7RuV372pogd`s z>Asn)6D(1cI?N3ACJ?$UGc)%G5N|g%2W+=DO1VMsuG@0YBcvbnT!Ps49MDSC0aLO) zG?ZR+J}D_BWvcE$E4DO#VJx)3LY~e&{-Lb|0Q#bgYpL0`<@Xw{;S;?yK2zBmD*w|ns{GHoC z&S!zHx*Z~5olVz9e7$d3UUuqs&x|x2dCsC+Q>)mO49RR~!@uS17;|-RX#FwD`q=%m zK{y-Ax?q-Bbp5!Iv@U6&qC#S_rAg&8iN!A>8L+iz)W~f)e40Kh-mdg+r8AT4J~#iW z!_-4`6;o{r#dof2A6RFT<|e)llo^wb#+e=Ob@qs~bOdasw>&#_n7Td|3CpR2J?*=P zi*NVcf3267pw8?xAphR_+ynMwFOs?Ex<_xD+Ylxw6&~XRtH#x7s&{AB#A{(JEpJs1 z?em%QPn-3vlv5C}1`rN#W$5RFFC#W`rUUO{+p#`ma*Et%-xjaMFH%!RST-u{9h`db zfCqu~IHfn`%Wem--%RSyduDF>X!D0N-%-Qg9w=?Q~ zDfH>?}y9aL-$vHf zJtV?YQc^bXj8eyerOHy*fYmHp>w6s+OuZBwciMdt)~VxFeG#aY#8j6M%@>4HfvmsA zqFi`DE7c*(!HexpA4xjPNKDiktzqO<(ldc42d@OZ)4}*qB>2c`Q=bo0+d0z7qg~RQ zbT$ZLTu>o7`k{lzO_xyr3d!@Bs3IfJw{j$K=Oh{T(?g`aek$hs!y`x#bFWa(h?=K&`NGPchd()8wphF-*|Akcg`%VaN zf?((Zclb|_9I~C%xpyGZym4%C{YTwhcaDH34a!;k{3lIhG`mUwiJSuI@$=`RNS;C{ z>oF|8Cf?PFeyC=w*N&elz%2IpK)LSq#M#gjHQtY_e%imk1UKvhm~n6-(60t|E}8xf>47{v&~J_a*RV> zqAGVr;pj!Uqb%~h$_s9NwfiBq+nZwrXmU_3oCbpEyaB=@KjFU^iY;*_dyhR#)`{4I z8oJx8fFRfSUP5Bb0*mbY{F9`UKs<%2K%(esaQMoGJ+11KF$j7Kre~06-5ajNTUXw5 z>Q3(n{0IMDq91bKtH;0H_rRIouZ-0Ai9^IQ%RCR@pK54yz3cvQ{jR5$y%w?bx zkY4I@@G$K_d@W28(zUKHBI(!^6sl)Z z<1U6BcmhiZpnVO2=ne)q2x5m$V~{RAAsBrqU|A3%%!SD1Ui$J6#EsKF`f_JL(Z(y|hROkBY`TR=x|Z9~0l;{M%IrVP zFD%~={+jAk{I$g;&|Jbon*sLF;OcvK;e(`MdrRwxmo*mfaFAq29oZB$LT8F~8n;_m{VZB*w8n-;U1? zY|g9I=H4hFg0ZN$JMk&#`0?Z5#H!pFKrEdUf_SL#_Xc1tB>*=BtWu_=#$5S0jns!r43(Oeh8#!&fK-5iK^s^X(!W8fxcr6IOsD-Nr635cg0zN64jp;V0RTCG@oB26Rv3`gh!L@|v0l?3QKXX~)&Xr3 zl6cvRx@oN;DfO$11>hm!&>IcZ_dwzNQ%LL=MXRYeBGPW5^#jiQ8JS$| z;QQtMll`Hupf6tsMW~?0!W*y%XC(~{*k^fwM#B^Ua9PKmOjEv>@J_%l2RycykIx2J zxDVD@pk{Qiw=V(GAvjz)R%HpN?RDjat3YN7s>N0z49E%QYc}W7b9V?3KZ|5}WB)a2 z@f The state of the actor after all of the actor's dependencies have been started. * Resources Acquired --> The state of the actor after all resources have been acquired. * Tasks Started --> The state of the actor after all tasks have been started. + * Started + * Paused --> The state of the actor when all tasks are halted without shutting down the entire actor. * Running --> The state of the actor when all tasks are running. + * Healthy --> The state of the actor when the actor is functioning properly. * Degraded --> The state of the actor when the actor is not functioning properly but is still able to perform some of its duties. * Unhealthy --> The state of the actor when the actor is temporarily not functioning. + * Stopping + * Tasks Stopped --> The state of the actor after all tasks have been started. * Resources Released --> The state of the actor after all resources have been acquired. * Dependencies Stopped --> The state of the actor after all of the actor's dependencies have been started. @@ -113,14 +115,16 @@ In order to effectively model these states in Python, we propose using the matur For a high level view, the parent states, their substates, and the transitions between them can be seen in the diagram below: -TODO: Insert Jumpstarter State Machine Diagram Here: https://user-images.githubusercontent.com/48936/107506089-43225a00-6ba6-11eb-810e-0ac14bf0e1e9.png +.. figure:: jumpstarter-state-machines-diagram.png Also, in that diagram you can also see the ``Restart`` state. We propose a separate state machine which we'll call *Actor Restart State Machine* that models the Actor's state as it relates to restarts: * Ignore --> A special state which is ignored by the Actor (effectively meaning we're not in any sort of restart state). * Restarting --> The state of the actor once it has begun restarting. + * Stopping --> The state of the actor while stopping during a restart. * Starting --> The state of the actor while starting during a restart. + * Restarted --> The state of the actor after it has been restarted. With these states and sub-states, for both the main state machine and the regular state machine, we provide a clear public API for code to hook into any part of the Actor's Lifecycle. Similar to how, for example, modern asynchronous frontend web frameworks like React and Vue provide hooks into the lifecycle of their components, `transitions`_ provides many different hooks to: @@ -131,6 +135,19 @@ With these states and sub-states, for both the main state machine and the regula With that base API, Jumpstarter provides a solid foundation and a lot of flexibility to help define self-contained pieces of business logic and facilitate communication between them while maintaining a separation of concerns. +For reference, the currently proposed transitions (as can be seen in the diagram above) are: + +* ``initialize()`` -> Initializes the actor without starting it. +* ``start()`` -> Starts the actor. +* ``pause()`` -> Pauses the actor's tasks without shutting it down completely. +* ``resume()`` -> Resumes the actor's tasks after it has been paused. +* ``stop()`` -> Stops the actor. +* ``restart()`` -> Restarts the actor. +* ``report_error()`` -> Report that an error has occurred while starting or stopping the actor. +* ``report_warning()`` -> Report an issue with the actor which interferes with some of the actor's functionality. +* ``report_problem()`` -> Report an issue with the actor which causes the actor to be temporarily malfunctioning. +* ``recover()`` -> Recover from a degraded or unhealthy states. + Three abstractions Jumpstarter provides that are addressed in both the ``starting`` and ``stopping`` states are: 1. Dependencies @@ -156,26 +173,26 @@ The proposed public API is as follows: @depends_on def account_balance_actor(self): - # It's presumed here `account_balance_actor` is an already existing instance of - # an `AccountBalanceActor`. + # It's presumed here `account_balance_actor` is an already existing `AccountBalanceActor` instance. return account_balance_actor -``` In this example, the ``AccountBalanceActor`` maintains the balance in a single user ID's account. The ``AccountBookkeepingActor`` is responsible for logging and auditing withdrawals and income, possibly passing these audit logs to another actor responsible for detecting fraud. Instead of returning an already existing *instance* of an ``AccountBalanceActor`` in ``@depends_on``, you can also: + 1. Use a factory method to initialize a brand new ``AccountBalanceActor`` instance (since every actor must inherit from ``Actor`` we'll define some helpful factory methods in ``Actor`` which can be used by all subclasses/instances). 2. Return a subclass of ``Actor`` and it will be initialized for you, proiding all the arguments are available for that actor. This uses the `Inversion of Control`_ pattern. How this works will be left as an implementation detail, but Jumpstarter, given that it knows each ``Actor``'s dependencies and has them all in a graph should be able to satisfy dependencies and inject arguments as long as it's able to find them in an accessible way. Resources --------- Actors have resources they manage during their lifetime, such as: + * Connections to databases and message brokers * File Handles * Synchronization Mechanisms (useful for short-lived actors) A resource can be an asynchronous context manager or a synchronous context manager. It's entered whenever the Actor is ``starting``, specifically just before the state machine transitions to the ``starting -> resources_acquired`` state. -It is exited whenever the Actor is stopping, specifically just before the state machine transitions to the ``starting -> resources_released`` state. Given the asynchronous nature of Jumpstarter, resources can be released concurrently (even if there are synchronous resource releases that are run, say, in a thread pool). Additionally, any and every actor, once resources are acquired, will be have `cancel scope`_ (acquired once ``starting -> resources_acquired`` state has been entered) in the that can be used to shut down the worker or cancel any running task(s), whether because of a timeout, a crash, a restart, or some other reason. Even if the task is run in a thread pool, the `cancel_scope` and fact that the Jumpstarter is running in an event loop means that more robust cancellation of tasks may be possible in future versions of Celery than have been up to this point (see https://vorpus.org/blog/timeouts-and-cancellation-for-humans/ for some helpful background on this). +It is exited whenever the Actor is stopping, specifically just before the state machine transitions to the ``starting -> resources_released`` state. Given the asynchronous nature of Jumpstarter, resources can be released concurrently (even if there are synchronous resource releases that are run, say, in a thread pool). Additionally, any and every actor, once resources are acquired, will be have `cancel scope`_ (acquired once ``starting -> resources_acquired`` state has been entered) in the that can be used to shut down the worker or cancel any running task(s), whether because of a timeout, a crash, a restart, or some other reason. Even if the task is run in a thread pool, the `cancel_scope` and fact that the Jumpstarter is running in an event loop means that more robust cancellation of tasks may be possible in future versions of Celery than have been up to this point (see `Nathaniel Smith's (of Trio) blog `_ for some helpful background on this). The proposed public API is as follows: From b98c71a591c2428acbcc8211575c81b3d9168aab Mon Sep 17 00:00:00 2001 From: Micah Lyle Date: Sun, 27 Jun 2021 09:46:20 -0700 Subject: [PATCH 11/14] Resolved some formatting suggestions from @thedrow --- draft/jumpstarter.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/draft/jumpstarter.rst b/draft/jumpstarter.rst index a60bf42..6f6c21e 100644 --- a/draft/jumpstarter.rst +++ b/draft/jumpstarter.rst @@ -78,7 +78,7 @@ It's important to remember that, although that is the technical definition of th In Jumpstarter, we've chosen to take direct/literal approach to 3., modeling the state of an Actor using an actual state machine abstraction, namely a `Hierarchical State Machine`_. The difference between a standard State Machine and a Hierarchical State Machine is that a standard State Machine is consistent from states and transitions between them, but in an Hierarchical State Machine, states can also have their own sub-state machines. Hierarchical State Machines help both tame the complexity of large (non-hierarchical) state machines and more clearly model the relationships and transitions between them. To give an example with Jumpstarter, we propose only a small number of parent states: * Initializing --> The initial state of the Actor when created. -* Initialized --> he state of the actor when we start it for the very first time. +* Initialized --> The state of the actor when we start it for the very first time. * Starting --> The state of the actor immediately after calling ``actor.start()``. We'll have to transition through a number of substates of ``starting`` first (like starting dependencies, acquiring resources, and starting tasks), which we'll explain in more detail below (think of this like powering on a computer. You typically have to wait a few seconds for the computer to set up its internal state nicely before its fully operational. It also needs to connect to internal and external devices, and be ready for operation, etc.). * Stopping --> The state of the actor immediately after calling ``actor.stop()``. We'll have to transition through a number of substates of ``stopping`` first (like stopping tasks, releasing resources, and stopping dependencies), which we'll explain in more detail below (think of this like powering off a computer. You typically have to wait a few seconds for the computer to clean up its internal state nicely before it can fully shut down). * Stopped --> The state of the actor after it has finished all of its ``stopping`` activities (think about how when you power off a computer). @@ -258,7 +258,7 @@ There are two primary motivations to discuss. For the first motivation, one of Celery's main use cases is to build asynchronous, distributed systems that communicate via message passing. The `Actor Model`_, which has -been around for almost half a century and is a tried and tested way to design and build +been around for almost half a century is a tried and tested way to design and build large-scale concurrent systems. It very much matches what Celery aims to do and has shown to have great success in projects like `Akka`_ and many others. The `Actor Model`_ also works great with Python's ``async/await`` support as messages are able to be @@ -355,8 +355,6 @@ Copyright This document has been placed in the public domain per the Creative Commons CC0 1.0 Universal license (https://creativecommons.org/publicdomain/zero/1.0/deed). -(All CEPs must include this exact copyright statement.) - .. Next-Gen Celery https://github.com/celery/ceps/blob/master/draft/high-level-architecture.rst .. Jumpstarter https://github.com/celery/jumpstarter .. Reference Implementation https://github.com/celery/jumpstarter/tree/actor From fde8069a92b53e96ab6cc7880f7db93533dcd8f1 Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Tue, 17 Aug 2021 20:56:39 +0300 Subject: [PATCH 12/14] Add the Jumpstarter CEP to the drafts' index page. --- draft/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/draft/index.rst b/draft/index.rst index 553ce54..ac14ef0 100644 --- a/draft/index.rst +++ b/draft/index.rst @@ -13,3 +13,4 @@ execution-platform.rst configuration.rst observability.rst + jumpstarter.rst From 8a69221bca4e1b5dd3ac623c5eb8db596f3df6c4 Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Tue, 17 Aug 2021 21:40:10 +0300 Subject: [PATCH 13/14] Fix formatting issues. --- draft/jumpstarter.rst | 89 ++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/draft/jumpstarter.rst b/draft/jumpstarter.rst index 6f6c21e..e153271 100644 --- a/draft/jumpstarter.rst +++ b/draft/jumpstarter.rst @@ -42,7 +42,7 @@ compatible event loop or used some other workaround. That leads this CEP, whose purpose is to provide a foundational asynchronous programming framework for the broader Python community modeled after the `Actor Model`_, and also -provide a foundation for `Next-Gen Celery`_ to be built upon. This will, down the line: +provide a foundation for `Celery Next-Gen`_ to be built upon. This will, down the line: 1. Allow awaiting on an asynchronous task results: @@ -50,10 +50,10 @@ provide a foundation for `Next-Gen Celery`_ to be built upon. This will, down th await some_task.apply_async(args=(1,2), kwargs={"kwarg1": 3 }) -2. Allow definining ``async`` tasks that can utilize ``await``, ``async with``, and all +2. Allow defining ``async`` tasks that can utilize ``await``, ``async with``, and all the other features of Python's ``async/await`` programming model. - .. code-block:: python +.. code-block:: python @task async def my_task(...): @@ -64,14 +64,16 @@ the other features of Python's ``async/await`` programming model. Specification ============= -Jumpstarter is a Python implementation of an `Actor System`_ (which utilizies the `Actor Model`_). There -are three fundamental axioms within the actor model (quoting the previous Wikipedia link): +Jumpstarter is a Python implementation of an `Actor System`_ (which utilizes the `Actor Model`_). There +are three fundamental axioms within the actor model: - An actor is a computational entity that, in response to a message it receives, can *concurrently* (emphasis ours): + "An actor is a computational entity that, in response to a message it receives, can *concurrently* (emphasis ours): 1. Send a finite number of messages to other actors; 2. Create a finite number of new actors; - 3. Designate the behavior to be used for the next message it receives. + 3. Designate the behavior to be used for the next message it receives." + + -- Wikipedia It's important to remember that, although that is the technical definition of the actor, the interpretation and implementation of Actors and Actor Systems can be very flexible. Namely, what constitutes a "message" and "state" is very much up to the interpretation of the developer(s) and the system(s) they're using. @@ -160,7 +162,8 @@ Actors may depend on other actors to run before starting themselves. In some cas The proposed public API is as follows: - .. code-block:: python +.. code-block:: python + from jumpstarter import Actor, depends_on class AccountBalanceActor(Actor): @@ -196,7 +199,8 @@ It is exited whenever the Actor is stopping, specifically just before the state The proposed public API is as follows: - .. code-block:: python +.. code-block:: python + from pathlib import Path from jumpstarter import Actor, resource @@ -216,7 +220,8 @@ An actor repeatedly runs tasks to fulfill its purpose. Using tasks, the user imp The proposed public API is: - .. code-block:: python +.. code-block:: python + from pathlib import Path from jumpstarter import Actor, task @@ -254,7 +259,7 @@ There are two primary motivations to discuss. 1. The motivation to build `Jumpstarter`_. 2. The motivation to, down the line, use `Jumpstarter`_ as a foundation for parts of -`Next-Gen Celery`_. +`Celery Next-Gen`_. For the first motivation, one of Celery's main use cases is to build asynchronous, distributed systems that communicate via message passing. The `Actor Model`_, which has @@ -264,11 +269,11 @@ shown to have great success in projects like `Akka`_ and many others. The `Actor also works great with Python's ``async/await`` support as messages are able to be asynchronously sent and awaited upon very efficiently. -`Jumpstarter`_ comes in to fill the spot of being that fundamental/primititve library to -build `Next-Gen Celery`_ on top of, while simultaneously being a modern implementation +`Jumpstarter`_ comes in to fill the spot of being that fundamental/primitives library to +build `Celery Next-Gen`_ on top of, while simultaneously being a modern implementation and interpretation of the `Actor Model`_ (and an `Actor System`_, or at least blocks for building one) in Python. For reasons why Celery would build its own library instead of -using an existing Actor framework in Python, see the :ref:`Rationale` below. +using an existing Actor framework in Python, see the `Rationale`_ below. For the second motivation, certain bugs and issues in Celery resolve around things like chord synchronization/counting errors, very hard to reproduce concurrency issues, canvas @@ -298,12 +303,12 @@ that takes advantage of all the latest abstractions and innovations in Python's either before ``async/await`` or in the earlier stages. 2. We want something that can be a standalone framework, but that can _also_ be informed by -the needs of `Next-Gen Celery`_. Hence, we'd like for the Celery organization to +the needs of `Celery Next-Gen`_. Hence, we'd like for the Celery organization to maintain and shepherd the project. We may find that we need to make changes rapidly in the beginning, and we'd like to see the project evolve and grow quickly without being blocked by other large dependent projects (like some or many of these other libraries may be), especially in the beginning. By Celery creating a new library, we can both -enable rapid development of `Jumpstarter`_ and `Next-Gen Celery`_ now and down the line, while +enable rapid development of `Jumpstarter`_ and `Celery Next-Gen`_ now and down the line, while still providing a framework that the greater Python community may find helpful to build other projects off of. @@ -346,8 +351,7 @@ The `Reference Implementation`_ has a nice sketch of how actors might look in that's the place to go and start taking a look at the time of writing. Further buildout of certain aspects of the reference implementation (which are also related to `Celery Next-Gen`_) may be blocked or waiting on some third-party -library support. One example is we're waiting for an `APScheduler 4.0 -Release`_. +library support. One example is we're waiting for an `AP Scheduler 4.0 Release`_. Copyright ========= @@ -355,28 +359,27 @@ Copyright This document has been placed in the public domain per the Creative Commons CC0 1.0 Universal license (https://creativecommons.org/publicdomain/zero/1.0/deed). -.. Next-Gen Celery https://github.com/celery/ceps/blob/master/draft/high-level-architecture.rst -.. Jumpstarter https://github.com/celery/jumpstarter -.. Reference Implementation https://github.com/celery/jumpstarter/tree/actor -.. AP Scheduler 4.0 Release https://github.com/agronholm/apscheduler/issues/465 -.. Next-Gen Rationale https://github.com/celery/ceps/blob/master/draft/high-level-architecture.rst#rationale -.. Actor Model https://en.wikipedia.org/wiki/Actor_model -.. Actor System https://doc.akka.io/docs/akka/current/general/actor-systems.html -.. Celery Pool AsyncIO https://github.com/kai3341/celery-pool-asyncio -.. Akka https://akka.io/ -.. Pykka https://github.com/jodal/pykka -.. Mopidy https://github.com/mopidy/mopidy -.. Cell https://github.com/celery/cell -.. Thespian https://github.com/thespianpy/Thespian -.. Pulsar https://github.com/quantmind/pulsar -.. AsyncIO https://docs.python.org/3/library/asyncio.html -.. Curio https://github.com/dabeaz/curio -.. Trio https://github.com/python-trio/trio -.. Trio-Asyncio https://github.com/python-trio/trio-asyncio -.. Hierarchical State Machine https://www.eventhelix.com/design-patterns/hierarchical-state-machine/ -.. transitions https://github.com/pytransitions/transitions -.. transitions-anyio https://github.com/pytransitions/transitions-anyio -.. transitions-gui https://github.com/pytransitions/transitions-gui -.. AnyIO https://github.com/agronholm/anyio -.. cancel scope https://anyio.readthedocs.io/en/stable/api.html#anyio.CancelScope -.. Inversion of Control https://martinfowler.com/bliki/InversionOfControl.html +.. _Celery Next-Gen: https://github.com/celery/ceps/blob/master/draft/high-level-architecture.rst +.. _Jumpstarter: https://github.com/celery/jumpstarter +.. _Reference Implementation: https://github.com/celery/jumpstarter/tree/actor +.. _AP Scheduler 4.0 Release: https://github.com/agronholm/apscheduler/issues/465 +.. _Actor Model: https://en.wikipedia.org/wiki/Actor_model +.. _Actor System: https://doc.akka.io/docs/akka/current/general/actor-systems.html +.. _Celery Pool AsyncIO: https://github.com/kai3341/celery-pool-asyncio +.. _Akka: https://akka.io/ +.. _Pykka: https://github.com/jodal/pykka +.. _Mopidy: https://github.com/mopidy/mopidy +.. _Cell: https://github.com/celery/cell +.. _Thespian: https://github.com/thespianpy/Thespian +.. _Pulsar: https://github.com/quantmind/pulsar +.. _AsyncIO: https://docs.python.org/3/library/asyncio.html +.. _Curio: https://github.com/dabeaz/curio +.. _Trio: https://github.com/python-trio/trio +.. _Trio-Asyncio: https://github.com/python-trio/trio-asyncio +.. _Hierarchical State Machine: https://www.eventhelix.com/design-patterns/hierarchical-state-machine/ +.. _transitions: https://github.com/pytransitions/transitions +.. _transitions-anyio: https://github.com/pytransitions/transitions-anyio +.. _transitions-gui: https://github.com/pytransitions/transitions-gui +.. _AnyIO: https://github.com/agronholm/anyio +.. _cancel scope: https://anyio.readthedocs.io/en/stable/api.html#anyio.CancelScope +.. _Inversion of Control: https://martinfowler.com/bliki/InversionOfControl.html From 5bba3fa9f8c6f49b123901a7c5043efd0e462676 Mon Sep 17 00:00:00 2001 From: Omer Katz Date: Wed, 18 Aug 2021 21:20:41 +0300 Subject: [PATCH 14/14] Mention states DSL. --- draft/jumpstarter.rst | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/draft/jumpstarter.rst b/draft/jumpstarter.rst index e153271..53b6888 100644 --- a/draft/jumpstarter.rst +++ b/draft/jumpstarter.rst @@ -77,7 +77,32 @@ are three fundamental axioms within the actor model: It's important to remember that, although that is the technical definition of the actor, the interpretation and implementation of Actors and Actor Systems can be very flexible. Namely, what constitutes a "message" and "state" is very much up to the interpretation of the developer(s) and the system(s) they're using. -In Jumpstarter, we've chosen to take direct/literal approach to 3., modeling the state of an Actor using an actual state machine abstraction, namely a `Hierarchical State Machine`_. The difference between a standard State Machine and a Hierarchical State Machine is that a standard State Machine is consistent from states and transitions between them, but in an Hierarchical State Machine, states can also have their own sub-state machines. Hierarchical State Machines help both tame the complexity of large (non-hierarchical) state machines and more clearly model the relationships and transitions between them. To give an example with Jumpstarter, we propose only a small number of parent states: +In Jumpstarter, we've chosen to take direct/literal approach to 3., modeling the state of an Actor using an actual state machine abstraction, namely a `Hierarchical State Machine`_. The difference between a standard State Machine and a Hierarchical State Machine is that a standard State Machine is consistent from states and transitions between them, but in an Hierarchical State Machine, states can also have their own sub-state machines. Hierarchical State Machines help both tame the complexity of large (non-hierarchical) state machines and more clearly model the relationships and transitions between them. + +States +------ + +The transitions library exposes an imperative API to define state machines. This is fine for software developers who have interest in employing a state machine or a few of them in their codebase. +Since Jumpstarter's Actor implementation relies on a state machine, we expect the users of our library to have to use the transitions API for even the simplest of actor implementations. + +This presents two major design problems: +1) We will expose transitions as Jumpstarter's public API. This will create a coupling between the libraries and if transitions introduce a backwards incompatitable change, it will break all Jumpstarter codebases, including Celery. +2) Using transition's imperative API to define the Actor's state machine is not ergonomic. It requires you to fiddle with the Actor's privates or expose them as public API which is far from desired. + +To resolve these problems, we introduce an internal `Domain Specific Language`_ (abbreviated as DSL) for defining states and transitions between them decleratively. +The difference between an internal DSL and an external one is that an internal DSL uses the host language (Python) to give the host language the feel of a particular language. + +In contrast to Ruby or Lisp, Python has been traditionally considered less of a candidate for internal DSLs due to lack of metaprogramming capabilities in Python. +However, in Python 3 there are ways to create declerative APIs with ease if you get a little bit creative. + +Since Python 3.0, we can populate the class' namespace using a metaclass which has a ``__prepare__`` method present. +This allows us to define the base Actor's state machine in the following fashion: + +.. code-block:: python + + class Actor(metaclass=ActorDSLMeta): + (initializing >> initialized >> starting >> starting.dependencies_started >> starting.resources_acquired + >> starting.tasks_started >> started) * Initializing --> The initial state of the Actor when created. * Initialized --> The state of the actor when we start it for the very first time. @@ -383,3 +408,4 @@ CC0 1.0 Universal license (https://creativecommons.org/publicdomain/zero/1.0/dee .. _AnyIO: https://github.com/agronholm/anyio .. _cancel scope: https://anyio.readthedocs.io/en/stable/api.html#anyio.CancelScope .. _Inversion of Control: https://martinfowler.com/bliki/InversionOfControl.html +.. _Domain Specific Language: https://en.wikipedia.org/wiki/Domain-specific_language