Update docs for ACM-r message handling architecture 97/140297/1
authorFrancescoFioraEst <francesco.fiora@est.tech>
Mon, 24 Feb 2025 17:27:05 +0000 (17:27 +0000)
committerFrancesco Fiora <francesco.fiora@est.tech>
Tue, 25 Feb 2025 11:19:30 +0000 (11:19 +0000)
Issue-ID: POLICY-5292
Change-Id: I27fb3966f19a762b4e3bc7415812f099e4b1d63a
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
docs/clamp/acm/design-impl/clamp-runtime-acm.rst
docs/clamp/acm/draw.io/acm-consumer-producer.drawio [new file with mode: 0644]
docs/clamp/acm/draw.io/acm-scheduling-job.drawio [new file with mode: 0644]
docs/clamp/acm/images/acm-consumer-producer-messages.png [new file with mode: 0644]
docs/clamp/acm/images/acm-scheduling-job.png [new file with mode: 0644]

index a3c22e6..802e9a0 100644 (file)
@@ -349,46 +349,61 @@ PARTICIPANT_REGISTER
 - A participant replica starts and send a PARTICIPANT_REGISTER message with participantId, replicaId and supported Element Types
 - ACM-runtime collects the message from Message Broker by ParticipantRegisterListener
 - if not present, it saves participant replica reference with status ON_LINE to DB
+- it sends PARTICIPANT_REGISTER_ACK to participant replica
 
 PARTICIPANT_PRIME_ACK
 ++++++++++++++++++++++
 - A participant sends PARTICIPANT_PRIME_ACK message in response to a PARTICIPANT_PRIME message
 - ParticipantPrimeAckListener collects the message from Message Broker
-- It updates AC Definition to DB with PRIMED/DEPRIMED as status
-- If AC Definition is fully PRIMED, ACM-runtime sends sync message to all participants replica
+- It stores the message into the DB
+- MessageIntercept intercepts that event and adds a task to handle a monitoring execution in SupervisionScanner
+- Monitoring updates AC Definition to DB with PRIMED/DEPRIMED as status
+- If AC Definition is fully PRIMED, Monitoring sends sync message to all participants replica
 
 PARTICIPANT_STATUS
 ++++++++++++++++++
-- A participant sends a scheduled PARTICIPANT_STATUS message with participantId, replicaId and supported Element Types
+- A participant sends a scheduled PARTICIPANT_STATUS message with participantId, replicaId and supported Element Types. Same message could be used by participant to update OutProperties of an AC instance/AC definition.
 - ACM-runtime collects the message from Message Broker by ParticipantStatusListener
-- if not present, it saves participant replica reference with status ON_LINE to DB
+- If not present, it saves participant replica reference with status ON_LINE to DB
+- If the message contains OutProperties of an AC instance/AC definition it stores the message into the DB
+- MessageIntercept intercepts that event and adds a task to handle a monitoring execution in SupervisionScanner
+- Monitoring updates the AC instance/AC definition
+- Monitoring sends a sync message to all participants replica
 
 AUTOMATION_COMPOSITION_DEPLOY_ACK
 +++++++++++++++++++++++++++++++++
 - A participant sends AUTOMATION_COMPOSITION_DEPLOY_ACK message in response to a AUTOMATION_COMPOSITION_DEPLOY message. It will send a AUTOMATION_COMPOSITION_DEPLOY_ACK - for each AC elements moved to the DEPLOYED state
 - AutomationCompositionUpdateAckListener collects the message from Message Broker
-- It checks the status of all Automation Composition elements and checks if the Automation Composition is fully DEPLOYED
-- It updates the AC to DB
+- It store the message into the DB
 - MessageIntercept intercepts that event and adds a task to handle a monitoring execution in SupervisionScanner
+- Monitoring checks the status of all Automation Composition elements and checks if the Automation Composition is fully DEPLOYED
+- Monitoring updates the AC instance to DB
+- If the Automation Composition is fully DEPLOYED Monitoring sends a sync message to all participants replica
 
 AUTOMATION_COMPOSITION_STATECHANGE_ACK
 ++++++++++++++++++++++++++++++++++++++
 - A participant sends AUTOMATION_COMPOSITION_STATECHANGE_ACK message in response to a AUTOMATION_COMPOSITION_STATECHANGE message. It will send a AUTOMATION_COMPOSITION_DEPLOY_ACK - for each AC elements moved to the ordered state
 - AutomationCompositionStateChangeAckListener collects the message from Message Broker
-- It checks the status of all Automation Composition elements and checks if the transition process of the Automation Composition is terminated
-- It updates the AC to DB
+- It store the message into the DB
 - MessageIntercept intercepts that event and adds a task to handle a monitoring execution in SupervisionScanner
+- Monitoring checks the status of all Automation Composition elements and checks if the transition process of the Automation Composition is terminated
+- Monitoring updates the AC instance to DB
+- If the transition process is terminated, Monitoring sends a sync message to all participants replica
 
 Design of monitoring execution in SupervisionScanner
 ****************************************************
 Monitoring is designed to process the follow operations:
 
+- to elaborate the messages from participants
 - to determine the next startPhase in a AUTOMATION_COMPOSITION_DEPLOY message
+- to determine the next stage in a AUTOMATION_COMPOSITION_MIGRATION message
 - to update AC deployState: in a scenario that "AutomationComposition.deployState" is in a kind of transitional state (example DEPLOYING), if all  - AC elements are moved properly to the specific state, the "AutomationComposition.deployState" will be updated to that and saved to DB
 - to update AC lockState: in a scenario that "AutomationComposition.lockState" is in a kind of transitional state (example LOCKING), if all  - AC elements are moved properly to the specific state, the "AutomationComposition.lockState" will be updated to that and saved to DB
+- to update AC subState: in a scenario that "AutomationComposition.subState" is in a kind of transitional state (example PREPARING), if all  - AC elements are moved properly to NONE state, the "AutomationComposition.subState" will be updated to NONE and saved to DB
 - to delete AC Instance: in a scenario that "AutomationComposition.deployState" is in DELETING, if all  - AC elements are moved properly to DELETED, the AC Instance will be deleted from DB
 - to retry AUTOMATION_COMPOSITION_DEPLOY/AUTOMATION_COMPOSITION_STATE_CHANGE messages. if there is an AC instance with startPhase completed, it will be moved to the next startPhase and retry a broadcast message with the new startPhase
-- to send sync message to all participants replica: in scenario where AC instance transition is fully completed
+- to retry AUTOMATION_COMPOSITION_MIGRATION messages. if there is an AC instance with stage completed, it will be moved to the next stage and retry a broadcast message with the new stage
+- to send sync message to all participants replica: in scenario where AC instance transition is fully completed or OutProperties has been changed
 
 The solution Design timeout and reporting for all Participant message dialogues are implemented into the monitoring execution.
 
@@ -396,6 +411,27 @@ The solution Design timeout and reporting for all Participant message dialogues
 - ThreadPoolExecutor executes the task
 - set AC instance stateChangeResult in timeout, if ACM-runtime do no receive Act message before MaxWaitMs milliseconds
 
+Producer and Consumer and Scheduling job mechanisms
++++++++++++++++++++++++++++++++++++++++++++++++++++
+To avoid conflicts, for example when an ACM-r pod is receiving a messages to change outProperties of an AC instance and other ACM-r pod is receiving a messages to change the status of an element of the same instance,
+Producer and Consumer and Scheduling job mechanisms has been implemented.
+With the Producer and Consumer mechanism, any ACM-r replica monitoring could elaborate a message independently from what ACM-r replica has fetched the message.
+Listeners of ACM-r will fetch messages from kafka and store to a message FIFO queue stored in DB.
+
+.. image:: ../images/acm-consumer-producer-messages.png
+
+Monitoring of a ACM-r replica will fetch messages from that queue.
+All Monitoring from different ACM-r pods are synchronized with Scheduling job to avoid to fetch messages related to same AC instance or AC definition at same time.
+InstanceIds and a compositionIds are generated with UUID as unique key and could be used as identificationId for messages.
+
+.. image:: ../images/acm-scheduling-job.png
+
+Edge case scenario: ACM-r pod has been terminated from Kubernetes
+-----------------------------------------------------------------
+Full elaboration of a monitoring for an AC instance or for a AC definition is protected by a transaction.
+If an ACM-r pod has been terminated from Kubernetes, the monitoring not full completed will be rollback from database.
+The monitoring job not completed wil be deleted after 200 seconds. All message of that AC definition or AC instance will processed by other monitoring.
+
 Design of Exception handling
 ****************************
 GlobalControllerExceptionHandler
diff --git a/docs/clamp/acm/draw.io/acm-consumer-producer.drawio b/docs/clamp/acm/draw.io/acm-consumer-producer.drawio
new file mode 100644 (file)
index 0000000..5002255
--- /dev/null
@@ -0,0 +1,76 @@
+<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0" modified="2025-02-24T15:17:34.768Z" version="24.3.0" etag="oOdE97yUTVgThpAVyM50" type="device">
+  <diagram name="Page-1" id="13e1069c-82ec-6db2-03f1-153e76fe0fe0">
+    <mxGraphModel dx="1666" dy="781" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="850" background="none" math="0" shadow="0">
+      <root>
+        <mxCell id="0" />
+        <mxCell id="1" parent="0" />
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-2" value="DB" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" parent="1" vertex="1">
+          <mxGeometry x="410" y="390" width="100" height="120" as="geometry" />
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-7" value="Producers" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
+          <mxGeometry x="280" y="150" width="118" height="30" as="geometry" />
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-8" value="Consumers" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
+          <mxGeometry x="510" y="150" width="120" height="30" as="geometry" />
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-13" value="Kafka" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
+          <mxGeometry x="150" y="160" width="60" height="200" as="geometry" />
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-20" value="ACM-r pod1" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;" parent="1" vertex="1">
+          <mxGeometry x="257" y="180" width="390" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-17" value="ACM-r pod 1&lt;div&gt;Monitoring&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
+          <mxGeometry x="525" y="193" width="90" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-9" value="ACM-r pod 1&lt;div&gt;Listener&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
+          <mxGeometry x="294" y="193" width="90" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-21" value="ACM-r pod2" style="rounded=1;whiteSpace=wrap;html=1;dashed=1;" parent="1" vertex="1">
+          <mxGeometry x="257" y="277" width="390" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-18" value="ACM-r pod 2&lt;div&gt;Monitoring&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
+          <mxGeometry x="525" y="287" width="90" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-10" value="ACM-r pod 2&lt;div&gt;Listener&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
+          <mxGeometry x="294" y="287" width="90" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-11" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.145;entryY=0;entryDx=0;entryDy=4.35;entryPerimeter=0;" parent="1" source="kN3JDQdCuxnZuiGcsfEb-9" target="kN3JDQdCuxnZuiGcsfEb-2" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="520" y="420" as="sourcePoint" />
+            <mxPoint x="570" y="370" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-12" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.06;entryY=0.042;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="kN3JDQdCuxnZuiGcsfEb-10" target="kN3JDQdCuxnZuiGcsfEb-2" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="394" y="261" as="sourcePoint" />
+            <mxPoint x="420" y="390" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-14" value="" style="endArrow=classic;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.35;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="kN3JDQdCuxnZuiGcsfEb-13" target="kN3JDQdCuxnZuiGcsfEb-9" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="110" y="475" as="sourcePoint" />
+            <mxPoint x="160" y="425" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-15" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.022;entryY=0.383;entryDx=0;entryDy=0;entryPerimeter=0;exitX=0.967;exitY=0.705;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="kN3JDQdCuxnZuiGcsfEb-13" target="kN3JDQdCuxnZuiGcsfEb-10" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="120" y="485" as="sourcePoint" />
+            <mxPoint x="170" y="435" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-22" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.7;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitPerimeter=0;" parent="1" source="kN3JDQdCuxnZuiGcsfEb-2" target="kN3JDQdCuxnZuiGcsfEb-17" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="680" y="420" as="sourcePoint" />
+            <mxPoint x="760" y="250" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="kN3JDQdCuxnZuiGcsfEb-23" value="" style="endArrow=classic;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" target="kN3JDQdCuxnZuiGcsfEb-18" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="480" y="390" as="sourcePoint" />
+            <mxPoint x="647" y="366.5" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+      </root>
+    </mxGraphModel>
+  </diagram>
+</mxfile>
diff --git a/docs/clamp/acm/draw.io/acm-scheduling-job.drawio b/docs/clamp/acm/draw.io/acm-scheduling-job.drawio
new file mode 100644 (file)
index 0000000..9591ada
--- /dev/null
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mxfile host="ac.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36" version="26.0.16">
+  <diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
+    <mxGraphModel dx="1434" dy="772" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
+      <root>
+        <mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
+        <mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
+        <mxCell id="WIyWlLk6GJQsqaUBKTNV-2" value="" style="rounded=0;html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=block;endFill=0;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="WIyWlLk6GJQsqaUBKTNV-3" target="8UuhrBDbArfPKTQupupm-0" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="220" y="170" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="WIyWlLk6GJQsqaUBKTNV-3" value="Fetch the list of composition ids&lt;div&gt;and instance ids that have&lt;/div&gt;&lt;div&gt;to be monitored&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
+          <mxGeometry x="115" y="10" width="210" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="WIyWlLk6GJQsqaUBKTNV-8" value="No" style="rounded=0;html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=block;endFill=0;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="WIyWlLk6GJQsqaUBKTNV-10" edge="1">
+          <mxGeometry x="0.3333" y="20" relative="1" as="geometry">
+            <mxPoint as="offset" />
+            <mxPoint x="850" y="200" as="sourcePoint" />
+            <mxPoint x="220" y="400" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="WIyWlLk6GJQsqaUBKTNV-9" value="Yes" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=block;endFill=0;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="WIyWlLk6GJQsqaUBKTNV-10" target="8UuhrBDbArfPKTQupupm-0" edge="1">
+          <mxGeometry y="10" relative="1" as="geometry">
+            <mxPoint as="offset" />
+            <mxPoint x="410" y="325" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="400" y="295" />
+              <mxPoint x="400" y="160" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="8UuhrBDbArfPKTQupupm-0" value="Fetch next indentification id&lt;div&gt;from the list&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
+          <mxGeometry x="115" y="120" width="210" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="8UuhrBDbArfPKTQupupm-2" value="" style="rounded=0;html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=block;endFill=0;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8UuhrBDbArfPKTQupupm-0" target="WIyWlLk6GJQsqaUBKTNV-10" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="220" y="220" as="sourcePoint" />
+            <mxPoint x="370" y="250" as="targetPoint" />
+            <Array as="points" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="WIyWlLk6GJQsqaUBKTNV-10" value="is this&lt;div&gt;indentification&amp;nbsp;&lt;span style=&quot;background-color: transparent; color: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&gt;id&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;background-color: transparent; color: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&gt;present into&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;background-color: transparent; color: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&gt;the messagejob?&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;" style="rhombus;whiteSpace=wrap;html=1;shadow=0;fontFamily=Helvetica;fontSize=12;align=center;strokeWidth=1;spacing=6;spacingTop=-4;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
+          <mxGeometry x="140" y="230" width="160" height="130" as="geometry" />
+        </mxCell>
+        <mxCell id="8UuhrBDbArfPKTQupupm-3" value="Save the identification id&lt;div&gt;into the messagejob&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
+          <mxGeometry x="115" y="400" width="210" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="8UuhrBDbArfPKTQupupm-5" value="Handle all messages by the identification id and remove&lt;div&gt;those messages when completed&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
+          <mxGeometry x="115" y="520" width="210" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="8UuhrBDbArfPKTQupupm-7" value="" style="rounded=0;html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=block;endFill=0;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8UuhrBDbArfPKTQupupm-3" target="8UuhrBDbArfPKTQupupm-5" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="400" y="420" as="sourcePoint" />
+            <mxPoint x="266" y="240" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="220" y="500" />
+              <mxPoint x="220" y="500" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="8UuhrBDbArfPKTQupupm-8" value="When all messages are completed remove the identification id&lt;div&gt;from the messagejob&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
+          <mxGeometry x="115" y="640" width="210" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="8UuhrBDbArfPKTQupupm-9" value="" style="rounded=0;html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=block;endFill=0;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" target="8UuhrBDbArfPKTQupupm-8" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="220" y="600" as="sourcePoint" />
+            <mxPoint x="266" y="360" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="220" y="620" />
+              <mxPoint x="220" y="620" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="8UuhrBDbArfPKTQupupm-10" value="No" style="rounded=0;html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=block;endFill=0;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8UuhrBDbArfPKTQupupm-12" target="8UuhrBDbArfPKTQupupm-0" edge="1">
+          <mxGeometry x="0.3333" y="20" relative="1" as="geometry">
+            <mxPoint as="offset" />
+            <mxPoint x="170" y="820" as="sourcePoint" />
+            <mxPoint x="60" y="150" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="60" y="815" />
+              <mxPoint x="60" y="160" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="8UuhrBDbArfPKTQupupm-11" value="Yes" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=block;endFill=0;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8UuhrBDbArfPKTQupupm-12" edge="1">
+          <mxGeometry y="10" relative="1" as="geometry">
+            <mxPoint as="offset" />
+            <mxPoint x="220" y="930" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="220" y="880" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="8UuhrBDbArfPKTQupupm-12" value="Is the indentification id&lt;div&gt;list empty?&lt;/div&gt;" style="rhombus;whiteSpace=wrap;html=1;shadow=0;fontFamily=Helvetica;fontSize=12;align=center;strokeWidth=1;spacing=6;spacingTop=-4;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
+          <mxGeometry x="140" y="750" width="160" height="130" as="geometry" />
+        </mxCell>
+        <mxCell id="8UuhrBDbArfPKTQupupm-13" value="" style="rounded=0;html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=block;endFill=0;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8UuhrBDbArfPKTQupupm-8" target="8UuhrBDbArfPKTQupupm-12" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="230" y="717" as="sourcePoint" />
+            <mxPoint x="230" y="747" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="220" y="730" />
+              <mxPoint x="220" y="730" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="8UuhrBDbArfPKTQupupm-14" value="Monitoring completed" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
+          <mxGeometry x="115" y="930" width="210" height="80" as="geometry" />
+        </mxCell>
+      </root>
+    </mxGraphModel>
+  </diagram>
+</mxfile>
diff --git a/docs/clamp/acm/images/acm-consumer-producer-messages.png b/docs/clamp/acm/images/acm-consumer-producer-messages.png
new file mode 100644 (file)
index 0000000..0076b16
Binary files /dev/null and b/docs/clamp/acm/images/acm-consumer-producer-messages.png differ
diff --git a/docs/clamp/acm/images/acm-scheduling-job.png b/docs/clamp/acm/images/acm-scheduling-job.png
new file mode 100644 (file)
index 0000000..3ded9e9
Binary files /dev/null and b/docs/clamp/acm/images/acm-scheduling-job.png differ