private boolean exists(WorkflowInstanceRecordStream stream) { try { return stream.exists(); } catch (StreamWrapperException e) { return false; } }
private boolean exists(WorkflowInstanceRecordStream stream) { try { return stream.exists(); } catch (StreamWrapperException e) { return false; } }
/** * Blocks and wait until the workflow identified by the key has been completed. * * @param workflowInstanceKey ID of the workflow */ public void awaitWorkflowCompletion(long workflowInstanceKey) { TestUtil.waitUntil( () -> workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .filter(r -> r.getKey() == workflowInstanceKey) .exists()); }
/** * Blocks and wait until the workflow identified by the key has been completed. * * @param workflowInstanceKey ID of the workflow */ public void awaitWorkflowCompletion(long workflowInstanceKey) { TestUtil.waitUntil( () -> workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .filter(r -> r.getKey() == workflowInstanceKey) .exists()); }
@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 shouldCorrelateMessageAndContinue() { // given testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("orderId", "order-123")); // when assertThat( testClient .receiveWorkflowInstanceSubscriptions() .withMessageName("order canceled") .withIntent(WorkflowInstanceSubscriptionIntent.OPENED) .limit(1) .getFirst()) .isNotNull(); testClient.publishMessage("order canceled", "order-123"); // then assertThat( RecordingExporter.workflowInstanceRecords(continueState) .withElementId(continuedElementId) .exists()) .isTrue(); assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.SEQUENCE_FLOW_TAKEN) .withElementId("to-end") .exists()) .isTrue(); } }
@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 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 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_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 shouldUpdateWorkflow() { // when testClient.deploy(SIMPLE_MODEL); assertThat(RecordingExporter.timerRecords(TimerIntent.CREATED).exists()).isTrue(); brokerRule.getClock().addTime(Duration.ofSeconds(1)); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_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(WorkflowInstanceIntent.ELEMENT_ACTIVATED) .withElementId("end_2") .withBpmnProcessId("process") .withVersion(2) .exists()) .isTrue(); }
@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 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 shouldContinueWhenMessageIsCorrelated() { // given testClient.deploy(WORKFLOW_WITH_MESSAGES); testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", "123")); final Record<WorkflowInstanceRecordValue> gatewayEvent = RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.GATEWAY_ACTIVATED) .getFirst(); // when testClient.publishMessage("msg-1", "123"); // then final Record<WorkflowInstanceSubscriptionRecordValue> triggeredEvent = RecordingExporter.workflowInstanceSubscriptionRecords( WorkflowInstanceSubscriptionIntent.CORRELATED) .getFirst(); Assertions.assertThat(triggeredEvent.getValue()) .hasElementInstanceKey(gatewayEvent.getKey()) .hasMessageName("msg-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 shouldTriggerAtSpecifiedTimeDate() { // given final Instant triggerTime = brokerRule.getClock().getCurrentTime().plusMillis(2000); final BpmnModelInstance model = Bpmn.createExecutableProcess("process") .startEvent("start_2") .timerWithDate(triggerTime.toString()) .endEvent("end_2") .done(); testClient.deploy(model); // when brokerRule.getClock().addTime(Duration.ofSeconds(2)); // then final TimerRecordValue timerRecord = RecordingExporter.timerRecords(TimerIntent.TRIGGERED).getFirst().getValue(); Assertions.assertThat(timerRecord) .hasDueDate(triggerTime.toEpochMilli()) .hasHandlerFlowNodeId("start_2") .hasElementInstanceKey(NO_ELEMENT_INSTANCE); assertThat( RecordingExporter.workflowInstanceRecords(EVENT_ACTIVATED) .withElementId("end_2") .exists()) .isTrue(); }
@Test public void shouldTriggerAtSpecifiedTimeDate() { // given final Instant triggerTime = brokerRule.getClock().getCurrentTime().plusMillis(2000); final BpmnModelInstance model = Bpmn.createExecutableProcess("process") .startEvent("start_2") .timerWithDate(triggerTime.toString()) .endEvent("end_2") .done(); testClient.deploy(model); // when brokerRule.getClock().addTime(Duration.ofSeconds(2)); // then final TimerRecordValue timerRecord = RecordingExporter.timerRecords(TimerIntent.TRIGGERED).getFirst().getValue(); Assertions.assertThat(timerRecord) .hasDueDate(triggerTime.toEpochMilli()) .hasHandlerFlowNodeId("start_2") .hasElementInstanceKey(NO_ELEMENT_INSTANCE); assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_ACTIVATED) .withElementId("end_2") .exists()) .isTrue(); }
@Test public void shouldOpenSubscriptionsWhenIncidentIsResolved() { // given testClient.createWorkflowInstance(PROCESS_ID, MsgPackUtil.asMsgPack("key-1", "k1")); final Record<IncidentRecordValue> incidentCreatedRecord = RecordingExporter.incidentRecords(IncidentIntent.CREATED).getFirst(); // when testClient.updatePayload( incidentCreatedRecord.getValue().getElementInstanceKey(), "{'key-1':'k1', 'key-2':'k2'}"); testClient.resolveIncident(incidentCreatedRecord.getKey()); // then assertThat( RecordingExporter.workflowInstanceSubscriptionRecords( WorkflowInstanceSubscriptionIntent.OPENED) .limit(2)) .extracting(Record::getValue) .extracting(WorkflowInstanceSubscriptionRecordValue::getMessageName) .containsExactlyInAnyOrder("msg-1", "msg-2"); // and testClient.publishMessage("msg-2", "k2"); assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .withElementId(PROCESS_ID) .exists()) .isTrue(); }
@Test public void shouldOpenSubscriptionsWhenIncidentIsResolved() { // given testClient.createWorkflowInstance(PROCESS_ID, MsgPackUtil.asMsgPack("key-1", "k1")); final Record<IncidentRecordValue> incidentCreatedRecord = RecordingExporter.incidentRecords(IncidentIntent.CREATED).getFirst(); // when testClient.updatePayload( incidentCreatedRecord.getValue().getElementInstanceKey(), "{'key-1':'k1', 'key-2':'k2'}"); testClient.resolveIncident(incidentCreatedRecord.getKey()); // then assertThat( RecordingExporter.workflowInstanceSubscriptionRecords( WorkflowInstanceSubscriptionIntent.OPENED) .limit(2)) .extracting(Record::getValue) .extracting(WorkflowInstanceSubscriptionRecordValue::getMessageName) .containsExactlyInAnyOrder("msg-1", "msg-2"); // and testClient.publishMessage("msg-2", "k2"); assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .withElementId(PROCESS_ID) .exists()) .isTrue(); }