Preview Bản nháp chờ review — title, nội dung, link có thể sửa trước khi bỏ nhãn.

Handler nhận request, bắn ba job: void audit(); void notify(); await save(); rồi return 200. Process restart: audit/notify dở dang, lỗi nuốt, metric “success” trong khi side-effect không xong. Đó là async mồ côi — không cha, không cancel, không join.

Structured concurrency: mọi task con nằm trong scope (nursery). Scope chỉ kết thúc khi con xong — hoặc bị cancel theo cây khi cha hủy / lỗi policy.

Vấn đề fire-and-forget

// JS — “xong” với caller, chưa xong với thế giới
async function handle(req) {
  void writeAudit(req)        // lỗi? ai bắt?
  void sendEmail(req.user)    // inventory ẩn
  return { ok: true }
}
// Client disconnect: hai task vẫn chạy (orphan)
// xem cancellation + inflight-inventory
  • Lỗi con không bubble → fail im.
  • In-flight không đếm → OOM “không hiểu”.
  • Cancel request không lan → việc mồ côi.

Scope = cha

// Ý structured (pseudo)
await withScope(async (scope) => {
  scope.fork(() => writeAudit(req))
  scope.fork(() => sendEmail(req.user))
  await save(req)
}) // đợi / cancel cả fork; policy lỗi rõ ràng

Kotlin coroutineScope, Java structured concurrency API, Trio nursery, Swift task group — cùng ý: cây task, không “đẻ rơi”.

Policy khi con fail

  • Cancel siblings + escalate: một fail → hủy anh em, scope throw (all-or-fail).
  • Isolate: log lỗi con, cha vẫn chạy (cần nói to — giống best-effort ignore).

Promise.all gần all-or-fail nhưng không cancel sibling mặc định (trừ AbortSignal tự truyền). Structured = cancel + lifetime gắn scope, không chỉ “đợi cả đám”.

Với series

  • Cancel theo cây, không chỉ một fetch.
  • Budget gắn scope cha — hết giờ hủy cả nhóm.
  • Không thay idempotency khi job bị cancel giữa chừng rồi redelivery.

Checklist

  1. Request path có void / fire-and-forget không?
  2. Disconnect/budget có hủy hết con không?
  3. Lỗi con có metric + policy không?
  4. Shutdown process: join hay kill mồ côi?

Một câu

Task có cha có mẹ — đừng đẻ async mồ côi.
Scope = lifetime + cancel + chỗ bắt lỗi, không chỉ Promise.all.