从 DeadlineHandler 中已使用序列的 EventStoreException 中恢复
Recovering from an EventStoreException where sequence is already in use within DeadlineHandler
有时会发生 EventStoreException,指出事件无法存储,因为它与聚合中的另一个事件具有相同的序列。
当 EventA 和 EventB 几乎具有相同的时间戳时会发生这种情况。
CommandA 由控制器发送,CommandB 由 DeadlineHandler 中的 Saga 发送。
所以最后期限的处理失败,记录了 EventStoreException,但没有重试。
如果我们用 PropagatingErrorHandler 配置 Saga 会有帮助吗?
事件table:
timestamp | aggregate_id | seq | type
| | |
2020-11-30T15:14:51.345541552Z | b02a5364-ee34-431a-ab1a-6c59bb937845 | 0 | MyAggregate
2020-11-30T15:14:52.06794746Z | b02a5364-ee34-431a-ab1a-6c59bb937845 | 1 | MyAggregate
异常详情:
org.axonframework.eventsourcing.eventstore.EventStoreException: An event for aggregate [b02a5364-ee34-431a-ab1a-6c59bb937845] at sequence [1] was already inserted
java.sql.BatchUpdateException: Batch entry 0 INSERT INTO events
(event_id, aggregate_id, sequence_number, type, timestamp, payload_type, payload_revision, payload, metadata)
VALUES
('d5be369e-5fd0-475e-b5b6-e12449a4ed04',
'b02a5364-ee34-431a-ab1a -6c59bb937845',
1,
'MyAggregate',
'2020-11-30T15:14:52.067871723Z',
'MyEvent',
NULL,
'{"payload":"payload"}',
'{"metaData":"metaData"}')
was aborted: ERROR: duplicate key value violates unique constraint "uk_aggregate_identifier_sequence_number"
Detail: Key (aggregate_id, sequence_number)=(b02a5364-ee34-431a-ab1a-6c59bb937845, 1) already exists.
如您所见,事件的时间戳几乎相同:
EventA: 2020-11-30T15:14:52.06794746Z
对比 EventB: 2020-11-30T15:14:52.067871723Z
首先回答您的问题,配置 PropagatingErrorHandler
没有帮助,因为 TrackingEventProcessor
不会重试 DeadlineMessage
。它仅适用于重试真实事件,但 DeadlineMessage
并非如此,因为它不是事件。
现在针对你的问题,我们假设你的 Saga 有一个 DeadlineHandler
并且这个组件正在向你的 Aggregate
调度一个 Command
同时另一个组件也在调度一个 Command
到相同的 Aggregate
。这样,Aggregate
就无法处理第二个 Command
。
基于此,我们可以给你2个建议:
- 有一个一致的 Routing Strategy,它被
CommandBus
的分布式实现使用。简而言之,它将为您提供以下内容:
Two commands with the same routing key will always be routed to the same segment.
- 在您的
CommandGateway
上配置 RetryScheduler
。您可以阅读更多相关信息 here。
The RetryScheduler is capable of scheduling retries when command execution has failed.
有时会发生 EventStoreException,指出事件无法存储,因为它与聚合中的另一个事件具有相同的序列。
当 EventA 和 EventB 几乎具有相同的时间戳时会发生这种情况。
CommandA 由控制器发送,CommandB 由 DeadlineHandler 中的 Saga 发送。
所以最后期限的处理失败,记录了 EventStoreException,但没有重试。
如果我们用 PropagatingErrorHandler 配置 Saga 会有帮助吗?
事件table:
timestamp | aggregate_id | seq | type
| | |
2020-11-30T15:14:51.345541552Z | b02a5364-ee34-431a-ab1a-6c59bb937845 | 0 | MyAggregate
2020-11-30T15:14:52.06794746Z | b02a5364-ee34-431a-ab1a-6c59bb937845 | 1 | MyAggregate
异常详情:
org.axonframework.eventsourcing.eventstore.EventStoreException: An event for aggregate [b02a5364-ee34-431a-ab1a-6c59bb937845] at sequence [1] was already inserted
java.sql.BatchUpdateException: Batch entry 0 INSERT INTO events
(event_id, aggregate_id, sequence_number, type, timestamp, payload_type, payload_revision, payload, metadata)
VALUES
('d5be369e-5fd0-475e-b5b6-e12449a4ed04',
'b02a5364-ee34-431a-ab1a -6c59bb937845',
1,
'MyAggregate',
'2020-11-30T15:14:52.067871723Z',
'MyEvent',
NULL,
'{"payload":"payload"}',
'{"metaData":"metaData"}')
was aborted: ERROR: duplicate key value violates unique constraint "uk_aggregate_identifier_sequence_number"
Detail: Key (aggregate_id, sequence_number)=(b02a5364-ee34-431a-ab1a-6c59bb937845, 1) already exists.
如您所见,事件的时间戳几乎相同:
EventA: 2020-11-30T15:14:52.06794746Z
对比 EventB: 2020-11-30T15:14:52.067871723Z
首先回答您的问题,配置 PropagatingErrorHandler
没有帮助,因为 TrackingEventProcessor
不会重试 DeadlineMessage
。它仅适用于重试真实事件,但 DeadlineMessage
并非如此,因为它不是事件。
现在针对你的问题,我们假设你的 Saga 有一个 DeadlineHandler
并且这个组件正在向你的 Aggregate
调度一个 Command
同时另一个组件也在调度一个 Command
到相同的 Aggregate
。这样,Aggregate
就无法处理第二个 Command
。
基于此,我们可以给你2个建议:
- 有一个一致的 Routing Strategy,它被
CommandBus
的分布式实现使用。简而言之,它将为您提供以下内容:
Two commands with the same routing key will always be routed to the same segment.
- 在您的
CommandGateway
上配置RetryScheduler
。您可以阅读更多相关信息 here。
The RetryScheduler is capable of scheduling retries when command execution has failed.