RINDA · Sequence 진단
시퀀스 "완료 처리 중" stuck 분석
TL;DR
- 대상 시퀀스는 버그가 아님 — 백엔드의 "답장 수확 3일 가드"에 정상적으로 걸린 상태. 답장이 계속 들어와(오늘 03:29 포함 최근 3일 31건) 3일 윈도우가 매번 리셋 → 답장이 멎고 3일 지나야 자동 완료.
- 진짜 버그는 따로 있음 — enrollment가 끝났는데(terminal/paused) 매달린
pending/deferredexecution이 정리되지 않아 영구 보류. beta 전체 802건 orphan, 최장 21일 stuck.
1. "완료 처리 중" 판정 메커니즘
프론트(campaign-status.ts:70)는
status='active' AND total>0 AND active_enrollments=0 일 때 amber 배지를 띄운다.
즉 DB는 active 인데 백엔드가 completed 로 못 넘긴 모든 경우가 동일하게 보인다.
백엔드 완료 보류 가드는 3개 (enrollment-progress.service.ts:629-647):
| 가드 | 보류 조건 | SSOT |
|---|---|---|
| #1 pending-executions | pending/processing/deferred execution 1건이라도 존재 | :664 |
| #2 recent-reply | harvest 3일 내 답장 존재 | :681 |
| #3 empty-recent-emails | enrollment 0 + 마지막 발송 < 3일 | :723 |
2. beta 실데이터 — stuck 7개 시퀀스 분류
| 시퀀스 | stuck | g1 pending | g2 답장(3d) | g3 마지막발송 | 진단 |
|---|---|---|---|---|---|
| AI 캠페인·6/2 (대상) | 3.1d | 0 | 31 | 0.06d | 정상 보류 |
| 싱가폴·말레이시아 | 3.0d | 0 | 7 | 0.22d | 정상 |
| 오세아니아 외 245명 | 2.8d | 0 | 3 | 2.78d | 정상 |
| 동남아 418개사 | 2.8d | 0 | 2 | 2.67d | 정상 |
| D10_1/2 R1 Group | 10.9d | 0 | 1 | 0.45d | 답장 띄엄띄엄 |
| 스페로네 200명 | 21.1d | 1 | 0 | 10.16d | 버그 |
| 베트남 유아헤어밴드 | 8.2d | 240 | 0 | 19.16d | 버그 |
대상 시퀀스 상세
enrollment: completed 28,349 / bounced 2,094 / stopped 176 / unsub 34 — active 0건. execution은 pending 0 (skipped 32,592 · sent 28,611 · failed 103). 발송 파이프라인은 깨끗하고, 오로지 답장이 계속 들어와 완료가 미뤄지는 것.
핵심
3만 명짜리 대형 캠페인이라 자동응답·재참여(re-engage)로 답장이 끊이지 않아 가드#2의 3일 윈도우가 매번 리셋된다.
설계 의도(답장을 놓치지 않으려 완료 지연)이지만, 대형 캠페인에서는 UX상 영구 stuck 처럼 느껴지는 게 실제 불편 포인트.
3. 진짜 버그 — orphan pending execution
스페로네 / 베트남의 잔존 execution과 소속 enrollment 정합성:
| 시퀀스 | exec status | enrollment status | 건수 | 예약시각 |
|---|---|---|---|---|
| 베트남 | deferred | paused | 240 | 14d 전 ~ 5.8d 미래 |
| 스페로네 | pending | completed | 1 | 6.2d 전 |
모순
enrollment는 이미
completed/paused 인데 그에 속한 execution이 pending/deferred 로 남아 있다.
그런데 가드#1(hasPendingStepExecutions, :664)은 enrollment 상태를 보지 않고 execution 상태만 본다 →
orphan이 1건이라도 있으면 그 시퀀스는 영구 보류.
beta 전체 orphan 규모
enrollment는 terminal/paused 인데 execution은 미처리:
| exec | enrollment | 건수 |
|---|---|---|
| pending | stopped | 685 |
| pending | completed | 57 |
| deferred | completed | 48 |
| deferred | stopped | 12 |
| 합계 | 802 |
근본 원인 2가지
- enrollment를 terminal/paused 로 전이할 때 매달린
pending/deferredexecution을skipped로 정리하지 않음 → orphan 발생. - 자동 복구
recoverStuckProcessingExecutions()(:440)는processing30분 threshold만 복구.pending/deferred는 복구 경로가 없어 영구 잔존.
4. 권장 수정
| 순위 | 조치 | 효과 |
|---|---|---|
| 1 | 가드#1 쿼리(:664)에 AND se.status='active' 추가 | orphan execution이 완료를 막지 못하게 — 802건 stuck 즉시 해소, 근본 정합 |
| 2 | enrollment terminal/paused 전이 시 잔존 pending/deferred 를 skipped 일괄 처리 | orphan 신규 발생 차단 |
| 3 | 기존 802 orphan 백필(skipped) + stuck 시퀀스 완료 재평가 1회 | 현존 데이터 정리 |
| 4 | "완료 처리 중" 배지에 사유 툴팁("최근 답장 처리 중, N일 후 자동 완료") | 가드#2 정상 케이스 혼동 방지 |
핵심
순위 1이 근본 해결책이다. 가드#1이 enrollment 상태를 무시하는 것이 21일 stuck의 직접 원인이고, 한 줄 수정으로 해결된다.