more
Build and Publish / BuildAndDeployArm64 (push) Failing after 5s
Build and Publish / BuildAndDeployAmd64 (push) Has been cancelled

This commit is contained in:
2026-06-21 23:47:53 +02:00
parent 9d420c43fa
commit a1f0bad972
5 changed files with 38 additions and 24 deletions
+6 -1
View File
@@ -60,7 +60,12 @@ func (p *rabbitPublisher) Publish(exchange, routingKey string, body []byte) erro
return err
}
}
err := p.ch.PublishWithContext(context.Background(), exchange, routingKey, false, false,
// Bound the publish so a half-open/black-holed connection can't wedge the
// outbox relay indefinitely; on timeout the error path resets and the relay
// retries on its next tick.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
err := p.ch.PublishWithContext(ctx, exchange, routingKey, false, false,
amqp.Publishing{ContentType: "application/json", Body: body})
if err != nil {
p.reset() // force a reconnect on the next attempt
+6 -5
View File
@@ -134,11 +134,12 @@ func (s *server) handleFromCheckout(w http.ResponseWriter, r *http.Request) {
s.logger.Warn("from-checkout flow failed", "orderId", id.String(), "err", runErr)
}
// Record the idempotency key durably so retries (incl. after a restart) are
// safe. We record even on a failed flow: the failed order grain exists, and a
// blind retry with the same key should return it rather than place a second
// order — the caller is told to retry with a fresh key (402 contract).
if req.IdempotencyKey != "" {
// Record the idempotency key durably only on success, so retries (incl. after
// a restart) return the captured order. A failed flow (402) is deliberately
// NOT recorded: the failed grain is terminal, and a retry with the same key
// should re-attempt rather than be handed back a dead order as a 409 hit
// (which the checkout client treats as a successful, existing order).
if req.IdempotencyKey != "" && runErr == nil {
if err := s.idem.Put(req.IdempotencyKey, ordID); err != nil {
s.logger.Error("idempotency record failed", "key", req.IdempotencyKey, "orderId", id.String(), "err", err)
}
+5 -4
View File
@@ -102,11 +102,12 @@ func main() {
// event survives a broker outage or a crash after the state change.
box, err := outbox.Open(filepath.Join(dataDir, "outbox.log"))
if err != nil {
logger.Warn("outbox disabled: open failed", "err", err)
} else {
go box.Run(context.Background(), newRabbitPublisher(amqpURL), 5*time.Second, logger)
emitPub = box
// Durability-critical (same as the idempotency store): fail fast rather
// than silently publish events nowhere for the whole process lifetime.
log.Fatalf("open outbox: %v", err)
}
go box.Run(context.Background(), newRabbitPublisher(amqpURL), 5*time.Second, logger)
emitPub = box
}
freg := flow.NewRegistry()
flow.RegisterBuiltinHooks(freg)