ETag を使用して FHIR リソースの競合を防止する

このページでは、Cloud Healthcare API の FHIR リソースで同時実行管理エンティティタグ(ETag)を使用する方法について説明します。ETag は、楽観的同時実行制御とクライアントサイド キャッシュを有効にすることで、データ損失を防ぎ、アプリケーションのパフォーマンスを向上させます。

ETag について

ETag は、バージョン番号と同様に、サーバー上の FHIR リソースの現在の状態の一意の識別子として機能します。FHIR リソースが作成または変更されるたびに、新しい ETag 値が生成されます。

ETag を使用すると、次の状況でデータの整合性を保証し、パフォーマンスを最適化できます。

  • 楽観的同時実行制御を保証するには: FHIR リソースを変更するリクエストに ETag を含めると、Cloud Healthcare API はその ETag がサーバー上の FHIR リソースの最新バージョンと一致するかどうかを検証します。これにより、あるクライアントが別のクライアントが行った変更を誤って上書きすることを防ぐことができます。これは、書き込み競合または「更新の失敗の問題」とも呼ばれます。

  • 条件付きリクエストの送信: ETag を使用すると、クライアントは特定の条件が満たされた場合にのみ、リクエストを条件付きで送信できます。これにより、データ取得が最適化され、不要なネットワーク トラフィックが削減されます。たとえば、次の HTTP ヘッダーを使用して条件付きリクエストを送信できます。

    • If-Match: 指定された ETag がサーバーの現在の ETag と一致する場合にのみ、リクエストは成功します。これにより、FHIR リソースの想定されるバージョンを更新できます。
    • If-None-Match: 指定された ETag がサーバーの現在の ETag と一致しない場合のみ、リクエストは成功します。これにより、ローカルにキャッシュに保存されているリソースのバージョンが最新かどうかを確認できるため、毎回サーバーからリソース全体を取得する必要がなくなります。これは通常、効率的なキャッシュに使用されます。

FHIR ETag は弱い検証を使用します。つまり、異なるサーバー インスタンス間で同じではない可能性がありますが、リソースの変更を効果的に追跡します。

ETag を取得する

次のサンプルでは、FHIR リソースの内容を取得する方法を示しています。

ETag は、FHIR リソースのコンテンツを取得するときに、完全な HTTP レスポンス ヘッダーに含まれます。ETag は FHIR リソースの Meta.versionId と一致します。

リクエストのデータを使用する前に、次のように置き換えます。

  • PROJECT_ID: Google Cloud プロジェクトの ID
  • LOCATION: データセットの場所
  • DATASET_ID: FHIR ストアの親データセット
  • FHIR_STORE_ID: FHIR ストア ID
  • FHIR_RESOURCE_TYPE: FHIR のリソースタイプ
  • FHIR_RESOURCE_ID: FHIR のリソース ID

curl

fhir.read メソッドを使用します。-verbose フラグは、ETag を含むレスポンスの HTTP ヘッダーを返します。

curl -X GET \
    -verbose \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/FHIR_RESOURCE_TYPE/FHIR_RESOURCE_ID"

レスポンスには次のものが含まれます。

< etag: W/"ETAG_VALUE"

PowerShell

fhir.read メソッドを使用します。-Headers フラグを指定すると、ETag を含むレスポンスの HTTP ヘッダーが返されます。

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
    -Method GET `
    -Headers $headers `
    -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/FHIR_RESOURCE_TYPE/FHIR_RESOURCE_ID" | Select-Object -Expand Headers

レスポンスには次のものが含まれます。

ETag                   {W/"ETAG_VALUE"}

FHIR リソースの更新時の同時実行を管理する

次のサンプルは、FHIR リソースの更新時に ETag を含める方法を示しています。

サンプルでは If-Match を使用しています。この動作は次のとおりです。

  • ETag がサーバー上の FHIR リソースの現在の ETag と一致する場合、更新は成功し、サーバーは更新されたリソースに新しい ETag を生成します。これにより、想定されるバージョンの FHIR リソースが更新されます。

  • ETag が一致しない場合、更新は 412 Precondition Failed エラーで失敗します。これは、元の ETag が取得されてから別のクライアントがリソースを変更したことを示します。これにより、誤って上書きされるデータの損失を防ぐことができます。

リクエストのデータを使用する前に、次のように置き換えます。

  • ETAG_VALUE: FHIR リソースの ETag 値
  • PROJECT_ID: Google Cloud プロジェクトの ID
  • LOCATION: データセットの場所
  • DATASET_ID: FHIR ストアの親データセット
  • FHIR_STORE_ID: FHIR ストア ID
  • FHIR_RESOURCE_TYPE: FHIR のリソースタイプ
  • FHIR_RESOURCE_ID: FHIR のリソース ID

curl

fhir.update メソッドを使用します。

curl -X PUT \
    -H "If-Match: W/\"ETAG_VALUE\"" \
    -H "Content-Type: application/json; charset=utf-8" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -d @request.json \
    "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/FHIR_RESOURCE_TYPE/FHIR_RESOURCE_ID"

レスポンスには、更新された FHIR リソースが含まれます。

PowerShell

fhir.update メソッドを使用します。

$cred = gcloud auth print-access-token
$etag = W/\"ETAG_VALUE\""
$headers = @{
  "Authorization" = "Bearer $cred"
  "If-Match"      = "$etag"}

Invoke-WebRequest `
    -Method PUT `
    -Headers $headers `
    -InFile request.json `
    -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/FHIR_RESOURCE_TYPE/FHIR_RESOURCE_ID" | Select-Object -Expand Content

レスポンスには、更新された FHIR リソースが含まれます。

クライアントサイド キャッシュを実装する

ETag を使用してクライアントサイド キャッシュを実装できます。これにより、データ取得が高速化され、よりスムーズでレスポンシブなユーザー エクスペリエンスを実現できます。

以前にキャッシュに保存された FHIR リソースを取得するには、キャッシュに保存された ETag を If-None-Match ヘッダーに含めます。この動作は次のとおりです。

  • ETag が一致する場合、サーバーは 304 Not Modified で応答し、クライアントはキャッシュ内のコピーを使用します。これにより、帯域幅を節約し、サーバー負荷を軽減できます。

  • ETag が一致しない場合、サーバーは更新された FHIR リソースと新しい ETag を送信し、クライアントがキャッシュを更新できるようにします。

次のサンプルは、サーバーの ETag と一致する ETag を使用して FHIR リソースの内容を取得する方法を示しています。

リクエストのデータを使用する前に、次のように置き換えます。

  • ETAG_VALUE: FHIR リソースの ETag 値
  • PROJECT_ID: Google Cloud プロジェクトの ID
  • LOCATION: データセットの場所
  • DATASET_ID: FHIR ストアの親データセット
  • FHIR_STORE_ID: FHIR ストア ID
  • FHIR_RESOURCE_TYPE: FHIR のリソースタイプ
  • FHIR_RESOURCE_ID: FHIR のリソース ID

curl

fhir.read メソッドを使用します。-verbose フラグを指定すると、レスポンスで HTTP ヘッダーが返されます。それ以外の場合は、レスポンスは返されません。

curl -X GET \
    -H "If-None-Match: W/\"ETAG_VALUE\"" \
    -v \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/FHIR_RESOURCE_TYPE/FHIR_RESOURCE_ID"

レスポンスには 304 Not Modified ステータス コードが含まれます。

PowerShell

fhir.read メソッドを使用します。-Headers フラグは、レスポンスで HTTP ヘッダーを返します。返されない場合、レスポンスは返されません。

$cred = gcloud auth print-access-token
$etag = W/\"ETAG_VALUE\""
$headers = @{
"Authorization" = "Bearer $cred"
  "If-None-Match"      = "$etag"}

Invoke-WebRequest `
    -Method GET `
    -Headers $headers `
    -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/fhirStores/FHIR_STORE_ID/fhir/FHIR_RESOURCE_TYPE/FHIR_RESOURCE_ID" | Select-Object -Expand Headers

レスポンスには 304 Not Modified ステータス コードが含まれます。