WorkflowInitializer { public Optional<Workflow> store(Workflow workflow, Consumer<Optional<Workflow>> guard) throws WorkflowInitializationException { try { return storage.runInTransactionWithRetries(tx -> store(tx, workflow, guard)); } catch (IOException e) { LOG.warn("failed to write workflow {} to storage", workflow.id(), e); throw new RuntimeException(e); } } WorkflowInitializer(Storage storage, Time time); Optional<Workflow> store(Workflow workflow, Consumer<Optional<Workflow>> guard);  }
@Test public void shouldStoreNewWorkflowAndUpdateNextNaturalTriggerWithOffset() throws IOException, WorkflowInitializationException { when(transaction.workflow(HOURLY_WORKFLOW_WITH_VALID_OFFSET.id())).thenReturn(Optional.empty()); workflowInitializer.store(HOURLY_WORKFLOW_WITH_VALID_OFFSET, PASS); final Instant offsetNow = HOURLY_WORKFLOW_WITH_VALID_OFFSET.configuration().subtractOffset(NOW); final Instant nextTrigger = nextInstant(offsetNow, Schedule.HOURS); final Instant nextWithOffset = HOURLY_WORKFLOW_WITH_VALID_OFFSET.configuration().addOffset(nextTrigger); TriggerInstantSpec expectedTriggerInstantSpec = TriggerInstantSpec.create(nextTrigger, nextWithOffset); verify(transaction, never()).store(any(Workflow.class)); verify(transaction, never()).updateNextNaturalTrigger(any(), any()); verify(transaction).storeWorkflowWithNextNaturalTrigger( HOURLY_WORKFLOW_WITH_VALID_OFFSET, expectedTriggerInstantSpec); }
@Test public void shouldUpdateExistingWorkflowAndNotUpdateNextNaturalTrigger() throws IOException, WorkflowInitializationException { when(transaction.workflow(HOURLY_WORKFLOW.id())).thenReturn(Optional.of(HOURLY_WORKFLOW)); when(transaction.store(HOURLY_WORKFLOW)).thenReturn(HOURLY_WORKFLOW.id()); workflowInitializer.store(HOURLY_WORKFLOW, PASS); verify(transaction).store(HOURLY_WORKFLOW); verify(transaction, never()).updateNextNaturalTrigger(any(), any()); verify(transaction, never()).storeWorkflowWithNextNaturalTrigger(any(), any()); }
@Test public void shouldFailToReadWorkflow() throws Exception { when(transaction.workflow(HOURLY_WORKFLOW.id())).thenThrow(new IOException("read error")); try { workflowInitializer.store(HOURLY_WORKFLOW, PASS); fail(); } catch (RuntimeException e) { assertEquals("read error", e.getCause().getMessage()); } }
@Test public void shouldFailToStoreWorkflow() throws Exception { doThrow(new IOException("write error")).when(transaction).store(HOURLY_WORKFLOW); when(transaction.workflow(HOURLY_WORKFLOW.id())).thenReturn(Optional.of(HOURLY_WORKFLOW)); try { workflowInitializer.store(HOURLY_WORKFLOW, PASS); fail(); } catch (RuntimeException e) { assertEquals("write error", e.getCause().getMessage()); } }
@Test public void shouldFailIfGuardFails() throws IOException, WorkflowInitializationException { when(transaction.workflow(HOURLY_WORKFLOW.id())).thenReturn(Optional.of(HOURLY_WORKFLOW)); final RuntimeException cause = new RuntimeException("fail!"); try { workflowInitializer.store(HOURLY_WORKFLOW, wf -> { throw cause; }); } catch (RuntimeException e) { assertThat(e, is(cause)); } verify(transaction).workflow(HOURLY_WORKFLOW.id()); verifyNoMoreInteractions(transaction); }
@Test(expected = WorkflowInitializationException.class) public void shouldFailComputeNextTrigger() throws Exception { when(transaction.workflow(HOURLY_WORKFLOW.id())) .thenReturn(Optional.of(HOURLY_WORKFLOW)); workflowInitializer.store(HOURLY_WORKFLOW_WITH_INVALID_OFFSET, PASS); }
@Test public void shouldFailToStoreNextNaturalTrigger() throws Exception { doThrow(new IOException("update error")).when(transaction) .storeWorkflowWithNextNaturalTrigger(any(), any()); when(transaction.workflow(HOURLY_WORKFLOW.id())) .thenReturn(Optional.of(HOURLY_WORKFLOW)); try { workflowInitializer.store(HOURLY_WORKFLOW_WITH_VALID_OFFSET, PASS); fail(); } catch (RuntimeException e) { assertEquals("update error", e.getCause().getMessage()); } }