SlotKeeper 設計と品質

create_reservation detail design

  • Operation: createReservation
  • Endpoint: POST /reservations

1. 正常系入力

Location Name Type 説明
body request CreateReservationRequest -
header Idempotency-Key IdempotencyKey -

Request body CreateReservationRequest

項目 型 説明
resourceId ResourceId 予約する資源を一意に識別するIDです。
startAt BookingTimestamp 予約開始日時です。15分刻みで、現在より後かつ30日以内です。
endAt BookingTimestamp 予約終了日時です。15分刻みで、開始と同じ日本時間の日付内です。
purpose PurposeText 予約目的です。1〜200文字です。

2. 正常系前提

  • 条件分岐: 有効期限内の成功記録がIdempotency-Keyに紐づいている場合。: 不成立
  • 条件分岐: 成功記録の正規化入力と再送された要求が一致しない場合。: 不成立
  • 条件分岐: 予約対象の資源が有効でない場合。: 不成立
  • 条件分岐: 取消済みを除き、半開区間が重なる確定予約がある場合。: 不成立
  • 例外処理: ROUTER_HANDLED_EXCEPTIONS: 発生しない

3. 正常系リソース変更

DB resources 更新

  • SQL: 002_update_resources_control_version.sql
  • 目的: 同一資源の予約作成・取消・無効化を競合させるため、資源の内部制御版を進めて現在値を取得する。
カラム カラム説明 パラメータ/SQL式 値の取得元
control_version 同一資源の予約作成・取消・無効化を競合させる内部制御版。 control_version + 1 SQL式: control_version + 1

DB idempotency_records 削除

  • SQL: 004_delete_idempotency_records.sql
  • 目的: 有効期限を過ぎた成功記録を新規要求として扱うため削除する。
カラム カラム説明 パラメータ/SQL式 値の取得元
principal_id 要求した利用者の認証subject。 principal_id 認証主体: caller.principalId
idempotency_key Idempotency-Keyヘッダの値。 idempotency_key record.idempotency_key

DB users 作成

  • SQL: 005_insert_users.sql
  • 目的: 初めて予約する利用者を記録する。既存利用者は変更しない。
カラム カラム説明 パラメータ/SQL式 値の取得元
principal_id 認証基盤のsubject。 principal_id 認証主体: caller.principalId
first_seen_at 初めて予約した日時。 first_seen_at clock.now()

DB reservations 作成

  • SQL: 006_insert_reservations.sql
  • 目的: 予約を確定状態の初期版で保存する。
カラム カラム説明 パラメータ/SQL式 値の取得元
reservation_id 予約ID。 reservation_id 自動生成: uuid4() を str 化
resource_id 予約対象の資源ID。 resource_id request.body.resourceId
owner_principal_id 予約者の認証subject。 owner_principal_id 認証主体: caller.principalId
start_at 予約開始日時。UTCで保存する。 start_at request.body.startAt
end_at 予約終了日時。UTCで保存し、この時刻を含まない。 end_at request.body.endAt
purpose 予約目的。1〜200文字。本人と管理者だけに返す。 purpose request.body.purpose
status 予約状態。confirmedまたはcancelled。 'confirmed' SQL式: 'confirmed'
row_version 楽観ロック用の行バージョン。 1 SQL式: 1

DB reservation_events 作成

  • SQL: 007_insert_reservation_events.sql
  • 目的: 予約作成の履歴を予約と同じtransactionで追記する。
カラム カラム説明 パラメータ/SQL式 値の取得元
event_id 履歴ID。 event_id 自動生成: uuid4() を str 化
reservation_id 対象の予約ID。 reservation_id reservation.reservation_id
actor_principal_id 操作した利用者の認証subject。 actor_principal_id 認証主体: caller.principalId
action 操作種別。createdまたはcancelled。 'created' SQL式: 'created'
occurred_at 操作日時。 occurred_at clock.now()

DB idempotency_records 作成

  • SQL: 008_insert_idempotency_records.sql
  • 目的: 元の成功応答を予約と同じtransactionで24時間の成功記録として保存する。
カラム カラム説明 パラメータ/SQL式 値の取得元
principal_id 要求した利用者の認証subject。 principal_id reservation.owner_principal_id
idempotency_key Idempotency-Keyヘッダの値。 idempotency_key header.Idempotency-Key
request_hash 正規化した要求本文のSHA-256。 request_hash 入力/生成値から _request_hash(...) で算出
response_payload 元の成功応答のJSON。 response_payload reservation.model_dump_json(by_alias=True)
expires_at 成功記録の有効期限。 expires_at clock.now() + IDEMPOTENCY_TTL

4. 正常系レスポンス

  • Response model: CreateReservationResponse
項目 説明 値の取得元
reservationId 予約を一意に識別するIDです。 reservation.reservation_id
resourceId 予約対象の資源を一意に識別するIDです。 reservation.resource_id
ownerPrincipalId 予約者を表す認証主体IDです。 reservation.owner_principal_id
startAt 予約開始日時です。 reservation.start_at
endAt 予約終了日時です。この時刻を含みません。 reservation.end_at
purpose 予約目的です。本人と管理者だけに返します。 reservation.purpose
status 予約の状態です。 reservation.status
version 予約取消の楽観ロックに使う版です。 reservation.version