deliverymq: attempt log is lost when logmq publish fails after a failed delivery (ack despite unpublished log)
Maintainer thường phản hồi trong vòng 1 ngày
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 50/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- go, redis
- Lĩnh vực
- backend, distributed-systems, testing
Hướng nghiên cứu
Start with messagehandler.go:321-331, :388-408, and :161-165 to trace how ErrDestinationPublishAttempt affects ack/nack decisions. Compare TestMessageHandler_PublishError_EligibleForRetry with TestMessageHandler_PublishAndLogError; the issue identifies the missing case as an eligible retry plus a failing log publisher. Done means the test confirms nack, retry scheduling, and eventual log publication when the log publish initially fails.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Problem
The delivery message ack decision is asymmetric with respect to logmq publish failures:
| Delivery outcome | Log publish fails → |
|---|---|
| success | nack — redeliver, log eventually persists (at-least-once, duplicate delivery accepted) |
| system error (pre-attempt) | nack |
| attempt failed, retry scheduled | ack — attempt log is permanently lost |
On the failed-attempt path, the handler schedules the retry, then publishes the log; if the publish fails, the error routes PostDeliveryError → AttemptError → ErrDestinationPublishAttempt → don't nack (messagehandler.go:321-331, :388-408, ack at :161-165). The LogEntry exists only in that process's memory, so the ack discards the only trigger that could re-publish it.
Consequences, as seen in production (#998):
- The attempt record is gone permanently — missing delivery history.
- The scheduled retry later fires, finds no prior attempt in the logstore, and loops on
no prior attempt found in logstore(#663). After #997, it lands in the retry DLQ instead — bounded, but the root loss remains, and quieter.
Why the ack was intentional, and why the reason no longer holds
Nacking here looked unsafe: redelivery re-runs scheduleRetry, which appeared to double-schedule. But Schedule uses a deterministic message ID (RetryID = eventID:destinationID) and rsmq SendMessage with a custom ID overwrites the existing message — re-scheduling is idempotent. (One precondition: the receive-count reset on overwrite, raised in #997 review.)
Proposed behavior
Uniform rule: ack only when the attempt log has been published; nack otherwise, regardless of delivery outcome. The logstore is the system of record — an unrecorded attempt didn't happen, so redo the unit of work. This matches what the success path already does.
Trade-offs to discuss:
- During a sustained logmq outage, failed deliveries get re-attempted at redelivery cadence, outside the retry backoff schedule (already true for successful deliveries today). A bounded local retry of the log publish before nacking would soften this.
- Redelivered attempts produce new attempt IDs → duplicate rows possible after recovery. Dup rows over lost rows.
Test gap
The suite covers every ack/nack path except this one. TestMessageHandler_PublishAndLogError looks like it covers it but uses a plain error, exercising the system-error branch (nack, no retry scheduled). The missing case is ErrDestinationPublishAttempt + eligible retry + log publish failure — a small variation of TestMessageHandler_PublishError_EligibleForRetry with a failing log publisher. Should land with the fix, asserting nack + retry scheduled + log eventually published.
Surfaced by @LendritIbrahimi in #998 (additional context section). #999 makes the trigger rarer; #997 bounds the orphaned-retry symptom; neither addresses the loss itself.
- Ngôn ngữ chính
- Go
- Star
- 1.1k
- Fork
- 70
- Merge trung bình
- 1 ngày 18 giờ
- Pull request đã merge (30 ngày)
- 56
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của hookdeck/outpost
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
hookdeck/outpost#1117 · 1 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của hookdeck/outpost
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 81/100
apache/rocketmq-dashboard#6895 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 87/100
777genius/agent-notifications#490 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
devantler-tech/ksail#7836 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
keyxmakerx/Chronicle#1469 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 73/100
Maintainer thường phản hồi trong vòng 1 ngày