如何在应用程序启动前重放数据库中的事件?
How to replay events from database before application startup?
我是一名学生,对用于事件溯源的 Axon 框架还很陌生,所以请多多包涵。我目前遇到的问题是,当我的 QueryHandler 需要访问在 spring 应用程序启动之前创建的事件时,它不会包含它们。
例如,创建了以下事件:
- 已创建网店
(该事件创建了一个新的网上商店并将其余额设置为 100)。该事件被保存到我的数据库中。当我查询当前网店余额时,可以return当前余额为100。(事件和查询代码如下)
如果我重新启动应用程序并尝试再次查询当前余额,之前的事件不会重播,所以我无法获得当前余额(重启后事件仍然存在于数据库中,所以我认为这只是框架没有检索所有以前事件的问题)。
我目前使用默认配置,Spring 的 Axon 4.0.3 和一个将事件存储到本地文件的 H2 数据库(我知道 H2 不是最佳选择,但仅此而已用于展示事件溯源和 CQRS 实际应用的小型概念证明,因此不需要大的和可扩展的)。
@Service
@NoArgsConstructor
public class WebshopsEventHandler {
private final Map<String, Webshop> webshops = new HashMap<>();
// ... some other unrelated code
@EventSourcingHandler
public void on(ShopCreatedEvent shopCreatedEvent) {
this.webshops.put(
shopCreatedEvent.getId(),
new Webshop(
shopCreatedEvent.getId(),
shopCreatedEvent.getName(),
shopCreatedEvent.getBalance() // Balance is 100 as default
)
);
}
// ... some more unrelated code
@QueryHandler
protected Optional handle(GetCurrentBalanceQuery getCurrentBalanceQuery) {
System.out.println("Balance query");
if (webshops.containsKey(getCurrentBalanceQuery.getShopId())) {
return Optional.of(webshops.get(getCurrentBalanceQuery.getShopId()).getBalance());
} else {
return Optional.empty();
}
}
}
如何配置 Axon 4 以在重启后检索所有以前的事件?
我想在这种情况下我可以帮助你。
首先让我向您介绍一下为什么您的 'query model store'、private final Map<String, Webshop>
没有在每次启动时都填满。
向 @EventHandler
注释函数提供事件的技术机制称为 事件处理器 。
从 4.0 版开始,Axon Framework 默认为 TrackingEventProcessor
。
TrackingEventProcessor
,顾名思义,跟踪它自己的事件处理。
它通过存储 TrackingToken
来实现 - 在您的设置中,这意味着它将存储在 H2 数据库文件中。 TrackingToken
存储(除其他外)给定 TrackingEventProcessor
处理的最后一个事件。
TrackingToken
允许您重播事件,因为您可以将其指向事件流中的不同时间点。
因此,调整令牌的位置是这种情况下的关键。
您可以通过在 TrackingEventProcessor
上启动重播来完成此操作,here 对此进行了详细解释。
然而,由于您只是展示它是如何工作的,而不是制作一个持久的系统,所以我建议一些更务实的东西。
如果您将 TokenStore
(负责存储您的令牌的组件)调整为 InMemoryTokenStore
,您将确保您的应用程序不会跟踪跟踪事件处理器的进度在您的应用程序关闭之间。
为此,您可以在配置文件或 @SpringBootApplication
注释 class 中执行以下操作(假设您使用的是 Spring 引导):
@Autowired
public void configureInMemoryTokenStore(EventProcessingConfigurer configurer) {
configurer.registerTokenStore(configuration -> new InMemoryTokenStore());
}
希望对您有所帮助!
我是一名学生,对用于事件溯源的 Axon 框架还很陌生,所以请多多包涵。我目前遇到的问题是,当我的 QueryHandler 需要访问在 spring 应用程序启动之前创建的事件时,它不会包含它们。
例如,创建了以下事件:
- 已创建网店
(该事件创建了一个新的网上商店并将其余额设置为 100)。该事件被保存到我的数据库中。当我查询当前网店余额时,可以return当前余额为100。(事件和查询代码如下)
如果我重新启动应用程序并尝试再次查询当前余额,之前的事件不会重播,所以我无法获得当前余额(重启后事件仍然存在于数据库中,所以我认为这只是框架没有检索所有以前事件的问题)。
我目前使用默认配置,Spring 的 Axon 4.0.3 和一个将事件存储到本地文件的 H2 数据库(我知道 H2 不是最佳选择,但仅此而已用于展示事件溯源和 CQRS 实际应用的小型概念证明,因此不需要大的和可扩展的)。
@Service
@NoArgsConstructor
public class WebshopsEventHandler {
private final Map<String, Webshop> webshops = new HashMap<>();
// ... some other unrelated code
@EventSourcingHandler
public void on(ShopCreatedEvent shopCreatedEvent) {
this.webshops.put(
shopCreatedEvent.getId(),
new Webshop(
shopCreatedEvent.getId(),
shopCreatedEvent.getName(),
shopCreatedEvent.getBalance() // Balance is 100 as default
)
);
}
// ... some more unrelated code
@QueryHandler
protected Optional handle(GetCurrentBalanceQuery getCurrentBalanceQuery) {
System.out.println("Balance query");
if (webshops.containsKey(getCurrentBalanceQuery.getShopId())) {
return Optional.of(webshops.get(getCurrentBalanceQuery.getShopId()).getBalance());
} else {
return Optional.empty();
}
}
}
如何配置 Axon 4 以在重启后检索所有以前的事件?
我想在这种情况下我可以帮助你。
首先让我向您介绍一下为什么您的 'query model store'、private final Map<String, Webshop>
没有在每次启动时都填满。
向 @EventHandler
注释函数提供事件的技术机制称为 事件处理器 。
从 4.0 版开始,Axon Framework 默认为 TrackingEventProcessor
。
TrackingEventProcessor
,顾名思义,跟踪它自己的事件处理。
它通过存储 TrackingToken
来实现 - 在您的设置中,这意味着它将存储在 H2 数据库文件中。 TrackingToken
存储(除其他外)给定 TrackingEventProcessor
处理的最后一个事件。
TrackingToken
允许您重播事件,因为您可以将其指向事件流中的不同时间点。
因此,调整令牌的位置是这种情况下的关键。
您可以通过在 TrackingEventProcessor
上启动重播来完成此操作,here 对此进行了详细解释。
然而,由于您只是展示它是如何工作的,而不是制作一个持久的系统,所以我建议一些更务实的东西。
如果您将 TokenStore
(负责存储您的令牌的组件)调整为 InMemoryTokenStore
,您将确保您的应用程序不会跟踪跟踪事件处理器的进度在您的应用程序关闭之间。
为此,您可以在配置文件或 @SpringBootApplication
注释 class 中执行以下操作(假设您使用的是 Spring 引导):
@Autowired
public void configureInMemoryTokenStore(EventProcessingConfigurer configurer) {
configurer.registerTokenStore(configuration -> new InMemoryTokenStore());
}
希望对您有所帮助!