DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Claude Codeでイベントスキーマレジストリを設計する:JSON Schema検証・バージョニング・後方互換

はじめに

「イベントのペイロード構造を変えたら下流のサービスが壊れた」——スキーマレジストリでイベントのスキーマをバージョン管理し、後方互換性を保ちながら進化させる設計をClaude Codeに生成させる。


CLAUDE.mdに設計ルールを書く

## イベントスキーマレジストリ設計ルール

- MINOR(1.x.0): 後方互換の追加(optional化、フィールド追加)
- MAJOR(2.0.0): 破壊的変更(フィールド削除、型変更)
- required追加はMINORでは禁止
- 送信前にスキーマ検証(無効なイベントを発行しない)
- 検証エラーはDead Letter Queueへ
Enter fullscreen mode Exit fullscreen mode

生成される実装(抜粋)

export class SchemaRegistry {
  register(eventType, version, schema) {
    // 後方互換チェック(同一Majorバージョン内)
    if (versions.length > 0 && sameMajor) {
      // required追加は禁止
      for (const field of newRequired) {
        if (!oldRequired.has(field)) throw new SchemaCompatibilityError(
          `Cannot add required field '${field}' in ${eventType}@${version}`
        );
      }
      // フィールド削除は禁止
      for (const field of oldFields) {
        if (!newFields.has(field)) throw new SchemaCompatibilityError(
          `Cannot remove field '${field}' without major version bump`
        );
      }
    }
    versions.push({ version, schema, registeredAt: new Date() });
  }

  validate(eventType, version, data) {
    const schema = this.getSchema(eventType, version);
    const validate = ajv.compile(schema.schema);
    return { valid: validate(data), errors: validate.errors?.map(e => `${e.instancePath} ${e.message}`) };
  }
}

// バージョンエンベロープ付きでイベント発行
async publish(eventType, version, data) {
  const { valid, errors } = schemaRegistry.validate(eventType, version, data);
  if (!valid) throw new SchemaValidationError(errors.join(', '));
  await redis.xAdd(`events:${eventType}`, '*', { envelope: JSON.stringify({ id: ulid(), type: eventType, version, payload: data }) });
}

// 受信時: Majorバージョン不一致は処理保留
if (!schemaRegistry.isCompatible(type, receivedVersion, myVersion)) {
  logger.warn('Major version mismatch, skipping');
  return; // 新しいデプロイを待つ
}
Enter fullscreen mode Exit fullscreen mode

まとめ

  1. CLAUDE.md にMINOR変更での後方互換ルール(required追加禁止・フィールド削除禁止)・MAJOR変更は破壊的のみ・DLQへの無効イベント送信を明記
  2. 後方互換チェック をregister時に自動実行——「required追加」「フィールド削除」を試みるとコード時点でエラー
  3. バージョンエンベロープ でメッセージにtype+versionを含める——受信側が自分の対応バージョンを確認してから処理
  4. Majorバージョン不一致 は処理を保留——新しいデプロイが完了するまでメッセージを消費しないことで古いコードでの誤処理を防止

アーキテクチャ設計のレビューは **Code Review Pack(¥980)* の /code-review で確認できます。*

prompt-works.jp

みょうが (@myougatheaxo) — ウーパールーパーのVTuber。

Top comments (0)