Skip to content

Commit

Permalink
Simplified the "Publishing events to other Active Objects" recipe.
Browse files Browse the repository at this point in the history
  • Loading branch information
aleph2c committed Jun 18, 2019
1 parent dbabd50 commit ebd402c
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 80 deletions.
64 changes: 42 additions & 22 deletions doc/recipes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1497,37 +1497,57 @@ call as saying, "I would like to subscribe to this type of event".

Publishing events to other Active Objects
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Your active object can communicate to other active objects in the system by
publishing events. There are two different threads in the active fabric
object that manage this communication and they each have a priority queue. A
priority queue lets you post items into a queue with different priorities. If
one posted thing is higher than another, it will be pushed closer to the front of
the queue. The ``publish`` method has access to the same prioritization. If
you call it with a priority number it will pass this number in with the message
that it is transmitting out to all of its subscribers. The task will
automatically arrange this message relative to all of the other
events that are waiting in the queue.

For an active object to publish an event to another active object (which has
subscribed to the event):
Your active object can send data to other active objects in the system by
publishing events.

But your active object can only control *how it talks to others*, not *who
listens to it*; so, if another active object wants to receive a published event
it must subscribe to it first.

If you would like to publish data that will be used by another ActiveObject,
copy your data into some sort of immutable object before you publish it:
namedtuple objects are perfect for these situations:

.. code-block:: python
from collections import namedtuple
# draw these payloads on your statechart diagram
MyPayload = namedtuple('MyPayload', ['name_of_item_1', 'name_of_item2'])
publishing_ao = ActiveObect()
publishing_ao.publish(Event(signal=signals.THING_SUBSCRIBING_AO_CARES_ABOUT)
# This is how you can send an 'THING_SUBSCRIBING_AO_CARES_ABOUT' event
# to anything that has subscribed to it
publishing_ao.publish(
Event(signal=signals.THING_SUBSCRIBING_AO_CARES_ABOUT,
payload=MyPayload(
name_of_item_1='something',
name_of_item_2='something_else'
)
)
)
Here is how to publish an event with a specific priority:

.. code-block:: python
publishing_ao = ActiveObect()
publishing_ao.publish(
Event(signal=signals.THING_SUBSCRIBING_AO_CARES_ABOUT))
# or you can set the priority (1 is the highest priority see note):
publishing_ao.publish(
Event(signal=signals.THING_SUBSCRIBING_AO_CARES_ABOUT
Event(signal=signals.THING_SUBSCRIBING_AO_CARES_ABOUT),
priority=1)
:NOTE:
The highest event priority corresponds to the number 1 and all higher numbers
have lower priority. If a number is higher than another it will have lower
priority than the number it is greater than. By default all published events
are given a priority of 1000. If two events have the same priority the queue
will behave like a first in first out queue.
.. note::
The priority numbering scheme is counter-intuitive: low numbers mean high
priority while high numbers mean low priority. The highest published event
priority is 1. By default all published events are given a priority of 1000.
If two events have the same priority the queue will behave like a first in
first out queue.


.. _recipes-seeing-what-is-:
Expand Down
64 changes: 42 additions & 22 deletions docs/_sources/recipes.rst.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1497,37 +1497,57 @@ call as saying, "I would like to subscribe to this type of event".

Publishing events to other Active Objects
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Your active object can communicate to other active objects in the system by
publishing events. There are two different threads in the active fabric
object that manage this communication and they each have a priority queue. A
priority queue lets you post items into a queue with different priorities. If
one posted thing is higher than another, it will be pushed closer to the front of
the queue. The ``publish`` method has access to the same prioritization. If
you call it with a priority number it will pass this number in with the message
that it is transmitting out to all of its subscribers. The task will
automatically arrange this message relative to all of the other
events that are waiting in the queue.

For an active object to publish an event to another active object (which has
subscribed to the event):
Your active object can send data to other active objects in the system by
publishing events.

But your active object can only control *how it talks to others*, not *who
listens to it*; so, if another active object wants to receive a published event
it must subscribe to it first.

If you would like to publish data that will be used by another ActiveObject,
copy your data into some sort of immutable object before you publish it:
namedtuple objects are perfect for these situations:

.. code-block:: python
from collections import namedtuple
# draw these payloads on your statechart diagram
MyPayload = namedtuple('MyPayload', ['name_of_item_1', 'name_of_item2'])
publishing_ao = ActiveObect()
publishing_ao.publish(Event(signal=signals.THING_SUBSCRIBING_AO_CARES_ABOUT)
# This is how you can send an 'THING_SUBSCRIBING_AO_CARES_ABOUT' event
# to anything that has subscribed to it
publishing_ao.publish(
Event(signal=signals.THING_SUBSCRIBING_AO_CARES_ABOUT,
payload=MyPayload(
name_of_item_1='something',
name_of_item_2='something_else'
)
)
)
Here is how to publish an event with a specific priority:

.. code-block:: python
publishing_ao = ActiveObect()
publishing_ao.publish(
Event(signal=signals.THING_SUBSCRIBING_AO_CARES_ABOUT))
# or you can set the priority (1 is the highest priority see note):
publishing_ao.publish(
Event(signal=signals.THING_SUBSCRIBING_AO_CARES_ABOUT
Event(signal=signals.THING_SUBSCRIBING_AO_CARES_ABOUT),
priority=1)
:NOTE:
The highest event priority corresponds to the number 1 and all higher numbers
have lower priority. If a number is higher than another it will have lower
priority than the number it is greater than. By default all published events
are given a priority of 1000. If two events have the same priority the queue
will behave like a first in first out queue.
.. note::
The priority numbering scheme is counter-intuitive: low numbers mean high
priority while high numbers mean low priority. The highest published event
priority is 1. By default all published events are given a priority of 1000.
If two events have the same priority the queue will behave like a first in
first out queue.


.. _recipes-seeing-what-is-:
Expand Down
19 changes: 11 additions & 8 deletions docs/activeobject.html
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,15 @@ <h2>Active Fabric<a class="headerlink" href="#active-fabric" title="Permalink to

<dl class="method">
<dt id="activeobject.ActiveFabricSource.thread_runner_fifo">
<code class="descname">thread_runner_fifo</code><span class="sig-paren">(</span><em>task_event</em>, <em>fifo_queue</em>, <em>fifo_subscriptions</em><span class="sig-paren">)</span><a class="headerlink" href="#activeobject.ActiveFabricSource.thread_runner_fifo" title="Permalink to this definition"></a></dt>
<code class="descname">thread_runner_fifo</code><span class="sig-paren">(</span><em>fabric_task_event</em>, <em>fifo_queue</em>, <em>fifo_subscriptions</em><span class="sig-paren">)</span><a class="headerlink" href="#activeobject.ActiveFabricSource.thread_runner_fifo" title="Permalink to this definition"></a></dt>
<dd><p>If this was a Thread class this function would be called “run”</p>
<p>This is the main execution code of the thread. It watches to see if the
HsmEvent() singleton has been cleared, if it has it exits its forever loop.</p>
</dd></dl>

<dl class="method">
<dt id="activeobject.ActiveFabricSource.thread_runner_lifo">
<code class="descname">thread_runner_lifo</code><span class="sig-paren">(</span><em>task_event</em>, <em>lifo_queue</em>, <em>lifo_subscriptions</em><span class="sig-paren">)</span><a class="headerlink" href="#activeobject.ActiveFabricSource.thread_runner_lifo" title="Permalink to this definition"></a></dt>
<code class="descname">thread_runner_lifo</code><span class="sig-paren">(</span><em>fabric_task_event</em>, <em>lifo_queue</em>, <em>lifo_subscriptions</em><span class="sig-paren">)</span><a class="headerlink" href="#activeobject.ActiveFabricSource.thread_runner_lifo" title="Permalink to this definition"></a></dt>
<dd><p>If this was a Thread class this function would be called “run”</p>
<p>This is the main execution code of the thread. It watches to see if the
HsmEvent() singleton has been cleared, if it has it exits its forever loop.</p>
Expand Down Expand Up @@ -258,9 +258,13 @@ <h2>Active Object<a class="headerlink" href="#id1" title="Permalink to this head

<dl class="method">
<dt id="activeobject.ActiveObject.run_event">
<code class="descname">run_event</code><span class="sig-paren">(</span><em>task_event</em>, <em>queue</em><span class="sig-paren">)</span><a class="headerlink" href="#activeobject.ActiveObject.run_event" title="Permalink to this definition"></a></dt>
<dd><p>The active object task function</p>
<p>This task method waits on the locking-deque. If the signal is not a
<code class="descname">run_event</code><span class="sig-paren">(</span><em>task_event</em>, <em>fabric_task_event</em>, <em>queue</em><span class="sig-paren">)</span><a class="headerlink" href="#activeobject.ActiveObject.run_event" title="Permalink to this definition"></a></dt>
<dd><p>The active object threading function.</p>
<p>If this statechart has not been stopped and the active fabric hasn’t been
stopped the threading function will run. If the active fabric has been
stopped, it will stop this thread as well by clearing the task_event
HsmEvent (threading.Event) object.</p>
<p>This threading method waits on the locking-deque. If the signal is not a
stop_active_object signal it calls the hsm next_rtc method, which will pop
the leftmost item out of the deque part of the locking-deque and dispatch it
into the hsm.</p>
Expand All @@ -274,9 +278,8 @@ <h2>Active Object<a class="headerlink" href="#id1" title="Permalink to this head

<dl class="method">
<dt id="activeobject.ActiveObject.stop">
<code class="descname">stop</code><span class="sig-paren">(</span><em>stop_fabric=None</em><span class="sig-paren">)</span><a class="headerlink" href="#activeobject.ActiveObject.stop" title="Permalink to this definition"></a></dt>
<dd><p>Stops the active object</p>
<p>Calling this method will stop all active objects.</p>
<code class="descname">stop</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#activeobject.ActiveObject.stop" title="Permalink to this definition"></a></dt>
<dd><p>Stops the active object, can cancels all of its pending events</p>
</dd></dl>

<dl class="method">
Expand Down
66 changes: 39 additions & 27 deletions docs/recipes.html
Original file line number Diff line number Diff line change
Expand Up @@ -1473,40 +1473,52 @@ <h2>Getting Information from your Statechart<a class="headerlink" href="#getting
</div>
<div class="section" id="publishing-events-to-other-active-objects">
<span id="recipes-publishing-event-to-other-active-objects"></span><h3>Publishing events to other Active Objects<a class="headerlink" href="#publishing-events-to-other-active-objects" title="Permalink to this headline"></a></h3>
<p>Your active object can communicate to other active objects in the system by
publishing events. There are two different threads in the active fabric
object that manage this communication and they each have a priority queue. A
priority queue lets you post items into a queue with different priorities. If
one posted thing is higher than another, it will be pushed closer to the front of
the queue. The <code class="docutils literal notranslate"><span class="pre">publish</span></code> method has access to the same prioritization. If
you call it with a priority number it will pass this number in with the message
that it is transmitting out to all of its subscribers. The task will
automatically arrange this message relative to all of the other
events that are waiting in the queue.</p>
<p>For an active object to publish an event to another active object (which has
subscribed to the event):</p>
<p>Your active object can send data to other active objects in the system by
publishing events.</p>
<p>But your active object can only control <em>how it talks to others</em>, not <em>who
listens to it</em>; so, if another active object wants to receive a published event
it must subscribe to it first.</p>
<p>If you would like to publish data that will be used by another ActiveObject,
copy your data into some sort of immutable object before you publish it:
namedtuple objects are perfect for these situations:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>

<span class="c1"># draw these payloads on your statechart diagram</span>
<span class="n">MyPayload</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s1">&#39;MyPayload&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;name_of_item_1&#39;</span><span class="p">,</span> <span class="s1">&#39;name_of_item2&#39;</span><span class="p">])</span>

<span class="n">publishing_ao</span> <span class="o">=</span> <span class="n">ActiveObect</span><span class="p">()</span>

<span class="c1"># This is how you can send an &#39;THING_SUBSCRIBING_AO_CARES_ABOUT&#39; event</span>
<span class="c1"># to anything that has subscribed to it</span>
<span class="n">publishing_ao</span><span class="o">.</span><span class="n">publish</span><span class="p">(</span>
<span class="n">Event</span><span class="p">(</span><span class="n">signal</span><span class="o">=</span><span class="n">signals</span><span class="o">.</span><span class="n">THING_SUBSCRIBING_AO_CARES_ABOUT</span><span class="p">,</span>
<span class="n">payload</span><span class="o">=</span><span class="n">MyPayload</span><span class="p">(</span>
<span class="n">name_of_item_1</span><span class="o">=</span><span class="s1">&#39;something&#39;</span><span class="p">,</span>
<span class="n">name_of_item_2</span><span class="o">=</span><span class="s1">&#39;something_else&#39;</span>
<span class="p">)</span>
<span class="p">)</span>
<span class="p">)</span>
</pre></div>
</div>
<p>Here is how to publish an event with a specific priority:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">publishing_ao</span> <span class="o">=</span> <span class="n">ActiveObect</span><span class="p">()</span>
<span class="n">publishing_ao</span><span class="o">.</span><span class="n">publish</span><span class="p">(</span><span class="n">Event</span><span class="p">(</span><span class="n">signal</span><span class="o">=</span><span class="n">signals</span><span class="o">.</span><span class="n">THING_SUBSCRIBING_AO_CARES_ABOUT</span><span class="p">)</span>
<span class="n">publishing_ao</span><span class="o">.</span><span class="n">publish</span><span class="p">(</span>
<span class="n">Event</span><span class="p">(</span><span class="n">signal</span><span class="o">=</span><span class="n">signals</span><span class="o">.</span><span class="n">THING_SUBSCRIBING_AO_CARES_ABOUT</span><span class="p">))</span>

<span class="c1"># or you can set the priority (1 is the highest priority see note):</span>
<span class="n">publishing_ao</span><span class="o">.</span><span class="n">publish</span><span class="p">(</span>
<span class="n">Event</span><span class="p">(</span><span class="n">signal</span><span class="o">=</span><span class="n">signals</span><span class="o">.</span><span class="n">THING_SUBSCRIBING_AO_CARES_ABOUT</span>
<span class="n">Event</span><span class="p">(</span><span class="n">signal</span><span class="o">=</span><span class="n">signals</span><span class="o">.</span><span class="n">THING_SUBSCRIBING_AO_CARES_ABOUT</span><span class="p">),</span>
<span class="n">priority</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</pre></div>
</div>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field-odd field"><th class="field-name">NOTE:</th><td class="field-body"></td>
</tr>
</tbody>
</table>
<p>The highest event priority corresponds to the number 1 and all higher numbers
have lower priority. If a number is higher than another it will have lower
priority than the number it is greater than. By default all published events
are given a priority of 1000. If two events have the same priority the queue
will behave like a first in first out queue.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">The priority numbering scheme is counter-intuitive: low numbers mean high
priority while high numbers mean low priority. The highest published event
priority is 1. By default all published events are given a priority of 1000.
If two events have the same priority the queue will behave like a first in
first out queue.</p>
</div>
</div>
</div>
<div class="section" id="seeing-what-is-going-on">
Expand Down
2 changes: 1 addition & 1 deletion docs/searchindex.js

Large diffs are not rendered by default.

0 comments on commit ebd402c

Please sign in to comment.