/** * Creates an update operation, optionally requiring an existing aggregate. * * @param handler The handler to invoke with the current state to apply updates. * @param autoCreate If true, the handler will be invoked with a null state in the case where no * current aggregate exists. If false, the command will fail without the * handler being invoked if the aggregate is not already present. * @return An operation representing the supplied logic, with metadata. */ public static <TState, TParams, TEvent> Operation<TState, TParams, TEvent> updateOf( final ParameterizedUpdateHandlerAggregate<TState, TParams, TEvent> handler, final boolean autoCreate) { ExpectedVersion expectedVersion = autoCreate ? ExpectedVersion.any() : ExpectedVersion.anyExisting(); return new OperationHandlerOperation<>( handler, true, true, expectedVersion, true); }
private eventstore.ExpectedVersion toEsVersion(final ExpectedVersion version) { if (version == null) { return new eventstore.ExpectedVersion.Any$(); } else { switch (version.getType()) { case ANY: return new eventstore.ExpectedVersion.Any$(); case EXACTLY: return new eventstore.ExpectedVersion.Exact(version.getExpectedVersion()); case NOT_CREATED: return new eventstore.ExpectedVersion.NoStream$(); default: throw new IllegalArgumentException( "Unrecognized expected version type: " + version); } } }
public static <TEvent> Operation<Object, Object, TEvent> constructorOf( final ConstructorHandler<TEvent> handler) { return new OperationHandlerOperation<>(handler, false, false, ExpectedVersion.notCreated()); }
public static ExpectedVersion merge( final ExpectedVersion baseVersion, final ExpectedVersion newVersion) { if (baseVersion != null && newVersion != null) { if (baseVersion.getType().compareTo(newVersion.getType()) > 0) { return mergeOrdered(newVersion, baseVersion); } else { return mergeOrdered(baseVersion, newVersion); } } else if (baseVersion != null) { return baseVersion; } else if (newVersion != null) { return newVersion; } else { return ExpectedVersion.any(); } }
updateExpectedVersion = ExpectedVersion.exactly(aggregate.sourceVersion()); } else { updateExpectedVersion = ExpectedVersion.notCreated(); updateExpectedVersion = ExpectedVersion.notCreated(); } else { updateExpectedVersion = ExpectedVersion.any(); if (updateExpectedVersion.getType() == ExpectedVersionType.ANY_EXISTING) { updateExpectedVersion = ExpectedVersion.any();
public OperationHandlerOperation( final OperationHandler<TState, TParams, TEvent> handler, final boolean requiresState, final boolean requiresArguments, final ExpectedVersion expectedVersion) { this(handler, requiresState, requiresArguments, expectedVersion, false); }
final ExpectedVersion baseVersion, final ExpectedVersion newVersion) { switch (baseVersion.getType()) { case ANY: switch (newVersion.getType()) { case ANY_EXISTING: return ExpectedVersion.anyExisting(); case EXACTLY: return newVersion; switch (newVersion.getType()) { case EXACTLY: if (baseVersion.getExpectedVersion() != newVersion.getExpectedVersion()) { throw new ConflictingExpectedVersionsException( "Cannot merge 'exactly " + baseVersion.getExpectedVersion() + "' with 'exactly " + newVersion.getExpectedVersion() + "'", baseVersion, newVersion); throw new ConflictingExpectedVersionsException( "Cannot merge 'exactly " + baseVersion.getExpectedVersion() + "' with 'not created'", baseVersion, newVersion);
@Override public ImmutableAggregate<TState, TEvent> save( @NotNull final Aggregate<TState, TEvent> aggregate, final boolean atomic, final Map<String, String> metadata) { Preconditions.checkNotNull(aggregate); ExpectedVersion expectedVersion; if (atomic) { if (aggregate.sourceVersion() == Aggregate.VERSION_NOT_CREATED) { expectedVersion = ExpectedVersion.notCreated(); } else { expectedVersion = ExpectedVersion.exactly(aggregate.sourceVersion()); } } else { expectedVersion = ExpectedVersion.any(); } int newVersion = append( aggregate.id(), aggregate.events(), expectedVersion, metadata); return DefaultImmutableAggregate.fromExisting( projection, aggregate.id(), newVersion, aggregate.state()); }
@Test public void mergeAnyAndNotCreated() { assertMerge(any(), notCreated(), notCreated()); }
@Test public void mergeAnyExistingAndExactly() { assertMerge(anyExisting(), exactly(3), exactly(3)); }
@Test public void mergeExactlyAndNotCreated() { assertMergeFail(exactly(3), notCreated()); }
@Test(expected = InvalidCommandException.class) @SuppressWarnings("unchecked") public void conflictingVersionsGiveInvalidCommand() { PowerMockito.mockStatic(ExpectedVersion.class); PowerMockito.when(ExpectedVersion.merge(any(), any())) .thenThrow(new ConflictingExpectedVersionsException( "error", null, null)); Operation operation = new OperationHandlerOperation( (x, y) -> null, true, false, ExpectedVersion.exactly(42)); DefaultCommand command = new DefaultCommand(repository, operation); command.setAggregateId(AGGREGATE_ID); command.run(); }
@Test public void mergeAnyExistingAndNotCreated() { assertMergeFail(anyExisting(), notCreated()); }
private static ExpectedVersion getEffectiveExpectedVersion( final ExpectedVersion commandExpectedVersion, final ExpectedVersion operationExpectedVersion) { try { return ExpectedVersion.merge(commandExpectedVersion, operationExpectedVersion); } catch (ConflictingExpectedVersionsException ex) { throw new InvalidCommandException( "Conflicting expected version constraints: " + ex.getMessage(), ex); } }
public static ExpectedVersion notCreated() { return new ExpectedVersion( ExpectedVersionType.NOT_CREATED, Aggregate.VERSION_NOT_CREATED); }
@Test public void mergeAnyExistingAndAnyExisting() { assertMerge(anyExisting(), anyExisting(), anyExisting()); }
updateExpectedVersion = ExpectedVersion.exactly(aggregate.sourceVersion()); } else { updateExpectedVersion = ExpectedVersion.notCreated(); updateExpectedVersion = ExpectedVersion.notCreated(); } else { updateExpectedVersion = ExpectedVersion.any(); if (updateExpectedVersion.getType() == ExpectedVersionType.ANY_EXISTING) { updateExpectedVersion = ExpectedVersion.any();
public OperationHandlerOperation( final OperationHandler<TState, TParams, TEvent> handler, final boolean requiresState, final boolean requiresArguments, final ExpectedVersion expectedVersion) { this(handler, requiresState, requiresArguments, expectedVersion, false); }