バージョン競合ガイド
このガイドでは、MBC CQRS サーバーレスフレームワークでバージョン競合がどのように発生するかを説明し、予防と回復のための戦略を提供します。
バージョン競合の原因
バージョン競合は、2つ以上の操作が同時に同じアイテムを更新しようとしたときに発生します。サーバーレスアプリケーションのような分散システムでは、これは適切に処理する必要がある一般的なシナリオです。
競合シナリオ
ユーザーAがアイテムを読み取り(バージョン1)
ユーザーBがアイテムを読み取り(バージョン1)
ユーザーAがアイテムを更新(バージョン1 -> 2)- 成功
ユーザーBがアイテムを更新(バージョン1 -> 2)- 競合!
このシナリオでは、ユーザーBの更新は、ユーザーAによって既にアイテムが更新されているため失敗します。フレームワークはDynamoDBの条件付き書き込みを使用してこの状況を検出します。
楽観的ロックの仕組み
フレームワークは、各アイテムのversionフィールドを通じて楽観的 ロックを実装します。このアプローチは、競合はまれであると想定し、リソースを事前にロックするのではなく、発生したときに処理します。
バージョン定数
import { VERSION_FIRST, VERSION_LATEST } from '@mbc-cqrs-serverless/core';
// VERSION_FIRST = 0: Used when creating new items (VERSION_FIRST = 0: 新規アイテム作成時に使用)
// VERSION_LATEST = -1: Auto-resolve to the latest version (VERSION_LATEST = -1: 最新バージョンに自動解決)
内部動作の仕組み
コマンドを発行する際、フレームワークは:
- 入力バージョンを現在のアイテムのバージョンと照合します
- バージョン番号を1増加させます
- DynamoDBの条件式
attribute_not_exists(pk) AND attribute_not_exists(sk)を使用して一意性を確保します - 別の更新が先に発生した場合、DynamoDBは
ConditionalCheckFailedExceptionをスローします - フレームワークはこれをHTTP 409 Conflictレスポンスに変換します
// Internal implementation (simplified) (内部実装(簡略化))
await this.dynamoDbService.putItem(
this.tableName,
command,
'attribute_not_exists(pk) AND attribute_not_exists(sk)', // Conditional write (条件付き書き込み)
);