Search code examples
activiticamundabusiness-process

Camunda / Activit (Boundary) Timer Event value < 10 seconds


I have a process as shown below. I want to execute some task every X seconds. When I put either CRON (0/5 * * * * ? should be every 5 seconds) time or ISO time (R3/PT5S - 3 executions every 5 seconds) < 10 seconds in the cycle time of the boundary timer event, it is executed every second or so (not the value specified). If I use 0/10 * * * * ? everything works fine and the event is executed every 10 seconds.

My final aim is to have a constant execution of a calculation every X seconds while the "rest" of the process, meaning the original business process, is executed as discribed by the BPMN model.

Process Example

XML File of process:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:camunda="http://activiti.org/bpmn" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:fox="http://www.camunda.com/fox" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" id="_cus4wJ7cEeWDYppcvQHBrQ" exporter="camunda modeler" exporterVersion="2.7.0" targetNamespace="http://activiti.org/bpmn">
  <bpmn2:process id="timerTest" name="Timer Test" isExecutable="true">
    <bpmn2:receiveTask id="waitingForMessage" camunda:async="true" camunda:exclusive="false" name="Waiting For Message" messageRef="Message_2">
      <bpmn2:incoming>SequenceFlow_22</bpmn2:incoming>
      <bpmn2:outgoing>SequenceFlow_17</bpmn2:outgoing>
    </bpmn2:receiveTask>
    <bpmn2:sequenceFlow id="SequenceFlow_17" name="" sourceRef="waitingForMessage" targetRef="end"/>
    <bpmn2:endEvent id="endCheckingTime" name="End Checking Time">
      <bpmn2:incoming>SequenceFlow_26</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:task id="checkRemainingTime" name="Check Remaining Time">
      <bpmn2:extensionElements>
        <camunda:executionListener class="timerTest.ExecutionListenerCheckRemainingTime" event="start"/>
      </bpmn2:extensionElements>
      <bpmn2:incoming>SequenceFlow_4</bpmn2:incoming>
      <bpmn2:outgoing>SequenceFlow_26</bpmn2:outgoing>
    </bpmn2:task>
    <bpmn2:sequenceFlow id="SequenceFlow_26" name="" sourceRef="checkRemainingTime" targetRef="endCheckingTime"/>
    <bpmn2:boundaryEvent id="BoundaryEvent_3" name="" attachedToRef="waitingForMessage" cancelActivity="false">
      <bpmn2:outgoing>SequenceFlow_18</bpmn2:outgoing>
      <bpmn2:timerEventDefinition id="_TimerEventDefinition_12">
        <bpmn2:timeCycle xsi:type="bpmn2:tFormalExpression">0/5 * * * * ?</bpmn2:timeCycle>
      </bpmn2:timerEventDefinition>
    </bpmn2:boundaryEvent>
    <bpmn2:sequenceFlow id="SequenceFlow_18" name="" sourceRef="BoundaryEvent_3" targetRef="ExclusiveGateway_1"/>
    <bpmn2:endEvent id="end" name="End Waiting">
      <bpmn2:incoming>SequenceFlow_17</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:exclusiveGateway id="ExclusiveGateway_1" default="SequenceFlow_5">
      <bpmn2:incoming>SequenceFlow_18</bpmn2:incoming>
      <bpmn2:outgoing>SequenceFlow_4</bpmn2:outgoing>
      <bpmn2:outgoing>SequenceFlow_5</bpmn2:outgoing>
    </bpmn2:exclusiveGateway>
    <bpmn2:sequenceFlow id="SequenceFlow_4" name="" sourceRef="ExclusiveGateway_1" targetRef="checkRemainingTime">
      <bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression"><![CDATA[${counter<5}]]></bpmn2:conditionExpression>
    </bpmn2:sequenceFlow>
    <bpmn2:endEvent id="EndEvent_1">
      <bpmn2:incoming>SequenceFlow_5</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:sequenceFlow id="SequenceFlow_5" name="" sourceRef="ExclusiveGateway_1" targetRef="EndEvent_1">
      <bpmn2:extensionElements>
        <camunda:executionListener class="timerTest.ExecutionListenerSendEndMessage" event="take"/>
      </bpmn2:extensionElements>
    </bpmn2:sequenceFlow>
    <bpmn2:startEvent id="StartEvent_2">
      <bpmn2:outgoing>SequenceFlow_22</bpmn2:outgoing>
    </bpmn2:startEvent>
    <bpmn2:sequenceFlow id="SequenceFlow_22" name="" sourceRef="StartEvent_2" targetRef="waitingForMessage"/>
    <bpmn2:textAnnotation id="TextAnnotation_1">
      <bpmn2:text><![CDATA[Problems with times < 10 Sec - No clue why]]></bpmn2:text>
    </bpmn2:textAnnotation>
    <bpmn2:association id="Association_2" sourceRef="TextAnnotation_1" targetRef="BoundaryEvent_3"/>
  </bpmn2:process>
  <bpmn2:message id="Message_2" name="testMessage"/>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="timerTest">
      <bpmndi:BPMNShape id="_BPMNShape_EndEvent_7" bpmnElement="endCheckingTime">
        <dc:Bounds height="36.0" width="36.0" x="561.0" y="299.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="22.0" width="119.0" x="520.0" y="340.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="_BPMNShape_Task_12" bpmnElement="checkRemainingTime">
        <dc:Bounds height="80.0" width="100.0" x="381.0" y="277.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_26" bpmnElement="SequenceFlow_26" sourceElement="_BPMNShape_Task_12" targetElement="_BPMNShape_EndEvent_7">
        <di:waypoint xsi:type="dc:Point" x="481.0" y="317.0"/>
        <di:waypoint xsi:type="dc:Point" x="561.0" y="317.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="6.0" width="6.0" x="743.0" y="329.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_3" bpmnElement="StartEvent_2">
        <dc:Bounds height="36.0" width="36.0" x="12.0" y="187.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="30.0" y="228.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="_BPMNShape_EndEvent_9" bpmnElement="end">
        <dc:Bounds height="36.0" width="36.0" x="561.0" y="187.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="22.0" width="77.0" x="541.0" y="228.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="_BPMNShape_TextAnnotation_2" bpmnElement="TextAnnotation_1">
        <dc:Bounds height="61.0" width="229.0" x="708.0" y="231.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="_BPMNShape_ReceiveTask_3" bpmnElement="waitingForMessage">
        <dc:Bounds height="80.0" width="100.0" x="168.0" y="165.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_17" bpmnElement="SequenceFlow_17" sourceElement="_BPMNShape_ReceiveTask_3" targetElement="_BPMNShape_EndEvent_9">
        <di:waypoint xsi:type="dc:Point" x="268.0" y="205.0"/>
        <di:waypoint xsi:type="dc:Point" x="561.0" y="205.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="6.0" width="6.0" x="163.0" y="212.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="_BPMNShape_BoundaryEvent_8" bpmnElement="BoundaryEvent_3">
        <dc:Bounds height="36.0" width="36.0" x="227.0" y="227.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="6.0" width="6.0" x="242.0" y="268.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_18" bpmnElement="SequenceFlow_18" sourceElement="_BPMNShape_BoundaryEvent_8" targetElement="_BPMNShape_ExclusiveGateway_2">
        <di:waypoint xsi:type="dc:Point" x="245.0" y="263.0"/>
        <di:waypoint xsi:type="dc:Point" x="245.0" y="284.0"/>
        <di:waypoint xsi:type="dc:Point" x="271.0" y="284.0"/>
        <di:waypoint xsi:type="dc:Point" x="271.0" y="306.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="6.0" width="6.0" x="150.0" y="298.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="_BPMNShape_ExclusiveGateway_2" bpmnElement="ExclusiveGateway_1" isMarkerVisible="true">
        <dc:Bounds height="50.0" width="50.0" x="246.0" y="306.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="271.0" y="361.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_4" bpmnElement="SequenceFlow_4" sourceElement="_BPMNShape_ExclusiveGateway_2" targetElement="_BPMNShape_Task_12">
        <di:waypoint xsi:type="dc:Point" x="296.0" y="331.0"/>
        <di:waypoint xsi:type="dc:Point" x="338.0" y="331.0"/>
        <di:waypoint xsi:type="dc:Point" x="338.0" y="317.0"/>
        <di:waypoint xsi:type="dc:Point" x="381.0" y="317.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="_BPMNShape_EndEvent_11" bpmnElement="EndEvent_1">
        <dc:Bounds height="36.0" width="36.0" x="366.0" y="405.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_5" bpmnElement="SequenceFlow_5" sourceElement="_BPMNShape_ExclusiveGateway_2" targetElement="_BPMNShape_EndEvent_11">
        <di:waypoint xsi:type="dc:Point" x="271.0" y="356.0"/>
        <di:waypoint xsi:type="dc:Point" x="271.0" y="423.0"/>
        <di:waypoint xsi:type="dc:Point" x="366.0" y="423.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="BPMNEdge_Association_2" bpmnElement="Association_2" sourceElement="_BPMNShape_TextAnnotation_2" targetElement="_BPMNShape_BoundaryEvent_8">
        <di:waypoint xsi:type="dc:Point" x="708.0" y="258.0"/>
        <di:waypoint xsi:type="dc:Point" x="263.0" y="245.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_22" bpmnElement="SequenceFlow_22" sourceElement="_BPMNShape_StartEvent_3" targetElement="_BPMNShape_ReceiveTask_3">
        <di:waypoint xsi:type="dc:Point" x="48.0" y="205.0"/>
        <di:waypoint xsi:type="dc:Point" x="168.0" y="205.0"/>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn2:definitions>

Solution

  • Pretty simple answer to your question if you using the default jobExecutor (i.e. not the asyncjobExecutor in Activiti 5.17+).

    If you look inside the JobExecutor code you will see:

      protected int maxJobsPerAcquisition = 1;
      protected long waitTimeInMillis = 5000L;
      protected String lockOwner = UUID.randomUUID().toString();
      protected int lockTimeInMillis = 5 * 60 * 1000;
      protected ClockReader clockReader;
    

    Notice the wait time between job acquisitions defaults to 5 Sec, hence any timer less than 5 seconds will have "unpredictable" results.