Event-Driven & CQRS — Series 2

Preview — 3 of 10 questions

What does mergeObjectContext do, and why is commit() separate?

javascript
@CommandHandler(ApproveOrder)
export class ApproveOrderHandler implements ICommandHandler<ApproveOrder> {
  constructor(
    private readonly repo: OrderRepository,
    private readonly publisher: EventPublisher,
  ) {}

  async execute({ orderId }: ApproveOrder) {
    const order = this.publisher.mergeObjectContext(await this.repo.findById(orderId));
    order.approve();          // internally calls this.apply(new OrderApproved(...))
    await this.repo.save(order);
    order.commit();
  }
}
AIt attaches a change-tracking proxy so the repository can compute a diff on save
BIt merges the aggregate's state with the latest version from the event store
CIt gives the aggregate instance access to the event bus, so apply() can record events on it; those events stay buffered until commit() publishes them — which lets the handler persist state first and emit only after the write succeeded
DIt converts the aggregate into a request-scoped provider for the duration of the command

What does a snapshot change, and what must remain true?

javascript
An aggregate has 180,000 events. Loading it replays all of them.
AIt replaces the event stream, so older events can be deleted
BIt caches the aggregate in memory, so the first load is still slow
CIt converts the event store into a state store, ending event sourcing for that aggregate
DIt stores the aggregate's state at a known version, so loading replays only the events after it — the events themselves stay the source of truth, and a snapshot must be discardable and rebuildable, since a changed aggregate shape means old snapshots have to be regenerated rather than migrated

Why does this happen in a CQRS system, and how is it usually handled?

javascript
POST /orders    201, order written to the write model
GET  /orders    the new order is missing
AThe read model is updated asynchronously from the events, so there is a window where the write has committed but the projection has not caught up. Options are to return the created resource directly from the command, have the client poll or subscribe, or — for the narrow cases that need it — read from the write model for the caller's own recent writes
BIt indicates a bug: CQRS guarantees the read model is updated in the same transaction
CThe read model must be queried with a special consistency flag to see recent writes
DIt only happens when the read model is on a different database

Sign up free to play

Answer all 10 questions (7 more), see explanations for every answer, and track your score.