Skip to the content.

0006. Resource / Project の削除は関連 Assignment を TransactWriteItems で原子的に cascade delete する

Note: 本 ADR は当初 Clerk Organization (pk = ORG#X) を前提に書かれた。 ADR 0009 で multi-tenant 単位を Clerk Org → 自前 Team モデルに再設計したため、 本文中の orgId / ORG# 表記は teamId / TEAM# と読み替えること。 cascade 戦略自体は不変。

Context

Resource / Project を削除したとき、関連する Assignment をどう扱うかを決める必要がある。 DynamoDB は外部キー制約を持たないため、app 層で整合性を担保する (docs/db/access-patterns.md A3 参照)。

選択肢:

説明 DB 整合性 UX 実装複雑度
(A) Cascade delete (TransactWriteItems で原子的) Resource + 関連 Assignment を 1 つの transaction で削除 ◎ (1 操作で完結)
(B) Block delete (関連 Assignment があれば 409) 「先に Assignment を削除してください」 △ (手作業多い)
(C) Orphan 許容 (Resource だけ削除、Assignment は残す) UI 表示時に projectId が見つからない Assignment を非表示 ❌ ゴミデータ蓄積 △ (見えないデータが残る)
(D) BatchWriteItem で eventually consistent cascade 25 件ずつ chunk、途中失敗でゴミ残る可能性

Decision

(A) Cascade delete を採用。 Resource と関連 Assignment、または Project と関連 Assignment を 1 つの TransactWriteItems で原子的に削除する。

実装詳細

web/src/lib/repository/resource.tsdeleteResource(teamId, id) (Project 側も同様):

  1. Query(pk = TEAM#X AND begins_with(sk, "ASN#")) + FilterExpression: resourceId == id で関連 Assignment の SK 一覧を取得 (pagination 対応)
  2. TransactWriteItems で:
    • Resource 自身の Delete (pk=TEAM#X, sk=RES#id)
    • 各関連 Assignment の Delete (pk=TEAM#X, sk=ASN#date#id)
  3. TransactWriteItems の制限 100 items。total が 100 を超えたら Error('cascade delete exceeds 100 items') を throw

UX

ResourceManager / ProjectManager の各行に「(N 件のアサイン)」と関連件数を表示。削除ボタン押下時の confirm() ダイアログで:

「{name}」と関連 {N} 件のアサインを削除しますか?
(取り消しできません)

関連 0 件なら従来どおり「{name} を削除しますか?」のみ。

100 件超のフォールバックは未実装

100 件超のフォールバック (BatchWriteItem chunk 化) は YAGNI として未実装。理由:

Consequences

Positive

Negative

Neutral

Alternatives considered

Implementation notes

+page.server.ts の form action は変更不要 — repository の deleteResource / deleteProject がそのまま cascade 動作になるため、呼び出しシグネチャ互換。

References