public static EventWithMetadata toEventWithMetadata(EventIdTypeAndData eventIdTypeAndData) { Optional<String> metadata = eventIdTypeAndData.getMetadata(); return new EventWithMetadata(toEvent(eventIdTypeAndData), eventIdTypeAndData.getId(), metadata == null ? Optional.empty() : metadata.map(md -> JSonMapper.fromJson(md, Map.class))); }
public static EventWithMetadata toEventWithMetadata(EventIdTypeAndData eventIdTypeAndData) { Optional<String> metadata = eventIdTypeAndData.getMetadata(); return new EventWithMetadata(toEvent(eventIdTypeAndData), eventIdTypeAndData.getId(), metadata == null ? Optional.empty() : metadata.map(md -> JSonMapper.fromJson(md, Map.class))); }
@Override @Transactional public SaveUpdateResult save(String aggregateType, List<EventTypeAndData> events, Optional<AggregateCrudSaveOptions> saveOptions) { List<EventIdTypeAndData> eventsWithIds = events.stream().map(this::toEventWithId).collect(Collectors.toList()); String entityId = saveOptions.flatMap(AggregateCrudSaveOptions::getEntityId).orElse(idGenerator.genId().asString()); Int128 entityVersion = last(eventsWithIds).getId(); try { jdbcTemplate.update(String.format("INSERT INTO %s (entity_type, entity_id, entity_version) VALUES (?, ?, ?)", entityTable), aggregateType, entityId, entityVersion.asString()); } catch (DuplicateKeyException e) { throw new EntityAlreadyExistsException(); } for (EventIdTypeAndData event : eventsWithIds) jdbcTemplate.update(String.format("INSERT INTO %s (event_id, event_type, event_data, entity_type, entity_id, triggering_event, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)", eventTable), event.getId().asString(), event.getEventType(), event.getEventData(), aggregateType, entityId, saveOptions.flatMap(AggregateCrudSaveOptions::getTriggeringEvent).map(EventContext::getEventToken).orElse(null), event.getMetadata().orElse(null) ); return new SaveUpdateResult(new EntityIdVersionAndEventIds(entityId, entityVersion, eventsWithIds.stream().map(EventIdTypeAndData::getId).collect(Collectors.toList())), new PublishableEvents(aggregateType, entityId, eventsWithIds)); }
@Override public <T extends Aggregate<T>> EntityWithMetadata<T> find(Class<T> clasz, String entityId, Optional<FindOptions> findOptions) { try { LoadedEvents le = aggregateCrud.find(clasz.getName(), entityId, toAggregateCrudFindOptions(findOptions)); if (activityLogger.isDebugEnabled()) activityLogger.debug("Loaded entity: {} {} {}", clasz.getName(), entityId, le.getEvents()); List<EventWithMetadata> eventsWithIds = le.getEvents().stream().map(AggregateCrudMapping::toEventWithMetadata).collect(Collectors.toList()); List<Event> events = eventsWithIds.stream().map(EventWithMetadata::getEvent).collect(Collectors.toList()); return new EntityWithMetadata<T>( new EntityIdAndVersion(entityId, le.getEvents().isEmpty() ? le.getSnapshot().get().getEntityVersion() : le.getEvents().get(le.getEvents().size() - 1).getId()), le.getSnapshot().map(SerializedSnapshotWithVersion::getEntityVersion), eventsWithIds, le.getSnapshot().map(ss -> Aggregates.applyEventsToMutableAggregate((T) snapshotManager.recreateFromSnapshot(clasz, AggregateCrudMapping.toSnapshot(ss.getSerializedSnapshot()), missingApplyEventMethodStrategy), events, missingApplyEventMethodStrategy)) .orElseGet(() -> Aggregates.recreateAggregate(clasz, events, missingApplyEventMethodStrategy))); } catch (RuntimeException e) { if (activityLogger.isDebugEnabled()) activityLogger.trace(String.format("Find entity failed: %s %s", clasz.getName(), entityId), e); throw e; } }
@Override public <T extends Aggregate<T>> CompletableFuture<EntityWithMetadata<T>> find(Class<T> clasz, String entityId, Optional<FindOptions> findOptions) { CompletableFuture<LoadedEvents> outcome = aggregateCrud.find(clasz.getName(), entityId, AggregateCrudMapping.toAggregateCrudFindOptions(findOptions)); CompletableFuture<LoadedEvents> tappedOutcome; if (activityLogger.isDebugEnabled()) tappedOutcome = CompletableFutureUtil.tap(outcome, (result, throwable) -> { if (throwable == null) activityLogger.debug("Loaded entity: {} {} {}", clasz.getName(), entityId, result.getEvents()); else { if (throwable instanceof EventuateException) activityLogger.trace(String.format("Find entity failed: %s %s %s", clasz.getName(), entityId, throwable.getClass().getName())); else activityLogger.trace(String.format("Find entity failed: %s %s", clasz.getName(), entityId), throwable); } }); else tappedOutcome = outcome; return tappedOutcome.thenApply(le -> { List<EventWithMetadata> eventsWithIds = eventSchemaMetadataManager.upcastEvents(clasz, le.getEvents()).stream().map(AggregateCrudMapping::toEventWithMetadata).collect(Collectors.toList()); List<Event> events = eventsWithIds.stream().map(EventWithMetadata::getEvent).collect(Collectors.toList()); return new EntityWithMetadata<T>( new EntityIdAndVersion(entityId, le.getEvents().isEmpty() ? le.getSnapshot().get().getEntityVersion() : le.getEvents().get(le.getEvents().size() - 1).getId()), le.getSnapshot().map(SerializedSnapshotWithVersion::getEntityVersion), eventsWithIds, le.getSnapshot().map(ss -> Aggregates.applyEventsToMutableAggregate((T) snapshotManager.recreateFromSnapshot(clasz, AggregateCrudMapping.toSnapshot(ss.getSerializedSnapshot()), missingApplyEventMethodStrategy), events, missingApplyEventMethodStrategy)) .orElseGet(() -> Aggregates.recreateAggregate(clasz, events, missingApplyEventMethodStrategy))); }); }
@Override public <T extends Aggregate<T>> EntityWithMetadata<T> find(Class<T> clasz, String entityId, Optional<FindOptions> findOptions) { try { LoadedEvents le = aggregateCrud.find(clasz.getName(), entityId, toAggregateCrudFindOptions(findOptions)); if (activityLogger.isDebugEnabled()) activityLogger.debug("Loaded entity: {} {} {}", clasz.getName(), entityId, le.getEvents()); List<EventWithMetadata> eventsWithIds = le.getEvents().stream().map(AggregateCrudMapping::toEventWithMetadata).collect(Collectors.toList()); List<Event> events = eventsWithIds.stream().map(EventWithMetadata::getEvent).collect(Collectors.toList()); return new EntityWithMetadata<T>( new EntityIdAndVersion(entityId, le.getEvents().isEmpty() ? le.getSnapshot().get().getEntityVersion() : le.getEvents().get(le.getEvents().size() - 1).getId()), le.getSnapshot().map(SerializedSnapshotWithVersion::getEntityVersion), eventsWithIds, le.getSnapshot().map(ss -> Aggregates.applyEventsToMutableAggregate((T) snapshotManager.recreateFromSnapshot(clasz, AggregateCrudMapping.toSnapshot(ss.getSerializedSnapshot()), missingApplyEventMethodStrategy), events, missingApplyEventMethodStrategy)) .orElseGet(() -> Aggregates.recreateAggregate(clasz, events, missingApplyEventMethodStrategy))); } catch (RuntimeException e) { if (activityLogger.isDebugEnabled()) activityLogger.trace(String.format("Find entity failed: %s %s", clasz.getName(), entityId), e); throw e; } }
@Override public <T extends Aggregate<T>> CompletableFuture<EntityWithMetadata<T>> find(Class<T> clasz, String entityId, Optional<FindOptions> findOptions) { CompletableFuture<LoadedEvents> outcome = aggregateCrud.find(clasz.getName(), entityId, AggregateCrudMapping.toAggregateCrudFindOptions(findOptions)); CompletableFuture<LoadedEvents> tappedOutcome; if (activityLogger.isDebugEnabled()) tappedOutcome = CompletableFutureUtil.tap(outcome, (result, throwable) -> { if (throwable == null) activityLogger.debug("Loaded entity: {} {} {}", clasz.getName(), entityId, result.getEvents()); else { if (throwable instanceof EventuateException) activityLogger.trace(String.format("Find entity failed: %s %s %s", clasz.getName(), entityId, throwable.getClass().getName())); else activityLogger.trace(String.format("Find entity failed: %s %s", clasz.getName(), entityId), throwable); } }); else tappedOutcome = outcome; return tappedOutcome.thenApply(le -> { List<EventWithMetadata> eventsWithIds = eventSchemaMetadataManager.upcastEvents(clasz, le.getEvents()).stream().map(AggregateCrudMapping::toEventWithMetadata).collect(Collectors.toList()); List<Event> events = eventsWithIds.stream().map(EventWithMetadata::getEvent).collect(Collectors.toList()); return new EntityWithMetadata<T>( new EntityIdAndVersion(entityId, le.getEvents().isEmpty() ? le.getSnapshot().get().getEntityVersion() : le.getEvents().get(le.getEvents().size() - 1).getId()), le.getSnapshot().map(SerializedSnapshotWithVersion::getEntityVersion), eventsWithIds, le.getSnapshot().map(ss -> Aggregates.applyEventsToMutableAggregate((T) snapshotManager.recreateFromSnapshot(clasz, AggregateCrudMapping.toSnapshot(ss.getSerializedSnapshot()), missingApplyEventMethodStrategy), events, missingApplyEventMethodStrategy)) .orElseGet(() -> Aggregates.recreateAggregate(clasz, events, missingApplyEventMethodStrategy))); }); }
@Override protected void publish(PublishableEvents publishableEvents) { String aggregateType = publishableEvents.getAggregateType(); String aggregateId = publishableEvents.getEntityId(); List<EventIdTypeAndData> eventsWithIds = publishableEvents.getEventsWithIds(); List<Subscription> subscriptions; synchronized (aggregateTypeToSubscription) { List<Subscription> x = aggregateTypeToSubscription.get(aggregateType); subscriptions = x == null ? null : new ArrayList<>(x); } if (subscriptions != null) for (Subscription subscription : subscriptions) { for (EventIdTypeAndData event : eventsWithIds) { if (subscription.isInterestedIn(aggregateType, event.getEventType())) subscription.handler.apply(new SerializedEvent(event.getId(), aggregateId, aggregateType, event.getEventData(), event.getEventType(), aggregateId.hashCode() % 8, eventOffset.getAndIncrement(), new EventContext(event.getId().asString()), event.getMetadata())); } } }
@Override protected void publish(PublishableEvents publishableEvents) { String aggregateType = publishableEvents.getAggregateType(); String aggregateId = publishableEvents.getEntityId(); List<EventIdTypeAndData> eventsWithIds = publishableEvents.getEventsWithIds(); List<Subscription> subscriptions; synchronized (aggregateTypeToSubscription) { List<Subscription> x = aggregateTypeToSubscription.get(aggregateType); subscriptions = x == null ? null : new ArrayList<>(x); } if (subscriptions != null) for (Subscription subscription : subscriptions) { for (EventIdTypeAndData event : eventsWithIds) { if (subscription.isInterestedIn(aggregateType, event.getEventType())) subscription.handler.apply(new SerializedEvent(event.getId(), aggregateId, aggregateType, event.getEventData(), event.getEventType(), aggregateId.hashCode() % 8, eventOffset.getAndIncrement(), new EventContext(event.getId().asString()), event.getMetadata())); } } }