本文へ移動
cccskills
無料GitHub で公開

api-design

RESTful API の設計を行います。エンドポイント定義、リクエスト/レスポンス仕様、エラーハンドリング、ScalarDBトランザクション例外のマッピングを含みます。

インストール方法を見る

含まれるファイル(1)

  • SKILL.md23.0 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

API Design Skill

目的

システムのRESTful APIを設計し、以下を定義します:

  1. エンドポイント設計: URL設計、HTTPメソッド、パス構造
  2. リクエスト/レスポンス仕様: DTO定義、バリデーション
  3. エラーハンドリング: エラーコード、エラーレスポンス形式、ScalarDBトランザクション例外のマッピング
  4. OpenAPI仕様書: Swagger/OpenAPI 3.0形式
  5. CDCメタデータのフィルタリング: tx_stateなどの内部カラムの除外
  6. サービス間通信設計: ScalarDB 2PCを利用したマイクロサービス間通信パターン

参照ドキュメント

ドキュメントパス説明
API設計手順workflow/06_api_interface_design.mdAPI設計の詳細ステップ
データアクセスパターンresearch/08_transparent_data_access.mdScalarDBの透過的データアクセス設計
マイクロサービスアーキテクチャresearch/01_microservice_architecture.mdMSAパターンとサービス分割

入力パラメータ

パラメータ必須説明デフォルト
projectNameYesプロジェクト名-
apiVersionNoAPIバージョンv1
baseUrlNoベースURL/api/v1
authTypeNo認証方式Bearer

API設計原則

RESTful設計原則

原則説明例
リソース指向名詞でリソースを表現/users, /audit-sets
HTTPメソッド操作をメソッドで表現GET=取得, POST=作成
ステートレスセッション状態を持たないトークン認証
統一インターフェース一貫したURL設計/resources/{id}

HTTPメソッドマッピング

メソッド操作成功コードべき等性
GET取得200Yes
POST作成201No
PUT全体更新200Yes
PATCH部分更新200No
DELETE削除204Yes

ScalarDB トランザクション例外のAPIマッピング

ScalarDBのトランザクション例外をHTTPステータスコードに適切にマッピングし、クライアントに対して適切なリトライ戦略を提供します。

リトライ可能な競合エラー (409 Conflict)

ScalarDB例外HTTPステータスエラーコードリトライ戦略
CrudConflictException409 ConflictSCALARDB_001Exponential backoff でリトライ推奨
CommitConflictException409 ConflictSCALARDB_002Exponential backoff でリトライ推奨

レスポンス例:

{
  "error": {
    "code": "SCALARDB_001",
    "message": "データ競合が発生しました。リトライしてください",
    "details": {
      "exception": "CrudConflictException",
      "retryable": true,
      "retryStrategy": "exponential_backoff",
      "recommendedWaitMs": 1000
    },
    "timestamp": "2026-02-17T10:00:00Z",
    "traceId": "abc-123-def"
  }
}

不明なトランザクション状態 (500 + リトライガイダンス)

ScalarDB例外HTTPステータスエラーコードリトライ戦略
UnknownTransactionStatusException500 Internal Server ErrorSCALARDB_003べき等性を確認してからリトライ

レスポンス例:

{
  "error": {
    "code": "SCALARDB_003",
    "message": "トランザクションの状態が不明です",
    "details": {
      "exception": "UnknownTransactionStatusException",
      "retryable": true,
      "retryStrategy": "idempotent_retry",
      "guidance": "操作がべき等であることを確認してからリトライしてください",
      "checkEndpoint": "/api/v1/transactions/{transactionId}/status"
    },
    "timestamp": "2026-02-17T10:00:00Z",
    "traceId": "abc-123-def"
  }
}

リトライ不可能なエラー

ScalarDB例外HTTPステータスエラーコード説明
CommitException500 Internal Server ErrorSCALARDB_004トランザクションのコミット失敗
UnsatisfiedConditionException422 Unprocessable EntitySCALARDB_005条件付き更新の条件不一致

UnsatisfiedConditionException のレスポンス例:

{
  "error": {
    "code": "SCALARDB_005",
    "message": "更新条件が満たされていません",
    "details": {
      "exception": "UnsatisfiedConditionException",
      "retryable": false,
      "reason": "Expected version does not match current version",
      "expectedCondition": {
        "field": "version",
        "expectedValue": 5,
        "actualValue": 6
      }
    },
    "timestamp": "2026-02-17T10:00:00Z",
    "traceId": "abc-123-def"
  }
}

エラーハンドリングのベストプラクティス

  1. クライアント側のリトライ実装

    • 409 Conflictの場合: Exponential backoffでリトライ
    • 500 + UnknownTransactionStatus: べき等性確認後にリトライ
    • 422 UnsatisfiedCondition: リトライせずエラー処理
  2. サーバー側の実装

    • トランザクションIDをログに記録
    • 分散トレーシングでトランザクション追跡
    • メトリクスで競合率を監視
  3. モニタリング

    • 409エラーの頻度を監視し、ホットスポットを検出
    • 500エラー(UnknownTransactionStatus)の発生を監視

CDCメタデータのフィルタリング

ScalarDB のChange Data Capture (CDC)機能で使用される内部メタデータカラムをAPIレスポンスから除外します。

フィルタリング対象カラム

カラム名説明フィルタリング理由
tx_stateトランザクション状態内部管理用、クライアントに不要
tx_idトランザクションID内部管理用、クライアントに不要
tx_prepared_atトランザクション準備時刻内部管理用、クライアントに不要
tx_committed_atトランザクションコミット時刻内部管理用、クライアントに不要
tx_versionトランザクションバージョン内部管理用、クライアントに不要
before_tx_idCDC用の前トランザクションIDCDC内部用
before_stateCDC用の前状態CDC内部用
before_versionCDC用の前バージョンCDC内部用
before_prepared_atCDC用の前準備時刻CDC内部用
before_committed_atCDC用の前コミット時刻CDC内部用

フィルタリング実装パターン

1. DTOレイヤーでのフィルタリング

@JsonIgnoreProperties(value = {
    "tx_state", "tx_id", "tx_prepared_at", "tx_committed_at", "tx_version",
    "before_tx_id", "before_state", "before_version",
    "before_prepared_at", "before_committed_at"
})
public class UserResponse {
    private String id;
    private String email;
    private String name;
    // ビジネスフィールドのみ
}

2. マッパーでの明示的フィルタリング

public class UserMapper {
    public UserResponse toResponse(Result result) {
        return UserResponse.builder()
            .id(result.getValue("id").get().getAsString())
            .email(result.getValue("email").get().getAsString())
            .name(result.getValue("name").get().getAsString())
            // CDCメタデータは意図的に除外
            .build();
    }
}

3. 共通フィルタークラス

public class CdcMetadataFilter {
    private static final Set<String> CDC_METADATA_COLUMNS = Set.of(
        "tx_state", "tx_id", "tx_prepared_at", "tx_committed_at", "tx_version",
        "before_tx_id", "before_state", "before_version",
        "before_prepared_at", "before_committed_at"
    );

    public static Map<String, Object> filterCdcMetadata(Map<String, Object> data) {
        return data.entrySet().stream()
            .filter(entry -> !CDC_METADATA_COLUMNS.contains(entry.getKey()))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }
}

APIレスポンス例

フィルタリング前(NG):

{
  "id": "user-001",
  "email": "user@example.com",
  "name": "山田太郎",
  "tx_state": "COMMITTED",
  "tx_id": "tx-12345",
  "tx_version": 3,
  "before_tx_id": "tx-12344"
}

フィルタリング後(OK):

{
  "id": "user-001",
  "email": "user@example.com",
  "name": "山田太郎",
  "createdAt": "2026-02-17T10:00:00Z",
  "updatedAt": "2026-02-17T12:00:00Z"
}

サービス間通信設計

ScalarDB 2PC(Two-Phase Commit)を利用したマイクロサービス間の分散トランザクション設計。

サービス間通信パターン

1. Orchestration パターン(推奨)

サービス間の分散トランザクションをオーケストレーターが調整。

[Order Service] (Orchestrator)
    |
    ├─> [Inventory Service] (Participant)
    ├─> [Payment Service] (Participant)
    └─> [Shipping Service] (Participant)

実装例:

// Order Service (Orchestrator)
public class OrderOrchestrator {
    @POST
    @Path("/orders")
    public Response createOrder(OrderRequest request) {
        TwoPhaseCommitTransaction tx = manager.start();
        try {
            // 1. 在庫予約(Participant 1)
            inventoryClient.reserve(tx.getId(), request.getItems());

            // 2. 支払い処理(Participant 2)
            paymentClient.process(tx.getId(), request.getPayment());

            // 3. 配送手配(Participant 3)
            shippingClient.arrange(tx.getId(), request.getAddress());

            // 4. 注文作成(Coordinator)
            Order order = createOrderRecord(tx, request);

            tx.prepare();
            tx.commit();

            return Response.status(201).entity(order).build();
        } catch (CrudConflictException | CommitConflictException e) {
            tx.rollback();
            return Response.status(409).entity(new ConflictError(e)).build();
        } catch (Exception e) {
            tx.rollback();
            return Response.status(500).entity(new ServerError(e)).build();
        }
    }
}

2. Saga パターン(代替案)

各サービスがローカルトランザクションを実行し、補償トランザクションで整合性を保つ。

Order Created → Reserve Inventory → Process Payment → Arrange Shipping
     ↓              ↓                    ↓                  ↓
  Rollback ← Cancel Reservation ← Refund ← Cancel Shipping

API設計ガイドライン

トランザクションIDの伝播

ヘッダーでの伝播:

POST /api/v1/inventory/reserve
Authorization: Bearer {token}
X-Transaction-Id: tx-12345-67890
X-Request-Id: req-abc-def
Content-Type: application/json

{
  "items": [
    {"productId": "prod-001", "quantity": 2}
  ]
}

べき等性の保証

分散トランザクションでのリトライに備えてべき等性を実装。

@POST
@Path("/inventory/reserve")
@Idempotent
public Response reserveInventory(
    @HeaderParam("X-Transaction-Id") String txId,
    ReservationRequest request) {

    // 既に処理済みかチェック
    if (reservationRepository.exists(txId, request.getProductId())) {
        return Response.status(200).build(); // べき等性
    }

    // 予約処理
    reservation = reservationService.reserve(txId, request);
    return Response.status(201).entity(reservation).build();
}

タイムアウト設計

操作タイプタイムアウト理由
Prepare30秒各サービスの準備完了待ち
Commit60秒全サービスのコミット完了待ち
Rollback30秒ロールバックは速やかに完了すべき
サービス間HTTP10秒ネットワーク遅延を考慮

エラーハンドリング

Participant側のエラーレスポンス:

{
  "error": {
    "code": "INVENTORY_INSUFFICIENT",
    "message": "在庫が不足しています",
    "details": {
      "productId": "prod-001",
      "requested": 10,
      "available": 5,
      "transactionId": "tx-12345"
    },
    "retryable": false
  }
}

Orchestrator側のエラーハンドリング:

try {
    inventoryClient.reserve(txId, items);
} catch (InsufficientInventoryException e) {
    // ビジネスエラー: リトライせずロールバック
    tx.rollback();
    return Response.status(422).entity(toErrorResponse(e)).build();
} catch (ServiceUnavailableException e) {
    // 一時的エラー: リトライ可能
    tx.rollback();
    return Response.status(503).entity(toRetryableError(e)).build();
}

サービス間通信のベストプラクティス

  1. Circuit Breaker の実装

    • サービス障害時の連鎖防止
    • タイムアウトとリトライの制御
  2. 分散トレーシング

    • トランザクションIDとリクエストIDの伝播
    • OpenTelemetry/Zipkinでの追跡
  3. 非同期処理の活用

    • 長時間処理はイベント駆動で分離
    • ScalarDB 2PCは同期的な短時間処理に限定
  4. 部分的な失敗への対処

    • 適切なロールバック処理
    • 補償トランザクションの実装

実行フロー

Stage 1: 既存API分析

1.1 コントローラーの調査
    - エンドポイント一覧
    - リクエスト/レスポンス型
    - 認証・認可設定

1.2 問題点の特定
    - REST原則違反
    - 命名規則の不一致
    - バージョニングの欠如
    - ScalarDB例外の不適切なマッピング
    - CDCメタデータの漏洩

Stage 2: リソース設計

2.1 リソースの特定
    - ドメインモデルからの抽出
    - 集約ルートの特定
    - サブリソースの定義

2.2 URL設計
    - 階層構造の設計
    - クエリパラメータの設計
    - フィルタリング・ソート

Stage 3: エンドポイント設計

3.1 CRUD操作
    - 一覧取得 (GET /resources)
    - 詳細取得 (GET /resources/{id})
    - 作成 (POST /resources)
    - 更新 (PUT/PATCH /resources/{id})
    - 削除 (DELETE /resources/{id})

3.2 カスタムアクション
    - アクション系 (POST /resources/{id}/actions)
    - バッチ操作 (POST /resources/batch)

3.3 サービス間通信エンドポイント
    - 2PC参加エンドポイント
    - トランザクション状態確認

Stage 4: リクエスト/レスポンス設計

4.1 リクエスト設計
    - パスパラメータ
    - クエリパラメータ
    - リクエストボディ
    - ヘッダー(X-Transaction-Id等)

4.2 レスポンス設計
    - 成功レスポンス
    - エラーレスポンス(ScalarDB例外含む)
    - ページネーション
    - CDCメタデータのフィルタリング

Stage 5: エラーハンドリング設計

5.1 HTTPステータスコード
    - 2xx: 成功
    - 4xx: クライアントエラー
    - 5xx: サーバーエラー

5.2 ScalarDB例外のマッピング
    - CrudConflictException → 409
    - CommitConflictException → 409
    - UnknownTransactionStatusException → 500
    - CommitException → 500
    - UnsatisfiedConditionException → 422

5.3 エラーレスポンス形式
    - エラーコード体系
    - リトライ戦略の提示
    - 詳細情報

Stage 6: OpenAPI仕様書生成

出力

output/phase2/06_api_interface_design.md

出力フォーマット

# API設計書

## 概要

| 項目 | 値 |
|------|-----|
| APIバージョン | v1 |
| ベースURL | /api/v1 |
| 認証方式 | Bearer Token (JWT) |
| コンテンツタイプ | application/json |

## 設計原則

### URL設計規則

- リソース名は複数形(kebab-case)
- IDはUUID形式
- ネストは2階層まで
- クエリパラメータはcamelCase

### 認証・認可

- すべてのエンドポイントで認証必須(一部除く)
- JWT Bearer Token をAuthorizationヘッダーで送信
- ロールベースアクセス制御(RBAC)

### ScalarDB固有の設計

- トランザクション例外の適切なHTTPマッピング
- CDCメタデータのフィルタリング
- 分散トランザクションのためのトランザクションID伝播

## リソース一覧

| # | リソース | ベースパス | 説明 |
|---|---------|-----------|------|
| 1 | Users | /api/v1/users | ユーザー管理 |
| 2 | AuditSets | /api/v1/audit-sets | 監査セット |
| 3 | EventLogs | /api/v1/event-logs | イベントログ |

## 共通仕様

### リクエストヘッダー

| ヘッダー | 必須 | 説明 |
|---------|------|------|
| Authorization | Yes | Bearer {token} |
| Content-Type | Yes | application/json |
| Accept-Language | No | レスポンス言語 |
| X-Request-ID | No | リクエスト追跡ID |
| X-Transaction-Id | No* | 分散トランザクションID(2PC使用時必須) |

### ページネーション

```json
{
  "data": [...],
  "pagination": {
    "page": 1,
    "pageSize": 20,
    "totalItems": 100,
    "totalPages": 5
  }
}

クエリパラメータ

パラメータ説明例
pageページ番号?page=1
pageSize1ページの件数?pageSize=20
sortソート項目?sort=createdAt:desc
filterフィルタ条件?filter[status]=active

ScalarDB トランザクション例外のエラーコード

エラーコードScalarDB例外HTTPステータスリトライ
SCALARDB_001CrudConflictException409Yes (Exponential backoff)
SCALARDB_002CommitConflictException409Yes (Exponential backoff)
SCALARDB_003UnknownTransactionStatusException500Yes (べき等確認後)
SCALARDB_004CommitException500No
SCALARDB_005UnsatisfiedConditionException422No

CDCメタデータのフィルタリング

以下のカラムはAPIレスポンスから除外されます:

  • tx_state, tx_id, tx_prepared_at, tx_committed_at, tx_version
  • before_tx_id, before_state, before_version, before_prepared_at, before_committed_at

サービス間通信設計

分散トランザクションエンドポイント

POST /api/v1/{resource}/prepare

トランザクションの準備フェーズ

POST /api/v1/{resource}/commit

トランザクションのコミット

POST /api/v1/{resource}/rollback

トランザクションのロールバック

トランザクションIDの伝播

すべてのサービス間通信でX-Transaction-Idヘッダーを使用してトランザクションIDを伝播します。

エンドポイント詳細

GET /api/v1/users

説明: ユーザー一覧を取得

認可: ADMIN, MANAGER

クエリパラメータ:

パラメータ型必須説明
pageintegerNoページ番号 (default: 1)
pageSizeintegerNo件数 (default: 20, max: 100)
statusstringNoステータスフィルタ

レスポンス (200):

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "email": "user@example.com",
      "name": "山田太郎",
      "status": "active",
      "createdAt": "2026-01-15T09:00:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "pageSize": 20,
    "totalItems": 45,
    "totalPages": 3
  }
}

注意: tx_stateなどのCDCメタデータは除外されています。

エラーレスポンス例

409 Conflict(リトライ可能)

{
  "error": {
    "code": "SCALARDB_001",
    "message": "データ競合が発生しました。リトライしてください",
    "details": {
      "exception": "CrudConflictException",
      "retryable": true,
      "retryStrategy": "exponential_backoff",
      "recommendedWaitMs": 1000
    },
    "timestamp": "2026-02-17T10:00:00Z",
    "traceId": "abc-123-def"
  }
}

422 Unprocessable Entity(リトライ不可)

{
  "error": {
    "code": "SCALARDB_005",
    "message": "更新条件が満たされていません",
    "details": {
      "exception": "UnsatisfiedConditionException",
      "retryable": false,
      "expectedCondition": {
        "field": "version",
        "expectedValue": 5,
        "actualValue": 6
      }
    },
    "timestamp": "2026-02-17T10:00:00Z",
    "traceId": "abc-123-def"
  }
}

500 Internal Server Error(べき等確認後リトライ)

{
  "error": {
    "code": "SCALARDB_003",
    "message": "トランザクションの状態が不明です",
    "details": {
      "exception": "UnknownTransactionStatusException",
      "retryable": true,
      "retryStrategy": "idempotent_retry",
      "guidance": "操作がべき等であることを確認してからリトライしてください",
      "checkEndpoint": "/api/v1/transactions/{transactionId}/status"
    },
    "timestamp": "2026-02-17T10:00:00Z",
    "traceId": "abc-123-def"
  }
}

## API設計チェックリスト

### URL設計
- [ ] リソース名が複数形になっている
- [ ] URLにアクション動詞が含まれていない
- [ ] 一貫したケース規則(kebab-case)
- [ ] 適切な階層構造

### HTTPメソッド
- [ ] 適切なメソッドが使用されている
- [ ] べき等性が考慮されている
- [ ] 適切なステータスコードを返す

### リクエスト/レスポンス
- [ ] 一貫したJSON構造
- [ ] 適切なバリデーション
- [ ] ページネーションの実装
- [ ] 適切なエラーハンドリング
- [ ] CDCメタデータのフィルタリング

### ScalarDB固有
- [ ] トランザクション例外の適切なマッピング
- [ ] リトライ戦略の明示
- [ ] トランザクションIDの伝播(2PC使用時)
- [ ] べき等性の実装(分散トランザクション)

### セキュリティ
- [ ] 認証が必要なエンドポイントの保護
- [ ] 認可の実装
- [ ] 入力値のサニタイズ

## 使用例

Skill: api-design

プロジェクト名: scalar-auditor-for-box APIバージョン: v1 ベースURL: /api/v1 認証方式: Bearer (JWT)


## 注意事項

- 既存のAPIとの後方互換性を考慮する
- バージョニング戦略を事前に決定する
- APIドキュメントは常に最新に保つ
- セキュリティレビューを実施する
- ScalarDBのトランザクション例外を適切にHTTPステータスコードにマッピングする
- CDCメタデータは必ずAPIレスポンスから除外する
- 分散トランザクションではトランザクションIDを確実に伝播する
- べき等性を実装してリトライに対応する

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

database-design

無料日本語概要

ScalarDBを前提としたデータベース設計を行います。スキーマ設計、トランザクション設計、マルチストレージ構成を対話形式で決定し、スキーマファイルと設計書を生成します。

wfukatsu/coding-agent-for-scalardb62026年2月19日 更新

domain-modeling

無料日本語概要

DDDに基づいたドメインモデルを設計します。戦略的設計(境界コンテキスト、ユビキタス言語)と戦術的設計(エンティティ、値オブジェクト、集約、ドメインサービス、ドメインイベント)を定義し、ヘキサゴナルアーキテクチャとの統合を行います。ScalarDBのトランザクション境界や管理テーブル分類の考慮事項を含みます。中間状態はresearch/に記録されます。

wfukatsu/coding-agent-for-scalardb62026年2月19日 更新

implementation-plan

無料日本語概要

設計ドキュメントに基づいて実装計画を生成します。ScalarDB特有のスキーマ定義、トランザクション実装、統合テストを含む実装可能なタスク指示書を作成し、フェーズ別の実装ロードマップを提供します。

wfukatsu/coding-agent-for-scalardb62026年2月19日 更新

infrastructure-design

無料日本語概要

Kubernetes、Kong API Gateway、ScalarDB Cluster v3.17を使用したインフラストラクチャ設計を行います。マニフェストファイルと設定ファイルを生成します。

wfukatsu/coding-agent-for-scalardb62026年2月19日 更新

scalardb-data-model

無料日本語概要

ScalarDBの制約を考慮したデータモデル設計を行います。Partition Key・Clustering Key・Secondary Index の設計、ホットスポット評価、メタデータオーバーヘッド見積もり、バックエンドDB選定を含みます。ワークフローStep 04(データモデル設計)で使用します。

wfukatsu/coding-agent-for-scalardb62026年2月19日 更新

scalardb-transaction

無料日本語概要

ScalarDBのトランザクション設計を行います。トランザクション境界定義、パターン選定(単一集約内/2PC/Saga/ハイブリッド)、OCC競合率評価、バッチ処理設計、v3.17最適化適用計画を含みます。ワークフローStep 05(トランザクション設計)で使用します。

wfukatsu/coding-agent-for-scalardb62026年2月19日 更新

wfukatsu のスキルをすべて見る

このスキルの問題を報告する