前面幾篇把「建立 → 核定 →(待)撮合」串起來了,但用戶會需要知道:我這張單現在到哪了?
目前我用 in-memory Map 做最簡單的讀模型:PENDING → CREATED → MATCHED)。
• 現在的目標是把事件流跑順、體驗整體設計;
• Map 查詢快,程式簡單;
• 不牽涉額外的儲存與運維。
• 使用者送單:Order 先 markPending(orderId)
• Wallet 核定:Order 這邊收到 OrderCreatedEvent 後 → markCreated(orderId)(訊號來自 Day 9,10的事件)
@Component
public class OrderStatusTracker {
private final Map<UUID, OrderStatus> status = new ConcurrentHashMap<>();
public void markPending(UUID id) { status.put(id, OrderStatus.PENDING); }
@RabbitListener(queues = ORDER_CREATED_QUEUE)
public void onOrderCreated(OrderCreatedEvent e) {
status.put(e.getOrderId(), OrderStatus.CREATED);
}
public OrderStatus get(UUID id) { return status.getOrDefault(id, OrderStatus.UNKNOWN); }
}
• 在 PlaceBuyOrderService.execute(...) 建立事件前先 markPending(orderId)(orderId 是建立事件時就生成的)。
• ORDER_CREATED_QUEUE 綁定 order.created,收到 Wallet 的回報就更新狀態(事件結構同 Day 10)。
@RestController
@RequestMapping("/orders")
@RequiredArgsConstructor
public class OrderQueryController {
private final OrderStatusTracker tracker;
@GetMapping("/{id}/status")
public ResponseEntity<String> status(@PathVariable UUID id) {
return ResponseEntity.ok(tracker.get(id).name());
}
}
這樣前端就能用 polling 看到最終一致的狀態;若 PENDING 停太久,UI 可以提醒使用者稍後再查或提供「重新整理」動作。
Map 版讀模型雖然簡單,但不需使用額外服務即可完成目的:
把建立 → 核定 → 可撮合跑穩、看得見;未來再把 MATCHED 加進來,或替換為 Redis/Mongo 都很自然(如未來真的要上更多節點再談儲存層也可以簡單轉換)。