@Override public CompletableFuture<Void> receive(Event event, long expectedCounter) throws IsClosedException { ensureRunning(); log.info("Received event {}", event); // TODO: optional retry on transaction conflict queuedEvents.increment(); return Striping.supplyAsyncStriped(() -> transition(event, expectedCounter), event.workflowInstance(), eventProcessingExecutor) .thenAccept((tuple) -> postTransition(tuple._1, tuple._2)); }
@Override public CompletionStage<Void> trigger(WorkflowInstance workflowInstance, Trigger trigger, TriggerParameters parameters) throws IsClosedException { ensureRunning(); log.debug("Trigger {}", workflowInstance); // TODO: optional retry on transaction conflict return CompletableFuture.runAsync(() -> initialize(workflowInstance), withMDC()).thenCompose((ignore) -> { final Event event = Event.triggerExecution(workflowInstance, trigger, parameters); try { return receive(event); } catch (IsClosedException isClosedException) { log.warn("Failed to send 'triggerExecution' event", isClosedException); // Best effort attempt to rollback the creation of the NEW state try { storage.deleteActiveState(workflowInstance); } catch (IOException e) { log.warn("Failed to remove dangling NEW state for: {}", workflowInstance, e); } throw new RuntimeException(isClosedException); } }); }
verifyCounter(event, expectedCounter, currentRunState.get()); log.info("Received event (verified) {}", event); updateResourceCounters(tx, event, currentRunState.get(), nextRunState);
private void updateResourceCounters(StorageTransaction tx, Event event, RunState currentRunState, RunState nextRunState) throws IOException { // increment counters if event is dequeue if (isDequeue(event) && nextRunState.data().resourceIds().isPresent()) { tryUpdatingCounter(currentRunState, tx, nextRunState.data().resourceIds().get()); } // decrement counters if transitioning from a state that consumes resources // to a state that doesn't consume any resources if (isConsumingResources(currentRunState.state()) && !isConsumingResources(nextRunState.state())) { if (nextRunState.data().resourceIds().isPresent()) { for (String resource : nextRunState.data().resourceIds().get()) { tx.updateCounter(shardedCounter, resource, -1); } } else { log.error("Resource ids are missing for {} when transitioning from {} to {}.", nextRunState.workflowInstance(), currentRunState, nextRunState); } } }
@Override public CompletableFuture<Void> receive(Event event) throws IsClosedException { return receive(event, Long.MAX_VALUE); }
final QueuedStateManager queuedStateManager = closer.register(new QueuedStateManager(time, eventProcessingExecutor, storage, eventConsumerFactory.apply(environment, stats), eventConsumerExecutor, fanOutput(outputHandlers), shardedCounter));