andreschaffer/event-sourcing-cqrs-examples

View on GitHub
src/main/java/bankservice/service/client/ClientService.java

Summary

Maintainability
A
1 hr
Test Coverage
A
100%
package bankservice.service.client;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.Collections.singletonList;
import static java.util.UUID.randomUUID;

import bankservice.domain.model.Event;
import bankservice.domain.model.EventStore;
import bankservice.domain.model.OptimisticLockingException;
import bankservice.domain.model.client.Client;
import bankservice.service.Retrier;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Consumer;

public class ClientService {

  private final EventStore eventStore;
  private final Retrier conflictRetrier;

  public ClientService(EventStore eventStore) {
    this.eventStore = checkNotNull(eventStore);
    int maxAttempts = 3;
    this.conflictRetrier = new Retrier(singletonList(OptimisticLockingException.class),
        maxAttempts);
  }

  public Optional<Client> loadClient(UUID id) {
    List<Event> eventStream = eventStore.load(id);
    if (eventStream.isEmpty()) {
      return Optional.empty();
    }
    return Optional.of(new Client(id, eventStream));
  }

  public Client process(EnrollClientCommand command) {
    Client client = new Client(randomUUID(), command.getName(), command.getEmail());
    storeEvents(client);
    return client;
  }

  public void process(UpdateClientCommand command) {
    process(command.getId(), c -> c.update(command.getName(), command.getEmail()));
  }

  private Client process(UUID clientId, Consumer<Client> consumer)
      throws ClientNotFoundException, OptimisticLockingException {

    return conflictRetrier.get(() -> {
      Optional<Client> possibleClient = loadClient(clientId);
      Client client = possibleClient.orElseThrow(() -> new ClientNotFoundException(clientId));
      consumer.accept(client);
      storeEvents(client);
      return client;
    });
  }

  private void storeEvents(Client client) {
    eventStore.store(client.getId(), client.getNewEvents(), client.getBaseVersion());
  }
}