A worker pulls a message off a queue and acks it before it finishes processing. When processing fails, the message is already gone and is lost forever. Fix the ack ordering so failures are redelivered (at-least-once).
You'll predict the failure first, then write the fix and watch your own code drive the behavior.
큐(대기줄)에 일감이 쌓여 있고, 일꾼이 맨 앞 일감을 하나 꺼낸다. 꺼낸 일감은 '처리 중' 칸으로 옮겨진다.
🔧 도구:MessageQueueinflight set
String m = queue.pollFirst(); if (m != null) inflight.add(m); // moved to inflight return m;
“A worker pulls one message off the queue to process it.”
checking microphone…
'ack'는 큐한테 '이거 다 끝냈으니 지워도 돼'라고 말하는 거다. ack하면 그 일감은 완전히 사라진다.
🔧 도구:ack()
void ack(String msg) {
inflight.remove(msg); // done -> removed for good
}“Ack tells the queue the message is done, so it gets removed for good.”
checking microphone…
지금 코드의 순서가 거꾸로다. 일을 시작하기 전에 먼저 ack부터 해버린다. 일감을 지우고 나서 일을 한다.
⚖️ Trade-off: 먼저 지워버리면, 일하다 실패해도 되돌릴 게 없다.
🔧 도구:ack() before process()
boolean process(String msg, boolean willFail) {
if (willFail) return false; // do the work FIRST, do not ack yet
done.add(msg);
mq.ack(msg);
return true;
}“The bug is the order: it acks first, and only then does the work.”
checking microphone…
일이 중간에 실패한다고 해보자. 일감은 이미 지워졌다. 'redeliver(다시 넣기)'를 불러도 넣을 일감이 없다 → 그 일은 영영 사라진다.
⚖️ Trade-off: 한 번 삐끗하면 그 메시지는 조용히 증발한다. 아무도 모른다.
🔧 도구:redeliver()
void redeliver(String msg) {
if (inflight.remove(msg)) queue.addFirst(msg); // only works if still inflight
}“If the work fails, the message is already gone, so it is silently lost.”
checking microphone…
고치는 법: 순서를 바꾼다. 일을 먼저 다 끝내고, 성공했을 때만 마지막에 ack한다.
✅ Fix: 성공해야만 지운다. 실패하면 일감은 '처리 중' 칸에 그대로 남는다.
🔧 도구:process() then ack()
if (willFail) return false; // fail: skip ack done.add(msg); mq.ack(msg); // ack ONLY after success
“The fix is to ack only after the work succeeds.”
checking microphone…
이제 실패하면? 일감이 아직 살아 있으니 redeliver가 그걸 큐 맨 앞에 다시 넣는다. 다음에 또 시도한다 → 최소 한 번은 처리된다.
🔧 도구:redeliver()at-least-once delivery
boolean ok = w.process(got, true); if (!ok) mq.redeliver(got); // still inflight -> back to head, retried
“On failure the message stays inflight, so redelivery puts it back to retry.”
checking microphone…
단, 새 문제가 하나 생긴다. 일은 성공했는데 ack 직전에 일꾼이 죽으면? 큐는 성공을 못 봤으니 같은 일감을 또 보낸다 → 같은 일이 두 번 처리될 수 있다.
⚖️ Trade-off: 성공-직후-사망 시 같은 메시지가 한 번 중복으로 다시 온다.
✅ Fix: 받는 쪽을 '여러 번 와도 결과가 같게(멱등)' 만든다. 그럼 중복이 와도 안전하다. 잃어버리는 것보단 두 번이 낫다.
🔧 도구:idempotency keydedup on consumer
// worker may die after process() but before ack() -> one duplicate redelivery if (seen.add(key)) done.add(msg); // consumer dedups -> idempotent
“It can duplicate if a worker dies after the work but before the ack, so consumers must be idempotent.”
checking microphone…
7단계 영어를 다 말하면 → 이 메커니즘 전체를 영어로 설명할 수 있게 된다.
Say it out loud in your own words — hit these terms — then check against the gold answer.
Say it in your own words — but hit these: queue · at least once · concurrency · idempotency
checking microphone…