publishPendingApproval fires email.pending_review (direction=outbound) via the outbox (PublishTx — pre-side-effect: the pending row hasn't been sent to SES yet) AND the legacy goroutine. pendingMsgID seeds the deterministic event id so /send retries with the same idempotency key don't fire duplicate
(ctx context.Context, e webhookpub.Event, pendingMsgID string)
| 350 | // deterministic event id so /send retries with the same idempotency |
| 351 | // key don't fire duplicate events. |
| 352 | func (a *API) publishPendingApproval(ctx context.Context, e webhookpub.Event, pendingMsgID string) { |
| 353 | var outboxWrote bool |
| 354 | if a.outbox != nil && pendingMsgID != "" { |
| 355 | e.ID = webhookpub.DeterministicEventID(pendingMsgID, e.Type) |
| 356 | err := a.store.WithTx(ctx, func(tx pgx.Tx) error { |
| 357 | return a.outbox.PublishTx(ctx, tx, e) |
| 358 | }) |
| 359 | if err != nil { |
| 360 | log.Printf("[api] outbox tx for email.pending_review err: %v", err) |
| 361 | } else { |
| 362 | // err==nil means the tx committed AND PublishTx returned |
| 363 | // nil — both are required for the row to be durably |
| 364 | // recorded. (If the flag was off, PublishTx no-op'd and |
| 365 | // returned nil; outbox.Enabled() guards that below in |
| 366 | // shouldFireLegacy so we don't suppress legacy in that |
| 367 | // case either.) |
| 368 | outboxWrote = true |
| 369 | } |
| 370 | } |
| 371 | a.emit().OutboxEventsPublished(e.Type) |
| 372 | if a.shouldFireLegacy(outboxWrote) { |
| 373 | a.publishAsync(e) |
| 374 | } |
| 375 | } |
| 376 | |
| 377 | // publishApproved fires email.review_approved via the outbox |
| 378 | // (PublishBestEffortTx — POST-side-effect: SES has already accepted |
no test coverage detected