Java 轴突-始终重新投影所有事件

Java 轴突-始终重新投影所有事件,java,axon,Java,Axon,是否可以使用SubscriptingEventProcessors使用,并且在投影事件时,始终从一开始就重新投影所有事件。意思是-我从不将投影保存到DB,但只要聚合中发出新事件,就重新投影所有事件?当然这是可能的! 但是,使用订阅事件处理器无法实现这一点。 您应该利用跟踪事件处理器,但在其后面有一个InMemoryTokenStore。这样,应用程序就永远不能从它停止的地方开始,因为它停止的地方的知识,TrackingToken,并不存在 因此,每次启动时都会重新创建投影 您可以采取的另一种方法

是否可以使用SubscriptingEventProcessors使用
,并且在投影事件时,始终从一开始就重新投影所有事件。意思是-我从不将投影保存到DB,但只要聚合中发出新事件,就重新投影所有事件?

当然这是可能的! 但是,使用订阅事件处理器无法实现这一点。 您应该利用跟踪事件处理器,但在其后面有一个
InMemoryTokenStore
。这样,应用程序就永远不能从它停止的地方开始,因为它停止的地方的知识,
TrackingToken
,并不存在

因此,每次启动时都会重新创建投影

您可以采取的另一种方法有点不同。 您仍然可以使用跟踪事件处理器,但需要实际的持久化
TokenStore
实现。其次,在应用程序启动时,您可以使用
TrackingEventProcessor#resetTokens()
函数发布给定跟踪事件处理器的重播

采用这种方法,您可以在事件处理组件中添加带注释的函数
@ResetHandler
,以便在再次处理所有事件之前清除投影表


希望这能给你一些见解博扬

@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);
    }
  }
}
公共类ReplayingSubscribingEventProcessor扩展SubscribingEventProcessor{
private final SubscribableMessageSource>messageSource;
受保护的ReplayingSubscribingEventProcessor(
建筑商(建筑商){
超级建筑商;
this.messageSource=builder.messageSource;
}
公共静态生成器(){
返回新的生成器();
}
/**
*每当需要处理事件消息时,忽略所有消息,因为已经在messageSource中,
*只需从事件源获取所有消息,并从此聚合根开始重新投影所有消息
*@param eventMessages
*/
@凌驾
受保护的无效进程(列表>事件消息){
试一试{
//重新处理此聚合的所有以前的事件(从当前事件获取id)
GenericDomainEventMessage gdem=(GenericDomainEventMessage)eventMessages.get(0);
List>prevEvs=((EventStore)messageSource.readEvents(gdem.getAggregateIdentifier()).asStream()
.collect(Collectors.toList());
processInUnitOfWork(prevEvs,新批处理InUnitOfWork(prevEvs),Segment.ROOT\u段);
}捕获(运行时异常e){
投掷e;
}捕获(例外e){
抛出新的EventProcessingException(“处理事件时发生异常”,e);
}
}
公共静态类生成器扩展SubscribingEventProcessor.Builder{
private SubscribableMessageSource>messageSource;
@凌驾
公共生成器消息源(
SubscribableMessageSource>messageSource){
super.messageSource(messageSource);
this.messageSource=messageSource;
归还这个;
}
@凌驾
公共ReplayingSubscribingEventProcessor.Builder名称(字符串名称){
超级名称(名称);
归还这个;
}
@凌驾
公共ReplayingSubscribingEventProcessor.Builder eventHandlerInvoker(
EventHandlerInvoker(EventHandlerInvoker){
super.eventHandlerInvoker(eventHandlerInvoker);
归还这个;
}
@凌驾
公共ReplayingSubscribingEventProcessor.Builder处理策略(
事件处理策略(事件处理策略){
超级加工战略(加工战略);
归还这个;
}
公共ReplayingSubscribingEventProcessor build(){
返回新的ReplayingSubscribingEventProcessor(此);
}
}
}
和配置:

@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();
    }
@Autowired
公共无效配置(事件处理配置器配置器){
configurer.registerEventProcessor(“inMemoryProcessor”,
(n,c,ehi)->replayingSubscribingEventProcessor(n,c,ehi,org.axonframework.config.Configuration::eventBus);
}
公共重播SubscriptingEventProcessor重播SubscriptingEventProcessor(
字符串名,
org.axonframework.config.conf配置文件,
EventHandlerInvoker EventHandlerInvoker,

功能我刚刚使用
InMemoryTokenStore
配置器。registerTokenStore(“inMemoryProcessor”,cfg->InMemoryTokenStore());
和带有
@ProcessingGroup(“inMemoryProcessor”)的带注释投影仪进行了设置
。现在我看到的是跟踪事件处理器不断轮询来自DB的事件。是否可以仅在调用
@QueryHandler
带注释的方法而不是之前进行投影?基本上,我发送eg id=1的请求,该方法知道,在该时间点,它需要从该aggreg重新投影所有事件ate并返回当前投影(不保存到db)?好的,我刚刚将
queryResult.updates().blockFirst()
更改为
queryResult.initialResult().block()
并且它似乎返回了正确的投影结果。它似乎返回了我猜是上一个投影的东西?如果我使用“更新”,它只是挂在一个循环队列中
来自DomainEventEntry e,其中e.globalIndex>:token
。是的,只有当查询在上传入时,才能创建投影de>@QueryHandler
带注释的函数。不过,这需要一些个人实现。Axon在其内部深处使用
注释EventListenerAdapter
包装带
@EventHandler
注释的类,以便能够使用事件流调用它。您可以在
@QueryHandl中包装投影呃
事件存储中提取事件流
并自己处理这个过程。我以前做过,但只有你能决定这个家庭作业是否可取。谢谢。你有这样的例子吗?还有-知道为什么在m中不触发updates()