Amplify Gen2での開発中に遭遇した循環依存エラーとその解決策についての備忘録です。
発生したエラーの概要
Amplify Gen2では、単純なCRUDだけでなく複雑な処理をカスタム関数として定義できます。この機能を使って、AppSyncを経由してLambda関数から外部APIにアクセスしたり、処理を加えた上でDBアクセスしたりすることが可能です。
カスタム関数を実行するには、amplify/data/resource.tsのDataリソースにカスタムQueryを追加することが推奨されています。
Amplifyでは、DynamoDBのテーブル名は環境ごとに自動生成されます(例: User-ha2gqaugm5a6bddf5s4p46mzfy-NONE)。Lambda関数に環境変数としてこのテーブル名を渡す実装を試みたところ、エラーが発生しました。
実装手順と発生したエラー
1. カスタム関数の作成
まず、基本的な関数を作成します
import { defineFunction } from "@aws-amplify/backend";
export const someFunction = defineFunction({
name: "someFunc",
entry: "./handler.ts",
});
export const handler: Schema["someFunc"]["functionHandler"] = async (event) => {
//DBテーブルに何らか処理する
const tableName = process.env.USER_TABLE_NAME;
//略
return { result: "success" }
}
2. バックエンド設定への追加
定義した関数をbackend.tsに追加します
const backend = defineBackend({
auth,
data,
someFunction
});
const userTable = backend.data.resources.tables["User"];
backend.someFunction.addEnvironment("USER_TABLE_NAME", userTable.tableName);
...略...
3. エラーの発生
サンドボックスを起動すると、以下のエラーが表示されました
npx ampx sandbox
failed: ValidationError: Circular dependency between resources: [xxxxx]
エラーの原因
このエラーは、リソース間の循環依存が原因で発生しています。
具体的には次の条件により発生します。
- Lambda関数(someFunction)がfunctionスタックに配置されている
- Lambda関数がDynamoDBテーブル(User)の情報を環境変数として参照している
- データリソース(dataスタック)がLambda関数を参照している(AppSyncのリゾルバーとして)
この状態では、functionスタックとdataスタックが互いに依存し合う循環参照が発生しています。
解決方法
この問題は、resourceGroupNameオプションを指定することで解決できます。
import { defineFunction } from "@aws-amplify/backend";
export const someFunction = defineFunction({
name: "someFunc",
entry: "./handler.ts",
resourceGroupName: "data",//追加
});
解決の仕組み
resourceGroupName: "data"を指定することで、Lambda関数がfunctionスタックではなくdataスタックに配置されるようになります。これにより次の状態となりエラー発生の原因が解消されます。
- Lambda関数とDynamoDBテーブルが同じスタック内に配置される
- スタック間の循環参照が解消される
Amplify Gen2のリソースグループ構造
Amplify Gen2では、バックエンドリソースは以下のようなリソースグループ(スタック)に分類されます。
auth: 認証関連リソース
data: データ関連リソース(DynamoDB、AppSync)
function: Lambda関数
storage: ストレージ関連リソース
これらのリソースグループはCloudFormationのネステッドスタックとして実装されており、循環参照があるとCloudFormationがデプロイ順序を決定できなくなります。
まとめ
resourceGroupName: "data"を指定することで、Lambda関数をdataリソースグループに移動させ、スタック間の循環参照を解消できます。この方法は、Amplify Gen2の公式ドキュメントでも推奨されているトラブルシューティング方法であり、特に関数がデータリソースと密接に関連している場合に効果的です。
さいごに
今回は、Amplify Gen2のバックエンド設定時の循環依存エラー
failed: ValidationError: Circular dependency between resources:
に対する備忘録を書かせていただきました。
どなたかのお役に立てると幸いです。