@Override public <T extends Aggregate<T>> EntityIdAndVersion save(Class<T> clasz, List<Event> events, Optional<SaveOptions> saveOptions) { Optional<String> serializedMetadata = saveOptions.flatMap(SaveOptions::getEventMetadata).map(JSonMapper::toJson); List<EventTypeAndData> serializedEvents = events.stream().map(event -> toEventTypeAndData(event, serializedMetadata)).collect(Collectors.toList()); try { EntityIdVersionAndEventIds result = aggregateCrud.save(clasz.getName(), serializedEvents, toAggregateCrudSaveOptions(saveOptions)); if (activityLogger.isDebugEnabled()) activityLogger.debug("Saved entity: {} {} {}", clasz.getName(), result.getEntityId(), toSerializedEventsWithIds(serializedEvents, result.getEventIds())); return result.toEntityIdAndVersion(); } catch (RuntimeException e) { activityLogger.error(String.format("Save entity failed: %s", clasz.getName()), e); throw e; } }
@Override public <T extends Aggregate<T>> EntityIdAndVersion save(Class<T> clasz, List<Event> events, Optional<SaveOptions> saveOptions) { Optional<String> serializedMetadata = saveOptions.flatMap(SaveOptions::getEventMetadata).map(JSonMapper::toJson); List<EventTypeAndData> serializedEvents = events.stream().map(event -> toEventTypeAndData(event, serializedMetadata)).collect(Collectors.toList()); try { EntityIdVersionAndEventIds result = aggregateCrud.save(clasz.getName(), serializedEvents, toAggregateCrudSaveOptions(saveOptions)); if (activityLogger.isDebugEnabled()) activityLogger.debug("Saved entity: {} {} {}", clasz.getName(), result.getEntityId(), toSerializedEventsWithIds(serializedEvents, result.getEventIds())); return result.toEntityIdAndVersion(); } catch (RuntimeException e) { activityLogger.error(String.format("Save entity failed: %s", clasz.getName()), e); throw e; } }
@Override public <T extends Aggregate<T>> CompletableFuture<EntityIdAndVersion> save(Class<T> clasz, List<Event> events, Optional<SaveOptions> saveOptions) { Optional<String> serializedMetadata = saveOptions.flatMap(so -> withSchemaMetadata(clasz, so.getEventMetadata())).map(JSonMapper::toJson); List<EventTypeAndData> serializedEvents = events.stream().map(event -> toEventTypeAndData(event, serializedMetadata)).collect(Collectors.toList()); CompletableFuture<EntityIdVersionAndEventIds> outcome = aggregateCrud.save(clasz.getName(), serializedEvents, AggregateCrudMapping.toAggregateCrudSaveOptions(saveOptions)); if (activityLogger.isDebugEnabled()) return CompletableFutureUtil.tap(outcome, (result, throwable) -> { if (throwable == null) activityLogger.debug("Saved entity: {} {} {}", clasz.getName(), result.getEntityId(), AggregateCrudMapping.toSerializedEventsWithIds(serializedEvents, result.getEventIds())); else activityLogger.error(String.format("Save entity failed: %s", clasz.getName()), throwable); }).thenApply(EntityIdVersionAndEventIds::toEntityIdAndVersion); else return outcome.thenApply(EntityIdVersionAndEventIds::toEntityIdAndVersion); }
@Override public <T extends Aggregate<T>> CompletableFuture<EntityIdAndVersion> save(Class<T> clasz, List<Event> events, Optional<SaveOptions> saveOptions) { Optional<String> serializedMetadata = saveOptions.flatMap(so -> withSchemaMetadata(clasz, so.getEventMetadata())).map(JSonMapper::toJson); List<EventTypeAndData> serializedEvents = events.stream().map(event -> toEventTypeAndData(event, serializedMetadata)).collect(Collectors.toList()); CompletableFuture<EntityIdVersionAndEventIds> outcome = aggregateCrud.save(clasz.getName(), serializedEvents, AggregateCrudMapping.toAggregateCrudSaveOptions(saveOptions)); if (activityLogger.isDebugEnabled()) return CompletableFutureUtil.tap(outcome, (result, throwable) -> { if (throwable == null) activityLogger.debug("Saved entity: {} {} {}", clasz.getName(), result.getEntityId(), AggregateCrudMapping.toSerializedEventsWithIds(serializedEvents, result.getEventIds())); else activityLogger.error(String.format("Save entity failed: %s", clasz.getName()), throwable); }).thenApply(EntityIdVersionAndEventIds::toEntityIdAndVersion); else return outcome.thenApply(EntityIdVersionAndEventIds::toEntityIdAndVersion); }
@Override public <T extends Aggregate<T>> EntityIdAndVersion update(Class<T> clasz, EntityIdAndVersion entityIdAndVersion, List<Event> events, Optional<UpdateOptions> updateOptions) { try { Optional<String> serializedEventMetadata = updateOptions.flatMap(UpdateOptions::getEventMetadata).map(JSonMapper::toJson); List<EventTypeAndData> serializedEvents = events.stream().map(event -> toEventTypeAndData(event, serializedEventMetadata)).collect(Collectors.toList()); EntityIdVersionAndEventIds result = aggregateCrud.update(new EntityIdAndType(entityIdAndVersion.getEntityId(), clasz.getName()), entityIdAndVersion.getEntityVersion(), serializedEvents, toAggregateCrudUpdateOptions(updateOptions)); if (activityLogger.isDebugEnabled()) activityLogger.debug("Updated entity: {} {} {}", clasz.getName(), result.getEntityId(), toSerializedEventsWithIds(serializedEvents, result.getEventIds())); return result.toEntityIdAndVersion(); } catch (RuntimeException e) { if (activityLogger.isDebugEnabled()) activityLogger.error(String.format("Update entity failed: %s %s", clasz.getName(), entityIdAndVersion), e); throw e; } }
@Override public <T extends Aggregate<T>> CompletableFuture<EntityIdAndVersion> update(Class<T> clasz, EntityIdAndVersion entityIdAndVersion, List<Event> events, Optional<UpdateOptions> updateOptions) { Optional<String> serializedMetadata = updateOptions.flatMap(UpdateOptions::getEventMetadata).map(JSonMapper::toJson); List<EventTypeAndData> serializedEvents = events.stream().map(event -> toEventTypeAndData(event, serializedMetadata)).collect(Collectors.toList()); CompletableFuture<EntityIdVersionAndEventIds> outcome = aggregateCrud.update(new EntityIdAndType(entityIdAndVersion.getEntityId(), clasz.getName()), entityIdAndVersion.getEntityVersion(), serializedEvents, AggregateCrudMapping.toAggregateCrudUpdateOptions(updateOptions)); if (activityLogger.isDebugEnabled()) return CompletableFutureUtil.tap(outcome, (result, throwable) -> { if (throwable == null) activityLogger.debug("Updated entity: {} {} {}", clasz.getName(), result.getEntityId(), AggregateCrudMapping.toSerializedEventsWithIds(serializedEvents, result.getEventIds())); else activityLogger.error(String.format("Update entity failed: %s %s", clasz.getName(), entityIdAndVersion), throwable); }).thenApply(EntityIdVersionAndEventIds::toEntityIdAndVersion); else return outcome.thenApply(EntityIdVersionAndEventIds::toEntityIdAndVersion); }
@Override public <T extends Aggregate<T>> CompletableFuture<EntityIdAndVersion> update(Class<T> clasz, EntityIdAndVersion entityIdAndVersion, List<Event> events, Optional<UpdateOptions> updateOptions) { Optional<String> serializedMetadata = updateOptions.flatMap(UpdateOptions::getEventMetadata).map(JSonMapper::toJson); List<EventTypeAndData> serializedEvents = events.stream().map(event -> toEventTypeAndData(event, serializedMetadata)).collect(Collectors.toList()); CompletableFuture<EntityIdVersionAndEventIds> outcome = aggregateCrud.update(new EntityIdAndType(entityIdAndVersion.getEntityId(), clasz.getName()), entityIdAndVersion.getEntityVersion(), serializedEvents, AggregateCrudMapping.toAggregateCrudUpdateOptions(updateOptions)); if (activityLogger.isDebugEnabled()) return CompletableFutureUtil.tap(outcome, (result, throwable) -> { if (throwable == null) activityLogger.debug("Updated entity: {} {} {}", clasz.getName(), result.getEntityId(), AggregateCrudMapping.toSerializedEventsWithIds(serializedEvents, result.getEventIds())); else activityLogger.error(String.format("Update entity failed: %s %s", clasz.getName(), entityIdAndVersion), throwable); }).thenApply(EntityIdVersionAndEventIds::toEntityIdAndVersion); else return outcome.thenApply(EntityIdVersionAndEventIds::toEntityIdAndVersion); }
@Override public <T extends Aggregate<T>> EntityIdAndVersion update(Class<T> clasz, EntityIdAndVersion entityIdAndVersion, List<Event> events, Optional<UpdateOptions> updateOptions) { try { Optional<String> serializedEventMetadata = updateOptions.flatMap(UpdateOptions::getEventMetadata).map(JSonMapper::toJson); List<EventTypeAndData> serializedEvents = events.stream().map(event -> toEventTypeAndData(event, serializedEventMetadata)).collect(Collectors.toList()); EntityIdVersionAndEventIds result = aggregateCrud.update(new EntityIdAndType(entityIdAndVersion.getEntityId(), clasz.getName()), entityIdAndVersion.getEntityVersion(), serializedEvents, toAggregateCrudUpdateOptions(updateOptions)); if (activityLogger.isDebugEnabled()) activityLogger.debug("Updated entity: {} {} {}", clasz.getName(), result.getEntityId(), toSerializedEventsWithIds(serializedEvents, result.getEventIds())); return result.toEntityIdAndVersion(); } catch (RuntimeException e) { if (activityLogger.isDebugEnabled()) activityLogger.error(String.format("Update entity failed: %s %s", clasz.getName(), entityIdAndVersion), e); throw e; } }
@Test public void shouldReadNewEventsOnly() throws InterruptedException { BlockingQueue<PublishedEvent> publishedEvents = new LinkedBlockingDeque<>(); CdcProcessor<PublishedEvent> cdcProcessor = createCdcProcessor(); cdcProcessor.start(publishedEvent -> { publishedEvents.add(publishedEvent); onEventSent(publishedEvent); }); String accountCreatedEventData = generateAccountCreatedEvent(); EntityIdVersionAndEventIds entityIdVersionAndEventIds = saveEvent(accountCreatedEventData); waitForEvent(publishedEvents, entityIdVersionAndEventIds.getEntityVersion(), LocalDateTime.now().plusSeconds(10), accountCreatedEventData); cdcProcessor.stop(); publishedEvents.clear(); cdcProcessor.start(publishedEvent -> { publishedEvents.add(publishedEvent); onEventSent(publishedEvent); }); List<String> excludedIds = entityIdVersionAndEventIds.getEventIds().stream().map(Int128::asString).collect(Collectors.toList()); accountCreatedEventData = generateAccountCreatedEvent(); entityIdVersionAndEventIds = updateEvent(entityIdVersionAndEventIds.getEntityId(), entityIdVersionAndEventIds.getEntityVersion(), accountCreatedEventData); waitForEventExcluding(publishedEvents, entityIdVersionAndEventIds.getEntityVersion(), LocalDateTime.now().plusSeconds(10), accountCreatedEventData, excludedIds); cdcProcessor.stop(); }
@Test public void shouldSaveAndLoadEventMetadata() throws InterruptedException { String saveMetadata = "MyMetaData"; String updateMetadata = "MyMetaDataForUpdate"; LinkedBlockingQueue<SerializedEvent> events = new LinkedBlockingQueue<>(); aggregateEvents.subscribe("shouldSaveAndLoadEventMetadata", singletonMap(aggregateType, singleton("MyEventType")), new SubscriberOptions(), se -> { events.add(se); return new CompletableFuture<Object>(); }); EntityIdVersionAndEventIds eidv = eventStore.save(aggregateType, singletonList(new EventTypeAndData("MyEventType", "{}", Optional.of(saveMetadata))), Optional.empty()); LoadedEvents findResult = eventStore.find(aggregateType, eidv.getEntityId(), Optional.of(new AggregateCrudFindOptions())); assertEquals(Optional.of(saveMetadata), findResult.getEvents().get(0).getMetadata()); EntityIdVersionAndEventIds updateResult = eventStore.update( new EntityIdAndType(eidv.getEntityId(), aggregateType), eidv.getEntityVersion(), singletonList(new EventTypeAndData("MyEventType", "{}", Optional.of(updateMetadata))), Optional.empty()); LoadedEvents findResult2 = eventStore.find(aggregateType, eidv.getEntityId(), Optional.of(new AggregateCrudFindOptions())); assertEquals(Optional.of(saveMetadata), findResult2.getEvents().get(0).getMetadata()); assertEquals(Optional.of(updateMetadata), findResult2.getEvents().get(1).getMetadata()); assertContainsEventWithMetadata(eidv.getEventIds().get(0), saveMetadata, events); assertContainsEventWithMetadata(updateResult.getEventIds().get(0), updateMetadata, events); }
if (event.getId().equals(eventId.asString()) && eventData.equals(event.getEventData())) { foundEvent = true; } else if (event.getId().equals(otherSaveResult.getEntityIdVersionAndEventIds().getEventIds().get(0).asString())) { fail("Found event inserted into other schema");