package io.muoncore.protocol.event.client; import io.muoncore.api.MuonFuture; import io.muoncore.exception.MuonException; import io.muoncore.protocol.event.ClientEvent; import io.muoncore.protocol.event.Event; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; public class AggregateEventClient { private EventClient client; public AggregateEventClient(EventClient client) { this.client = client; } /** * Publish the given events to the provided aggregate event stream * * The ID should be for the aggregate root * * The events will be converted into Muon `Event` types * * stream will be /aggregate/[id] * * type will be the event type class Simple Name - eg co.myapp.UserCreatedEvent -> UserCreatedEvent * * @param id * @param events */ public void publishDomainEvents(String id, List events) { events.forEach(domainEvent -> { ClientEvent persistEvent = ClientEvent .ofType(domainEvent.getClass().getSimpleName()) .payload(domainEvent) .stream("/aggregate/" + id) .build(); EventResult result = client.event(persistEvent); if (result.getStatus() == EventResult.EventResultStatus.FAILED) { throw new MuonException("Failed to persist domain event " + domainEvent + ":" + result.getCause()); } }); } public List<Event> loadAggregateRoot(String id) throws InterruptedException { CountDownLatch latch = new CountDownLatch(1); List<Event> events = new ArrayList<>(); client.replay("/aggregate/" + id, EventReplayMode.REPLAY_ONLY, new Subscriber<Event>() { @Override public void onSubscribe(Subscription s) { s.request(Long.MAX_VALUE); } @Override public void onNext(Event o) { events.add(o); } @Override public void onError(Throwable t) { latch.countDown(); } @Override public void onComplete() { latch.countDown(); } }); latch.await(); return events; } }