@Test public void shouldRecreateATimerForTheSpecifiedAmountOfRepetitions() { // given testClient.deploy(TWO_REPS_CYCLE_WORKFLOW); brokerRule.getClock().pinCurrentTime(); testClient.createWorkflowInstance(PROCESS_ID); // when assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).getFirst()).isNotNull(); brokerRule.getClock().addTime(Duration.ofSeconds(5)); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2)).hasSize(2); brokerRule.getClock().addTime(Duration.ofSeconds(5)); testClient.completeJobOfType("type"); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .withElementId(PROCESS_ID) .exists()) .isTrue(); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).count()).isEqualTo(2); }
@Test public void shouldCreateMultipleWorkflowInstancesWithRepeatingTimer() { // when testClient.deployWithResponse(THREE_SEC_MODEL); // then assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).exists()).isTrue(); brokerRule.getClock().addTime(Duration.ofSeconds(3)); assertThat(RecordingExporter.timerRecords(TimerIntent.TRIGGERED).exists()).isTrue(); assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_READY) .withElementId("process_3") .exists()) .isTrue(); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).count()).isEqualTo(2); brokerRule.getClock().addTime(Duration.ofSeconds(3)); assertThat(RecordingExporter.timerRecords(TimerIntent.TRIGGERED).limit(2).count()).isEqualTo(2); assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_READY) .withElementId("process_3") .limit(2) .count()) .isEqualTo(2); }
@Test public void shouldCreateMultipleWorkflowInstancesWithRepeatingTimer() { // when testClient.deployWithResponse(THREE_SEC_MODEL); // then assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).exists()).isTrue(); brokerRule.getClock().addTime(Duration.ofSeconds(3)); assertThat(RecordingExporter.timerRecords(TimerIntent.TRIGGERED).exists()).isTrue(); assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_ACTIVATING) .withElementId("process_3") .exists()) .isTrue(); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).count()).isEqualTo(2); brokerRule.getClock().addTime(Duration.ofSeconds(3)); assertThat(RecordingExporter.timerRecords(TimerIntent.TRIGGERED).limit(2).count()).isEqualTo(2); assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_ACTIVATING) .withElementId("process_3") .limit(2) .count()) .isEqualTo(2); }
@Test public void shouldRecreateATimerForTheSpecifiedAmountOfRepetitions() { // given testClient.deploy(TWO_REPS_CYCLE_WORKFLOW); brokerRule.getClock().pinCurrentTime(); testClient.createWorkflowInstance(PROCESS_ID); // when assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).getFirst()).isNotNull(); brokerRule.getClock().addTime(Duration.ofSeconds(5)); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2)).hasSize(2); brokerRule.getClock().addTime(Duration.ofSeconds(5)); testClient.completeJobOfType("type"); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .withElementId(PROCESS_ID) .exists()) .isTrue(); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).count()).isEqualTo(2); }
@Test public void shouldCancelTimer() { // given testClient.deploy(WORKFLOW_WITH_TIMERS); testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", "123")); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).exists()).isTrue(); // when brokerRule.getClock().addTime(Duration.ofSeconds(1)); // then assertThat(RecordingExporter.timerRecords(TimerIntent.CANCELED).limit(1)) .extracting(r -> r.getValue().getHandlerFlowNodeId()) .hasSize(1) .contains("timer-2"); }
@Test public void shouldCancelTimer() { // given testClient.deploy(WORKFLOW_WITH_TIMERS); testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", "123")); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).exists()); // when brokerRule.getClock().addTime(Duration.ofSeconds(1)); // then assertThat(RecordingExporter.timerRecords(TimerIntent.CANCELED).limit(1)) .extracting(r -> r.getValue().getHandlerFlowNodeId()) .hasSize(1) .contains("timer-2"); }
@Test public void shouldRecreateATimerInfinitely() { // given final int expectedRepetitions = 5; testClient.deploy(INFINITE_CYCLE_WORKFLOW); brokerRule.getClock().pinCurrentTime(); testClient.createWorkflowInstance(PROCESS_ID); // when assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).getFirst()).isNotNull(); for (int i = 2; i <= expectedRepetitions; i++) { brokerRule.getClock().addTime(Duration.ofSeconds(5)); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(i).count()).isEqualTo(i); } testClient.completeJobOfType("type"); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .withElementId(PROCESS_ID) .exists()) .isTrue(); assertThat( RecordingExporter.timerRecords(TimerIntent.CREATED).limit(expectedRepetitions).count()) .isEqualTo(expectedRepetitions); } }
@Test public void shouldRecreateATimerInfinitely() { // given final int expectedRepetitions = 5; testClient.deploy(INFINITE_CYCLE_WORKFLOW); brokerRule.getClock().pinCurrentTime(); testClient.createWorkflowInstance(PROCESS_ID); // when assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).getFirst()).isNotNull(); for (int i = 2; i <= expectedRepetitions; i++) { brokerRule.getClock().addTime(Duration.ofSeconds(5)); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(i).count()).isEqualTo(i); } testClient.completeJobOfType("type"); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .withElementId(PROCESS_ID) .exists()) .isTrue(); assertThat( RecordingExporter.timerRecords(TimerIntent.CREATED).limit(expectedRepetitions).count()) .isEqualTo(expectedRepetitions); } }
@Test public void shouldCreateMultipleInstanceAtTheCorrectTimes() { // when testClient.deploy(MULTI_TIMER_START_MODEL); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).count()).isEqualTo(2); brokerRule.getClock().addTime(Duration.ofSeconds(2)); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.EVENT_TRIGGERED) .withElementId("start_4") .exists()) .isTrue(); assertThat( RecordingExporter.workflowInstanceRecords(EVENT_ACTIVATED) .withElementId("end_4") .exists()) .isTrue(); brokerRule.getClock().addTime(Duration.ofSeconds(1)); assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.EVENT_TRIGGERED) .withElementId("start_5") .exists()) .isTrue(); assertThat( RecordingExporter.workflowInstanceRecords(EVENT_ACTIVATED) .withElementId("end_5") .exists()) .isTrue(); }
@Test public void shouldUpdateWorkflow() { // when testClient.deploy(SIMPLE_MODEL); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).exists()).isTrue(); brokerRule.getClock().addTime(Duration.ofSeconds(1)); // then assertThat( RecordingExporter.workflowInstanceRecords(EVENT_ACTIVATED) .withElementId("end_1") .withBpmnProcessId("process") .withVersion(1) .exists()) .isTrue(); // when testClient.deploy(REPEATING_MODEL); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).count()).isEqualTo(2); brokerRule.getClock().addTime(Duration.ofSeconds(2)); assertThat( RecordingExporter.workflowInstanceRecords(EVENT_ACTIVATED) .withElementId("end_2") .withBpmnProcessId("process") .withVersion(2) .exists()) .isTrue(); }
@Test public void shouldRecreateATimerWithCycle() { // given testClient.deploy(TWO_REPS_CYCLE_WORKFLOW); brokerRule.getClock().pinCurrentTime(); final long nowMs = brokerRule.getClock().getCurrentTimeInMillis(); testClient.createWorkflowInstance(PROCESS_ID); // when final Record<TimerRecordValue> timerCreatedRecord = RecordingExporter.timerRecords(TimerIntent.CREATED).getFirst(); brokerRule.getClock().addTime(Duration.ofSeconds(5)); final Record<TimerRecordValue> timerRescheduledRecord = RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).getLast(); // then assertThat(timerCreatedRecord).isNotEqualTo(timerRescheduledRecord); assertThat(timerCreatedRecord.getValue().getDueDate()).isEqualTo(nowMs + 1000); assertThat(timerRescheduledRecord.getValue().getDueDate()).isEqualTo(nowMs + 6000); }
@Test public void shouldRecreateATimerWithCycle() { // given testClient.deploy(TWO_REPS_CYCLE_WORKFLOW); brokerRule.getClock().pinCurrentTime(); final long nowMs = brokerRule.getClock().getCurrentTimeInMillis(); testClient.createWorkflowInstance(PROCESS_ID); // when final Record<TimerRecordValue> timerCreatedRecord = RecordingExporter.timerRecords(TimerIntent.CREATED).getFirst(); brokerRule.getClock().addTime(Duration.ofSeconds(5)); final Record<TimerRecordValue> timerRescheduledRecord = RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).getLast(); // then assertThat(timerCreatedRecord).isNotEqualTo(timerRescheduledRecord); assertThat(timerCreatedRecord.getValue().getDueDate()).isEqualTo(nowMs + 1000); assertThat(timerRescheduledRecord.getValue().getDueDate()).isEqualTo(nowMs + 6000); }
@Test public void shouldUpdateTimerPeriod() { // when long beginTime = brokerRule.getClock().getCurrentTimeInMillis(); testClient.deploy(THREE_SEC_MODEL); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).exists()).isTrue(); brokerRule.getClock().addTime(Duration.ofSeconds(3)); // then TimerRecordValue timerRecord = RecordingExporter.timerRecords(TimerIntent.TRIGGERED).getFirst().getValue(); Assertions.assertThat(timerRecord).hasDueDate(beginTime + 3000); // when beginTime = brokerRule.getClock().getCurrentTimeInMillis(); final BpmnModelInstance slowerModel = Bpmn.createExecutableProcess("process_3") .startEvent("start_4") .timerWithCycle("R2/PT4S") .endEvent("end_4") .done(); testClient.deploy(slowerModel); // then assertThat(RecordingExporter.timerRecords(TimerIntent.CANCELED).getFirst()).isNotNull(); timerRecord = RecordingExporter.timerRecords(TimerIntent.CREATED).skip(2).getFirst().getValue(); Assertions.assertThat(timerRecord).hasDueDate(beginTime + 4000); brokerRule.getClock().addTime(Duration.ofSeconds(3)); assertThat(RecordingExporter.timerRecords(TimerIntent.TRIGGERED).limit(1).count()).isEqualTo(1); brokerRule.getClock().addTime(Duration.ofSeconds(1)); assertThat(RecordingExporter.timerRecords(TimerIntent.TRIGGERED).limit(2).count()).isEqualTo(2); }
@Test public void shouldCancelSubscriptionsWhenScopeIsTerminated() { // given testClient.deploy(WORKFLOW_WITH_TIMER_AND_MESSAGE); final long workflowInstanceKey = testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", "123")); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(1).exists()); assertThat( RecordingExporter.workflowInstanceSubscriptionRecords( WorkflowInstanceSubscriptionIntent.OPENED) .limit(1) .exists()); // when testClient.cancelWorkflowInstance(workflowInstanceKey); // then assertThat(RecordingExporter.timerRecords(TimerIntent.CANCELED).limit(1)) .extracting(r -> r.getValue().getHandlerFlowNodeId()) .hasSize(1) .contains("timer"); assertThat( RecordingExporter.workflowInstanceSubscriptionRecords( WorkflowInstanceSubscriptionIntent.CLOSED) .limit(1)) .extracting(r -> r.getValue().getMessageName()) .hasSize(1) .contains("msg"); }
@Test public void shouldContinueWhenTimerIsTriggered() { // given testClient.deploy(WORKFLOW_WITH_TIMERS); testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", "123")); final Record<WorkflowInstanceRecordValue> gatewayEvent = RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.GATEWAY_ACTIVATED) .getFirst(); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).exists()); // when brokerRule.getClock().addTime(Duration.ofSeconds(1)); // then final Record<TimerRecordValue> triggeredEvent = RecordingExporter.timerRecords(TimerIntent.TRIGGERED).getFirst(); Assertions.assertThat(triggeredEvent.getValue()) .hasElementInstanceKey(gatewayEvent.getKey()) .hasHandlerFlowNodeId("timer-1"); assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.SEQUENCE_FLOW_TAKEN) .withElementId("to-end1") .exists()) .isTrue(); assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .withElementId(PROCESS_ID) .exists()); }
@Test public void shouldCreateTimer() { // given testClient.deploy(WORKFLOW_WITH_TIMERS); // when testClient.createWorkflowInstance(PROCESS_ID); // then final Record<WorkflowInstanceRecordValue> gatewayEvent = RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.GATEWAY_ACTIVATED) .getFirst(); final List<Record<TimerRecordValue>> timerEvents = RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).asList(); assertThat(timerEvents) .hasSize(2) .extracting( r -> tuple(r.getValue().getHandlerFlowNodeId(), r.getValue().getElementInstanceKey())) .contains(tuple("timer-1", gatewayEvent.getKey()), tuple("timer-2", gatewayEvent.getKey())); }
@Test public void shouldCreateTimer() { // given testClient.deploy(WORKFLOW_WITH_TIMERS); // when testClient.createWorkflowInstance(PROCESS_ID); // then final Record<WorkflowInstanceRecordValue> gatewayEvent = RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_ACTIVATED) .withElementType(BpmnElementType.EVENT_BASED_GATEWAY) .getFirst(); final List<Record<TimerRecordValue>> timerEvents = RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).asList(); assertThat(timerEvents) .hasSize(2) .extracting( r -> tuple(r.getValue().getHandlerFlowNodeId(), r.getValue().getElementInstanceKey())) .contains(tuple("timer-1", gatewayEvent.getKey()), tuple("timer-2", gatewayEvent.getKey())); }
@Test public void testLifeCycle() { // given final BpmnModelInstance workflow = Bpmn.createExecutableProcess(PROCESS_ID) .startEvent() .intermediateCatchEvent("timer", c -> c.timerWithDuration("PT0S")) .endEvent() .done(); testClient.deploy(workflow); testClient.createWorkflowInstance(PROCESS_ID); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .withElementId(PROCESS_ID) .exists()) .isTrue(); assertThat(RecordingExporter.workflowInstanceRecords().withElementId("timer").limit(5)) .extracting(r -> r.getMetadata().getIntent()) .containsExactly( WorkflowInstanceIntent.EVENT_ACTIVATING, WorkflowInstanceIntent.EVENT_ACTIVATED, WorkflowInstanceIntent.EVENT_OCCURRED, WorkflowInstanceIntent.EVENT_TRIGGERING, WorkflowInstanceIntent.EVENT_TRIGGERED); assertThat(RecordingExporter.timerRecords().limit(4)) .extracting(r -> r.getMetadata().getIntent()) .containsExactly( TimerIntent.CREATE, TimerIntent.CREATED, TimerIntent.TRIGGER, TimerIntent.TRIGGERED); }
@Test public void testLifecycle() { // given testClient.deploy(WORKFLOW_WITH_TIMERS); testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", "123")); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).limit(2).exists()); // when brokerRule.getClock().addTime(Duration.ofSeconds(1)); // then assertThat( RecordingExporter.workflowInstanceRecords() .skipUntil( r -> r.getMetadata().getIntent() == WorkflowInstanceIntent.GATEWAY_ACTIVATED) .limitToWorkflowInstanceCompleted()) .extracting(r -> tuple(r.getValue().getElementId(), r.getMetadata().getIntent())) .containsExactly( tuple("gateway", WorkflowInstanceIntent.GATEWAY_ACTIVATED), tuple("timer-1", WorkflowInstanceIntent.EVENT_OCCURRED), tuple("timer-1", WorkflowInstanceIntent.EVENT_TRIGGERING), tuple("timer-1", WorkflowInstanceIntent.EVENT_TRIGGERED), tuple("to-end1", WorkflowInstanceIntent.SEQUENCE_FLOW_TAKEN), tuple("end1", WorkflowInstanceIntent.EVENT_ACTIVATING), tuple("end1", WorkflowInstanceIntent.EVENT_ACTIVATED), tuple(PROCESS_ID, WorkflowInstanceIntent.ELEMENT_COMPLETING), tuple(PROCESS_ID, WorkflowInstanceIntent.ELEMENT_COMPLETED)); }