是否可以使用usingSubscribingEventProcessors
,并且在投影事件时,请始终从头开始重新投影所有事件。含义-我从不将投影保存到数据库,而是在Aggregate发出新事件时重新投影所有事件?
答案 0 :(得分:1)
当然可以!
但是,您无法通过使用“订阅事件处理器”来实现。
您应该利用跟踪事件处理器,但后面要有InMemoryTokenStore
。这样做,应用程序就永远无法从停止的地方开始,因为TrackingToken
并不存在。
因此,最终每次启动时都会重新创建投影。
您可以采用的另一种方法有些不同。
您仍将使用跟踪事件处理器,但使用实际的持久性TokenStore
实现。其次,在应用程序启动时,您可以使用TrackingEventProcessor#resetTokens()
函数来重播给定的跟踪事件处理器。
采用这种方法,您可以在事件处理组件中添加带有注释的@ResetHandler
函数,以清除投影表之前,以便再次处理所有事件。
希望这会给您Bojan一些见解!
答案 1 :(得分:0)
@Steven,您对此解决方案有何看法?
public class ReplayingSubscribingEventProcessor extends SubscribingEventProcessor {
private final SubscribableMessageSource<? extends EventMessage<?>> messageSource;
protected ReplayingSubscribingEventProcessor(
Builder builder) {
super(builder);
this.messageSource = builder.messageSource;
}
public static Builder builder() {
return new Builder();
}
/**
* Whenever there is a need to process event messages, ignore all of them and since already inside messageSource,
* just take all messages from event source and re-project all from beginning for this aggregate root
* @param eventMessages
*/
@Override
protected void process(List<? extends EventMessage<?>> eventMessages) {
try {
//reprocess all previous events for this aggregate (get id from current event)
GenericDomainEventMessage gdem = (GenericDomainEventMessage) eventMessages.get(0);
List<? extends EventMessage<?>> prevEvs = ((EventStore)messageSource).readEvents(gdem.getAggregateIdentifier()).asStream()
.collect(Collectors.toList());
processInUnitOfWork(prevEvs, new BatchingUnitOfWork<>(prevEvs), Segment.ROOT_SEGMENT);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new EventProcessingException("Exception occurred while processing events", e);
}
}
public static class Builder extends SubscribingEventProcessor.Builder{
private SubscribableMessageSource<? extends EventMessage<?>> messageSource;
@Override
public Builder messageSource(
SubscribableMessageSource<? extends EventMessage<?>> messageSource) {
super.messageSource(messageSource);
this.messageSource = messageSource;
return this;
}
@Override
public ReplayingSubscribingEventProcessor.Builder name(String name) {
super.name(name);
return this;
}
@Override
public ReplayingSubscribingEventProcessor.Builder eventHandlerInvoker(
EventHandlerInvoker eventHandlerInvoker) {
super.eventHandlerInvoker(eventHandlerInvoker);
return this;
}
@Override
public ReplayingSubscribingEventProcessor.Builder processingStrategy(
EventProcessingStrategy processingStrategy) {
super.processingStrategy(processingStrategy);
return this;
}
public ReplayingSubscribingEventProcessor build() {
return new ReplayingSubscribingEventProcessor(this);
}
}
}
和配置:
@Autowired
public void configure(EventProcessingConfigurer configurer){
configurer.registerEventProcessor("inMemoryProcessor",
(n, c, ehi) -> replayingSubscribingEventProcessor(n, c, ehi, org.axonframework.config.Configuration::eventBus));
}
public ReplayingSubscribingEventProcessor replayingSubscribingEventProcessor(
String name,
org.axonframework.config.Configuration conf,
EventHandlerInvoker eventHandlerInvoker,
Function<org.axonframework.config.Configuration, SubscribableMessageSource<? extends EventMessage<?>>> messageSource) {
return ReplayingSubscribingEventProcessor.builder()
.name(name)
.eventHandlerInvoker(eventHandlerInvoker)
.messageSource(messageSource.apply(conf))
.processingStrategy(DirectEventProcessingStrategy.INSTANCE)
.build();
}