fix(planting-service): improve outbox event confirmation accuracy
- markAsConfirmed now uses aggregateId + eventType for precise matching - Prevents accidentally confirming multiple events for the same order - EventAckController passes eventType to markAsConfirmed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
8de7a668f0
commit
ba5b6141a3
|
|
@ -53,8 +53,11 @@ export class EventAckController {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (message.success) {
|
if (message.success) {
|
||||||
// 标记事件为已确认
|
// 标记事件为已确认(使用 eventId + eventType 精确匹配)
|
||||||
const confirmed = await this.outboxRepository.markAsConfirmed(message.eventId);
|
const confirmed = await this.outboxRepository.markAsConfirmed(
|
||||||
|
message.eventId,
|
||||||
|
message.eventType,
|
||||||
|
);
|
||||||
|
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
|
|
@ -62,7 +65,7 @@ export class EventAckController {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.logger.warn(
|
this.logger.warn(
|
||||||
`[ACK] Event ${message.eventId} not found or already confirmed`,
|
`[ACK] Event ${message.eventId} (${message.eventType}) not found or already confirmed`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -145,25 +145,32 @@ export class OutboxRepository {
|
||||||
/**
|
/**
|
||||||
* 标记事件为已确认(消费方已成功处理)
|
* 标记事件为已确认(消费方已成功处理)
|
||||||
* B方案:收到消费方确认后调用
|
* B方案:收到消费方确认后调用
|
||||||
|
* 使用 aggregateId + eventType 组合精确匹配,避免误确认同一订单的其他事件
|
||||||
*/
|
*/
|
||||||
async markAsConfirmed(eventId: string): Promise<boolean> {
|
async markAsConfirmed(eventId: string, eventType?: string): Promise<boolean> {
|
||||||
// 通过 aggregateId + eventType 查找事件
|
const whereClause: Prisma.OutboxEventWhereInput = {
|
||||||
|
aggregateId: eventId,
|
||||||
|
status: OutboxStatus.SENT,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果提供了 eventType,则精确匹配
|
||||||
|
if (eventType) {
|
||||||
|
whereClause.eventType = eventType;
|
||||||
|
}
|
||||||
|
|
||||||
const result = await this.prisma.outboxEvent.updateMany({
|
const result = await this.prisma.outboxEvent.updateMany({
|
||||||
where: {
|
where: whereClause,
|
||||||
aggregateId: eventId,
|
|
||||||
status: OutboxStatus.SENT,
|
|
||||||
},
|
|
||||||
data: {
|
data: {
|
||||||
status: OutboxStatus.CONFIRMED,
|
status: OutboxStatus.CONFIRMED,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result.count > 0) {
|
if (result.count > 0) {
|
||||||
this.logger.log(`[OUTBOX] ✓ Event ${eventId} confirmed by consumer`);
|
this.logger.log(`[OUTBOX] ✓ Event ${eventId} (${eventType || 'all types'}) confirmed by consumer`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.warn(`[OUTBOX] Event ${eventId} not found or not in SENT status`);
|
this.logger.warn(`[OUTBOX] Event ${eventId} (${eventType || 'any'}) not found or not in SENT status`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue