/** * Run a given {@code deadlineCall} immediately, or schedule it for the {@link UnitOfWork} it's 'prepare commit' * phase if a UnitOfWork is active. This is required as the DeadlineManager schedule message which we want to happen * on order with other message being handled. * * @param deadlineCall a {@link Runnable} to be executed now or on prepare commit if a {@link UnitOfWork} is active */ protected void runOnPrepareCommitOrNow(Runnable deadlineCall) { if (CurrentUnitOfWork.isStarted()) { CurrentUnitOfWork.get().onPrepareCommit(unitOfWork -> deadlineCall.run()); } else { deadlineCall.run(); } }
@Override public AnnotatedSaga<T> doLoad(String sagaIdentifier) { UnitOfWork<?> unitOfWork = CurrentUnitOfWork.get(); UnitOfWork<?> processRoot = unitOfWork.root(); AnnotatedSaga<T> loadedSaga = managedSagas.computeIfAbsent(sagaIdentifier, id -> { AnnotatedSaga<T> result = doLoadSaga(sagaIdentifier); if (result != null) { processRoot.onCleanup(u -> managedSagas.remove(id)); } return result; }); if (loadedSaga != null && unsavedSagaResource(processRoot).add(sagaIdentifier)) { unitOfWork.onPrepareCommit(u -> { unsavedSagaResource(processRoot).remove(sagaIdentifier); commit(loadedSaga); }); } return loadedSaga; }
@Override public void eventHandled(EventMessage<?> msg) { if (++counter >= threshold && msg instanceof DomainEventMessage) { if (CurrentUnitOfWork.isStarted()) { CurrentUnitOfWork.get().onPrepareCommit( u -> scheduleSnapshot((DomainEventMessage) msg)); } else { scheduleSnapshot((DomainEventMessage) msg); } counter = 0; } }
@Override public AnnotatedSaga<T> doCreateInstance(String sagaIdentifier, Supplier<T> sagaFactory) { try { UnitOfWork<?> unitOfWork = CurrentUnitOfWork.get(), processRoot = unitOfWork.root(); T sagaRoot = sagaFactory.get(); resourceInjector.injectResources(sagaRoot); AnnotatedSaga<T> saga = new AnnotatedSaga<>(sagaIdentifier, Collections.emptySet(), sagaRoot, sagaModel); unsavedSagaResource(processRoot).add(sagaIdentifier); unitOfWork.onPrepareCommit(u -> { if (saga.isActive()) { storeSaga(saga); saga.getAssociationValues().commit(); unsavedSagaResource(processRoot).remove(sagaIdentifier); } }); managedSagas.put(sagaIdentifier, saga); processRoot.onCleanup(u -> managedSagas.remove(sagaIdentifier)); return saga; } catch (Exception e) { throw new SagaCreationException("An error occurred while attempting to create a new managed instance", e); } }
@Override public A newInstance(Callable<T> factoryMethod) throws Exception { UnitOfWork<?> uow = CurrentUnitOfWork.get(); AtomicReference<A> aggregateReference = new AtomicReference<>(); // a constructor may apply events, and the persistence of an aggregate must take precedence over publishing its events. uow.onPrepareCommit(x -> { A aggregate = aggregateReference.get(); // aggregate construction may have failed with an exception. In that case, no action is required on commit if (aggregate != null) { prepareForCommit(aggregate); } }); A aggregate = doCreateNew(factoryMethod); aggregateReference.set(aggregate); Assert.isTrue(aggregateModel.entityClass().isAssignableFrom(aggregate.rootType()), () -> "Unsuitable aggregate for this repository: wrong type"); Map<String, A> aggregates = managedAggregates(uow); Assert.isTrue(aggregates.putIfAbsent(aggregate.identifierAsString(), aggregate) == null, () -> "The Unit of Work already has an Aggregate with the same identifier"); uow.onRollback(u -> aggregates.remove(aggregate.identifierAsString())); return aggregate; }
/** * Register handlers with the current Unit of Work that save or delete the given {@code aggregate} when * the Unit of Work is committed. * * @param aggregate The Aggregate to save or delete when the Unit of Work is committed */ protected void prepareForCommit(A aggregate) { if (UnitOfWork.Phase.STARTED.isBefore(CurrentUnitOfWork.get().phase())) { doCommit(aggregate); } else { CurrentUnitOfWork.get().onPrepareCommit(u -> { // If the aggregate isn't "managed" anymore, it means its state was invalidated by a rollback doCommit(aggregate); }); } }
@Override protected void validateOnLoad(Aggregate<T> aggregate, Long expectedVersion) { if (expectedVersion != null && expectedVersion < aggregate.version()) { DefaultConflictResolver conflictResolver = new DefaultConflictResolver(eventStore, aggregate.identifierAsString(), expectedVersion, aggregate.version()); ConflictResolution.initialize(conflictResolver); CurrentUnitOfWork.get().onPrepareCommit(uow -> conflictResolver.ensureConflictsResolved()); } else { super.validateOnLoad(aggregate, expectedVersion); } }
unitOfWork.onPrepareCommit(u -> { if (u.parent().isPresent() && !u.parent().get().phase().isAfter(PREPARE_COMMIT)) { eventsQueue(u.parent().get()).addAll(eventQueue);
unitOfWork.onPrepareCommit(uow -> tokenStore.storeToken(unitOfWork.getResource(lastTokenResourceKey), builder.name, unitOfWork.getResource(segmentIdResourceKey)));
/** * Run a given {@code deadlineCall} immediately, or schedule it for the {@link UnitOfWork.Phase#PREPARE_COMMIT} * phase if a UnitOfWork is active. This is required as the DeadlineManager schedule message which we want to happen * on order with other message being handled. * * @param deadlineCall a {@link Runnable} to be executed now or on prepare commit if a {@link UnitOfWork} is active */ protected void runOnPrepareCommitOrNow(Runnable deadlineCall) { if (CurrentUnitOfWork.isStarted()) { CurrentUnitOfWork.get().onPrepareCommit(unitOfWork -> deadlineCall.run()); } else { deadlineCall.run(); } } }
/** * Run a given {@code deadlineCall} immediately, or schedule it for the {@link UnitOfWork} it's 'prepare commit' * phase if a UnitOfWork is active. This is required as the DeadlineManager schedule message which we want to happen * on order with other message being handled. * * @param deadlineCall a {@link Runnable} to be executed now or on prepare commit if a {@link UnitOfWork} is active */ protected void runOnPrepareCommitOrNow(Runnable deadlineCall) { if (CurrentUnitOfWork.isStarted()) { CurrentUnitOfWork.get().onPrepareCommit(unitOfWork -> deadlineCall.run()); } else { deadlineCall.run(); } }
@Override public A newInstance(Callable<T> factoryMethod) throws Exception { UnitOfWork<?> uow = CurrentUnitOfWork.get(); AtomicReference<A> aggregateReference = new AtomicReference<>(); // a constructor may apply events, and the persistence of an aggregate must take precedence over publishing its events. uow.onPrepareCommit(x -> prepareForCommit(aggregateReference.get())); A aggregate = doCreateNew(factoryMethod); aggregateReference.set(aggregate); Assert.isTrue(aggregateModel.entityClass().isAssignableFrom(aggregate.rootType()), () -> "Unsuitable aggregate for this repository: wrong type"); Map<String, A> aggregates = managedAggregates(uow); Assert.isTrue(aggregates.putIfAbsent(aggregate.identifierAsString(), aggregate) == null, () -> "The Unit of Work already has an Aggregate with the same identifier"); uow.onRollback(u -> aggregates.remove(aggregate.identifierAsString())); return aggregate; }
@Override public void eventHandled(EventMessage<?> msg) { if (++counter >= threshold && msg instanceof DomainEventMessage) { if (CurrentUnitOfWork.isStarted()) { CurrentUnitOfWork.get().onPrepareCommit( u -> scheduleSnapshot((DomainEventMessage) msg)); } else { scheduleSnapshot((DomainEventMessage) msg); } counter = 0; } }
@Override public AnnotatedSaga<T> doLoad(String sagaIdentifier) { UnitOfWork<?> unitOfWork = CurrentUnitOfWork.get(); UnitOfWork<?> processRoot = unitOfWork.root(); AnnotatedSaga<T> loadedSaga = managedSagas.computeIfAbsent(sagaIdentifier, id -> { AnnotatedSaga<T> result = doLoadSaga(sagaIdentifier); if (result != null) { processRoot.onCleanup(u -> managedSagas.remove(id)); } return result; }); if (loadedSaga != null && unsavedSagaResource(processRoot).add(sagaIdentifier)) { unitOfWork.onPrepareCommit(u -> { unsavedSagaResource(processRoot).remove(sagaIdentifier); commit(loadedSaga); }); } return loadedSaga; }
@Override public void eventHandled(EventMessage<?> msg) { if (++counter >= threshold && msg instanceof DomainEventMessage) { if (CurrentUnitOfWork.isStarted()) { CurrentUnitOfWork.get().onPrepareCommit( u -> scheduleSnapshot((DomainEventMessage) msg)); } else { scheduleSnapshot((DomainEventMessage) msg); } counter = 0; } }
@Override public A newInstance(Callable<T> factoryMethod) throws Exception { UnitOfWork<?> uow = CurrentUnitOfWork.get(); AtomicReference<A> aggregateReference = new AtomicReference<>(); // a constructor may apply events, and the persistence of an aggregate must take precedence over publishing its events. uow.onPrepareCommit(x -> prepareForCommit(aggregateReference.get())); A aggregate = doCreateNew(factoryMethod); aggregateReference.set(aggregate); Assert.isTrue(aggregateModel.entityClass().isAssignableFrom(aggregate.rootType()), () -> "Unsuitable aggregate for this repository: wrong type"); Map<String, A> aggregates = managedAggregates(uow); Assert.isTrue(aggregates.putIfAbsent(aggregate.identifierAsString(), aggregate) == null, () -> "The Unit of Work already has an Aggregate with the same identifier"); uow.onRollback(u -> aggregates.remove(aggregate.identifierAsString())); return aggregate; }
/** * Register handlers with the current Unit of Work that save or delete the given {@code aggregate} when * the Unit of Work is committed. * * @param aggregate The Aggregate to save or delete when the Unit of Work is committed */ protected void prepareForCommit(A aggregate) { if (UnitOfWork.Phase.STARTED.isBefore(CurrentUnitOfWork.get().phase())) { doCommit(aggregate); } else { CurrentUnitOfWork.get().onPrepareCommit(u -> { // if the aggregate isn't "managed" anymore, it means its state was invalidated by a rollback doCommit(aggregate); }); } }
/** * Register handlers with the current Unit of Work that save or delete the given {@code aggregate} when * the Unit of Work is committed. * * @param aggregate The Aggregate to save or delete when the Unit of Work is committed */ protected void prepareForCommit(A aggregate) { if (UnitOfWork.Phase.STARTED.isBefore(CurrentUnitOfWork.get().phase())) { doCommit(aggregate); } else { CurrentUnitOfWork.get().onPrepareCommit(u -> { // If the aggregate isn't "managed" anymore, it means its state was invalidated by a rollback doCommit(aggregate); }); } }
@Override protected void validateOnLoad(Aggregate<T> aggregate, Long expectedVersion) { if (expectedVersion != null && expectedVersion < aggregate.version()) { DefaultConflictResolver conflictResolver = new DefaultConflictResolver(eventStore, aggregate.identifierAsString(), expectedVersion, aggregate.version()); ConflictResolution.initialize(conflictResolver); CurrentUnitOfWork.get().onPrepareCommit(uow -> conflictResolver.ensureConflictsResolved()); } else { super.validateOnLoad(aggregate, expectedVersion); } }
@Override protected void validateOnLoad(Aggregate<T> aggregate, Long expectedVersion) { if (expectedVersion != null && expectedVersion < aggregate.version()) { DefaultConflictResolver conflictResolver = new DefaultConflictResolver(eventStore, aggregate.identifierAsString(), expectedVersion, aggregate.version()); ConflictResolution.initialize(conflictResolver); CurrentUnitOfWork.get().onPrepareCommit(uow -> conflictResolver.ensureConflictsResolved()); } else { super.validateOnLoad(aggregate, expectedVersion); } }