private void delegateAfterCommitToParent(UnitOfWork<?> uow) { Optional<UnitOfWork<?>> parent = uow.parent(); if (parent.isPresent()) { parent.get().afterCommit(this::delegateAfterCommitToParent); } else { changePhase(Phase.AFTER_COMMIT); } }
/** * Either runs the provided {@link Runnable} immediately or adds it to a {@link List} as a resource to the current * {@link UnitOfWork} if {@link SimpleQueryUpdateEmitter#inStartedPhaseOfUnitOfWork} returns {@code true}. This is * done to * ensure any emitter calls made from a message handling function are executed in the * {@link UnitOfWork.Phase#AFTER_COMMIT} phase. * <p> * The latter check requires the current UnitOfWork's phase to be {@link UnitOfWork.Phase#STARTED}. This is done * to allow users to circumvent their {@code queryUpdateTask} being handled in the AFTER_COMMIT phase. They can do * this by retrieving the current UnitOfWork and performing any of the {@link QueryUpdateEmitter} calls in a * different phase. * * @param queryUpdateTask a {@link Runnable} to be ran immediately or as a resource if {@link * SimpleQueryUpdateEmitter#inStartedPhaseOfUnitOfWork} returns {@code true} */ private void runOnAfterCommitOrNow(Runnable queryUpdateTask) { if (inStartedPhaseOfUnitOfWork()) { UnitOfWork<?> unitOfWork = CurrentUnitOfWork.get(); unitOfWork.getOrComputeResource( this.toString() + QUERY_UPDATE_TASKS_RESOURCE_KEY, resourceKey -> { List<Runnable> queryUpdateTasks = new ArrayList<>(); unitOfWork.afterCommit(uow -> queryUpdateTasks.forEach(Runnable::run)); return queryUpdateTasks; } ).add(queryUpdateTask); } else { queryUpdateTask.run(); } }
@Override public void storeToken(TrackingToken token, String processorName, int segment) { if (CurrentUnitOfWork.isStarted()) { CurrentUnitOfWork.get().afterCommit(uow -> tokens.put(new ProcessAndSegment(processorName, segment), getOrDefault(token, NULL_TOKEN))); } else { tokens.put(new ProcessAndSegment(processorName, segment), getOrDefault(token, NULL_TOKEN)); } }
@Override public void handle(List<? extends EventMessage<?>> events, Consumer<List<? extends EventMessage<?>>> processor) { if (CurrentUnitOfWork.isStarted()) { UnitOfWork<?> unitOfWorkRoot = CurrentUnitOfWork.get().root(); unitOfWorkRoot.getOrComputeResource(scheduledEventsKey, key -> { List<EventMessage<?>> allEvents = new ArrayList<>(); unitOfWorkRoot.afterCommit(uow -> schedule(allEvents, processor)); return allEvents; }).addAll(events); } else { schedule(events, processor); } }
unitOfWork.afterCommit(u -> { if (u.parent().isPresent() && !u.root().phase().isAfter(AFTER_COMMIT)) { u.root().afterCommit(w -> doWithEvents(this::afterCommit, eventQueue)); } else { doWithEvents(this::afterCommit, eventQueue);
@Override public void publish(List<? extends EventMessage<?>> events) { Stream<MessageMonitor.MonitorCallback> ingested = events.stream().map(messageMonitor::onMessageIngested); if (CurrentUnitOfWork.isStarted()) { UnitOfWork<?> unitOfWork = CurrentUnitOfWork.get(); Assert.state(!unitOfWork.phase().isAfter(PREPARE_COMMIT), () -> "It is not allowed to publish events when the current Unit of Work has already been " + "committed. Please start a new Unit of Work before publishing events."); Assert.state(!unitOfWork.root().phase().isAfter(PREPARE_COMMIT), () -> "It is not allowed to publish events when the root Unit of Work has already been " + "committed."); unitOfWork.afterCommit(u -> ingested.forEach(MessageMonitor.MonitorCallback::reportSuccess)); unitOfWork.onRollback(uow -> ingested.forEach( message -> message.reportFailure(uow.getExecutionResult().getExceptionResult()) )); eventsQueue(unitOfWork).addAll(events); } else { try { prepareCommit(intercept(events)); commit(events); afterCommit(events); ingested.forEach(MessageMonitor.MonitorCallback::reportSuccess); } catch (Exception e) { ingested.forEach(m -> m.reportFailure(e)); throw e; } } }
private void delegateAfterCommitToParent(UnitOfWork<?> uow) { Optional<UnitOfWork<?>> parent = uow.parent(); if (parent.isPresent()) { parent.get().afterCommit(this::delegateAfterCommitToParent); } else { changePhase(Phase.AFTER_COMMIT); } }
private void delegateAfterCommitToParent(UnitOfWork<?> uow) { Optional<UnitOfWork<?>> parent = uow.parent(); if (parent.isPresent()) { parent.get().afterCommit(this::delegateAfterCommitToParent); } else { changePhase(Phase.AFTER_COMMIT); } }
/** * Either runs the provided {@link Runnable} immediately or adds it to a {@link List} as a resource to the current * {@link UnitOfWork} if {@link SimpleQueryBus#inStartedPhaseOfUnitOfWork} returns {@code true}. This is done to * ensure any emitter calls made from a message handling function are executed in the * {@link UnitOfWork.Phase#AFTER_COMMIT} phase. * <p> * The latter check requires the current UnitOfWork's phase to be {@link UnitOfWork.Phase#STARTED}. This is done * to allow users to circumvent their {@code queryUpdateTask} being handled in the AFTER_COMMIT phase. They can do * this by retrieving the current UnitOfWork and performing any of the {@link QueryUpdateEmitter} calls in a * different phase. * * @param queryUpdateTask a {@link Runnable} to be ran immediately or as a resource if {@link * SimpleQueryBus#inStartedPhaseOfUnitOfWork} returns {@code true} */ private void runOnAfterCommitOrNow(Runnable queryUpdateTask) { if (inStartedPhaseOfUnitOfWork()) { UnitOfWork<?> unitOfWork = CurrentUnitOfWork.get(); unitOfWork.getOrComputeResource( this.toString() + QUERY_UPDATE_TASKS_RESOURCE_KEY, resourceKey -> { List<Runnable> queryUpdateTasks = new ArrayList<>(); unitOfWork.afterCommit(uow -> queryUpdateTasks.forEach(Runnable::run)); return queryUpdateTasks; } ).add(queryUpdateTask); } else { queryUpdateTask.run(); } }
/** * Either runs the provided {@link Runnable} immediately or adds it to a {@link List} as a resource to the current * {@link UnitOfWork} if {@link SimpleQueryUpdateEmitter#inStartedPhaseOfUnitOfWork} returns {@code true}. This is * done to * ensure any emitter calls made from a message handling function are executed in the * {@link UnitOfWork.Phase#AFTER_COMMIT} phase. * <p> * The latter check requires the current UnitOfWork's phase to be {@link UnitOfWork.Phase#STARTED}. This is done * to allow users to circumvent their {@code queryUpdateTask} being handled in the AFTER_COMMIT phase. They can do * this by retrieving the current UnitOfWork and performing any of the {@link QueryUpdateEmitter} calls in a * different phase. * * @param queryUpdateTask a {@link Runnable} to be ran immediately or as a resource if {@link * SimpleQueryUpdateEmitter#inStartedPhaseOfUnitOfWork} returns {@code true} */ private void runOnAfterCommitOrNow(Runnable queryUpdateTask) { if (inStartedPhaseOfUnitOfWork()) { UnitOfWork<?> unitOfWork = CurrentUnitOfWork.get(); unitOfWork.getOrComputeResource( this.toString() + QUERY_UPDATE_TASKS_RESOURCE_KEY, resourceKey -> { List<Runnable> queryUpdateTasks = new ArrayList<>(); unitOfWork.afterCommit(uow -> queryUpdateTasks.forEach(Runnable::run)); return queryUpdateTasks; } ).add(queryUpdateTask); } else { queryUpdateTask.run(); } }
@Override public void storeToken(TrackingToken token, String processorName, int segment) { if (CurrentUnitOfWork.isStarted()) { CurrentUnitOfWork.get().afterCommit(uow -> tokens.put(new ProcessAndSegment(processorName, segment), getOrDefault(token, NULL_TOKEN))); } else { tokens.put(new ProcessAndSegment(processorName, segment), getOrDefault(token, NULL_TOKEN)); } }
@Override public void storeToken(TrackingToken token, String processorName, int segment) { if (CurrentUnitOfWork.isStarted()) { CurrentUnitOfWork.get().afterCommit(uow -> tokens.put(new ProcessAndSegment(processorName, segment), getOrDefault(token, NULL_TOKEN))); } else { tokens.put(new ProcessAndSegment(processorName, segment), getOrDefault(token, NULL_TOKEN)); } }
/** * Commit/rollback Kafka work once a given unit of work is committed/rollback. */ private void handleActiveUnitOfWork(Producer<K, V> producer, Map<Future<RecordMetadata>, ? super EventMessage<?>> futures, Map<? super EventMessage<?>, MonitorCallback> monitorCallbacks, ConfirmationMode confirmationMode) { UnitOfWork<?> uow = CurrentUnitOfWork.get(); uow.afterCommit(u -> completeKafkaWork(monitorCallbacks, producer, confirmationMode, futures)); uow.onRollback(u -> rollbackKafkaWork(producer, confirmationMode)); }
@Override public void handle(List<? extends EventMessage<?>> events, Consumer<List<? extends EventMessage<?>>> processor) { if (CurrentUnitOfWork.isStarted()) { UnitOfWork<?> unitOfWorkRoot = CurrentUnitOfWork.get().root(); unitOfWorkRoot.getOrComputeResource(scheduledEventsKey, key -> { List<EventMessage<?>> allEvents = new ArrayList<>(); unitOfWorkRoot.afterCommit(uow -> schedule(allEvents, processor)); return allEvents; }).addAll(events); } else { schedule(events, processor); } }
@Override public void handle(List<? extends EventMessage<?>> events, Consumer<List<? extends EventMessage<?>>> processor) { if (CurrentUnitOfWork.isStarted()) { UnitOfWork<?> unitOfWorkRoot = CurrentUnitOfWork.get().root(); unitOfWorkRoot.getOrComputeResource(scheduledEventsKey, key -> { List<EventMessage<?>> allEvents = new ArrayList<>(); unitOfWorkRoot.afterCommit(uow -> schedule(allEvents, processor)); return allEvents; }).addAll(events); } else { schedule(events, processor); } }
/** * Commit/rollback Kafka work once a given unit of work is committed/rollback. */ private void handleActiveUnitOfWork(Producer<K, V> producer, Map<Future<RecordMetadata>, ? super EventMessage<?>> futures, Map<? super EventMessage<?>, MonitorCallback> monitorCallbacks, ConfirmationMode confirmationMode) { UnitOfWork<?> uow = CurrentUnitOfWork.get(); uow.afterCommit(u -> completeKafkaWork(monitorCallbacks, producer, confirmationMode, futures)); uow.onRollback(u -> rollbackKafkaWork(producer, confirmationMode)); }
unitOfWork.afterCommit(u -> { if (u.parent().isPresent() && !u.root().phase().isAfter(AFTER_COMMIT)) { u.root().afterCommit(w -> doWithEvents(this::afterCommit, eventQueue)); } else { doWithEvents(this::afterCommit, eventQueue);
unitOfWork.afterCommit(u -> { if (u.parent().isPresent() && !u.root().phase().isAfter(AFTER_COMMIT)) { u.root().afterCommit(w -> doWithEvents(this::afterCommit, eventQueue)); } else { doWithEvents(this::afterCommit, eventQueue);
@Override public void publish(List<? extends EventMessage<?>> events) { Stream<MessageMonitor.MonitorCallback> ingested = events.stream().map(messageMonitor::onMessageIngested); if (CurrentUnitOfWork.isStarted()) { UnitOfWork<?> unitOfWork = CurrentUnitOfWork.get(); Assert.state(!unitOfWork.phase().isAfter(PREPARE_COMMIT), () -> "It is not allowed to publish events when the current Unit of Work has already been " + "committed. Please start a new Unit of Work before publishing events."); Assert.state(!unitOfWork.root().phase().isAfter(PREPARE_COMMIT), () -> "It is not allowed to publish events when the root Unit of Work has already been " + "committed."); unitOfWork.afterCommit(u -> ingested.forEach(MessageMonitor.MonitorCallback::reportSuccess)); unitOfWork.onRollback(u -> ingested.forEach(m -> m.reportFailure(u.getExecutionResult().getExceptionResult()))); eventsQueue(unitOfWork).addAll(events); } else { try { prepareCommit(intercept(events)); commit(events); afterCommit(events); ingested.forEach(MessageMonitor.MonitorCallback::reportSuccess); } catch (Exception e) { ingested.forEach(m -> m.reportFailure(e)); throw e; } } }
@Override public void publish(List<? extends EventMessage<?>> events) { Stream<MessageMonitor.MonitorCallback> ingested = events.stream().map(messageMonitor::onMessageIngested); if (CurrentUnitOfWork.isStarted()) { UnitOfWork<?> unitOfWork = CurrentUnitOfWork.get(); Assert.state(!unitOfWork.phase().isAfter(PREPARE_COMMIT), () -> "It is not allowed to publish events when the current Unit of Work has already been " + "committed. Please start a new Unit of Work before publishing events."); Assert.state(!unitOfWork.root().phase().isAfter(PREPARE_COMMIT), () -> "It is not allowed to publish events when the root Unit of Work has already been " + "committed."); unitOfWork.afterCommit(u -> ingested.forEach(MessageMonitor.MonitorCallback::reportSuccess)); unitOfWork.onRollback(uow -> ingested.forEach( message -> message.reportFailure(uow.getExecutionResult().getExceptionResult()) )); eventsQueue(unitOfWork).addAll(events); } else { try { prepareCommit(intercept(events)); commit(events); afterCommit(events); ingested.forEach(MessageMonitor.MonitorCallback::reportSuccess); } catch (Exception e) { ingested.forEach(m -> m.reportFailure(e)); throw e; } } }