こんにちは、CX 事業本部 Delivery 部の若槻です。
今回は、AWS SDK for JS のタイムアウト設定に利用していた @aws-sdk/node-http-handler
が deprecated となったため @smithy/node-http-handler
で置き換えてみました。
@aws-sdk/node-http-handler で型エラーが発生するようになった
@aws-sdk/node-http-handler では HTTP リクエストハンドラーが提供されています。これを利用することにより、下記で紹介されているように AWS SDK で HTTP リクエストのタイムアウトを設定することができます。
この @aws-sdk/node-http-handler
ですが、ライブラリバージョンを次のようにアップデートしました。
package.json
{
"dependencies": {
"@aws-sdk/client-dynamodb": "3.438.0",
"@aws-sdk/node-http-handler": "3.374.0"
}
}
すると次のような TypeScript の型エラーが発生するようになりました。
Argument of type '[{ region: string; apiVersion: string; requestHandler: NodeHttpHandler; }]' is not assignable to parameter of type '[DynamoDBClientConfig] | []'.
Type '[{ region: string; apiVersion: string; requestHandler: NodeHttpHandler; }]' is not assignable to type '[DynamoDBClientConfig]'.
Type '{ region: string; apiVersion: string; requestHandler: NodeHttpHandler; }' is not assignable to type 'DynamoDBClientConfig'.
Type '{ region: string; apiVersion: string; requestHandler: NodeHttpHandler; }' is not assignable to type 'ClientDefaults'.
Types of property 'requestHandler' are incompatible.
Type 'NodeHttpHandler' is not assignable to type 'HttpHandler'.
Type 'NodeHttpHandler' is missing the following properties from type '{ updateHttpClientConfig(key: never, value: never): void; httpHandlerConfigs(): {}; }': updateHttpClientConfig, httpHandlerConfigsts(2345)
@aws-sdk/node-http-handler が deprecated となり、@smithy/node-http-handler への移行が推奨されていた
@aws-sdk/node-http-handler の npm ページを見ると、2023 年 7 月頃より利用が非推奨(deprecated)となっていました。
This package has been deprecated
Author message:
This package has moved to @smithy/node-http-handler
そして合わせて移行先としてアナウンスされていたのが @smithy/node-http-handler
です。
@smithy/node-http-handler で置き換える
@aws-sdk/node-http-handler
を @smithy/node-http-handler
で置き換えてみます。と言っても両者は互換性があるため、パッケージ名を置き換えるだけで移行可能です。
まず @aws-sdk/node-http-handler
をアンインストールし、@smithy/node-http-handler
をインストールします。
npm uninstall @aws-sdk/node-http-handler
npm install @smithy/node-http-handler
アンインストールおよびインストールできました。
package.json
{
"dependencies": {
"@aws-sdk/client-dynamodb": "3.438.0",
+ "@smithy/node-http-handler": "2.1.8"
- "@aws-sdk/node-http-handler": "3.374.0"
}
}
そして @aws-sdk/node-http-handler
の import を @smithy/node-http-handler
に置き換えます。
src/companies.ts
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
// import { NodeHttpHandler } from "@aws-sdk/node-http-handler"; // 削除
import { NodeHttpHandler } from "@smithy/node-http-handler"; // 追加
const dynamodbClient = new DynamoDBClient({
region: "ap-northeast-1",
apiVersion: "2012-08-10",
requestHandler: new NodeHttpHandler({
connectionTimeout: 200,
requestTimeout: 1000,
}),
});
これで型エラーが解消されました。
また最終的に次のようなコードで @smithy/node-http-handler
を利用することができました。AWS X-Ray によるキャプチャを AWS SDK クライアントでも利用可能にする captureAWSv3Client
や DynamoDB のデータをドキュメント形式で利用可能にする DynamoDBDocument
などをあわせて使用した場合でも問題なく動作しました。
src/companies.ts
import {
ConditionalCheckFailedException,
DynamoDBClient,
} from "@aws-sdk/client-dynamodb";
import { DynamoDBDocument } from "@aws-sdk/lib-dynamodb";
import { NodeHttpHandler } from "@smithy/node-http-handler";
import { captureAWSv3Client } from "aws-xray-sdk";
const region = process.env.AWS_REGION || "ap-northeast-1";
const apiVersion = "2012-08-10";
const COMPANIES_TABLE_NAME =
process.env.COMPANIES_TABLE_NAME || "dummy-companiesTableName";
const dynamodbClient = captureAWSv3Client(
new DynamoDBClient({
region: region,
apiVersion: apiVersion,
requestHandler: new NodeHttpHandler({
connectionTimeout: 200, // 初回の TCP 接続(SYN SENT)の試行に十分な値を設定。2回目の TCP Retransmission を待たずにタイムアウトさせる
requestTimeout: 1000, // 1 回あたりの API オペレーションの最大取得サイズ 1 MB の取得に十分な値を設定
}),
}),
);
const doc = DynamoDBDocument.from(dynamodbClient);
export interface Company {
id: string;
name: string;
}
/**
* PutItem を使用して会社テーブルにアイテムを put する
* @param company Company
*/
export const putItem = async (company: Company): Promise<void> => {
try {
await doc.put({
TableName: COMPANIES_TABLE_NAME,
Item: company,
ConditionExpression: "attribute_not_exists(id)",
});
} catch (e) {
if (e instanceof ConditionalCheckFailedException) {
throw new Error("CompanyAlreadyExists");
}
throw new Error(JSON.stringify(e));
}
};
そもそも Smithy って何?
node-http-handler
の名前空間の移行先となった Smithy は、AWS が今まで開発してきたインターフェイス定義言語から AWS 固有の実装を分離し、AWS SDK 以外でも広く利用できるようにされたツールです。
Smithy は、Amazon および AWS 内で 10 年以上にわたって広く使用されているインターフェイス定義言語に基づいています。私たちは、他の開発者が独自のサービスに Smithy を使用し、何万ものサービスを構築してきた私たちの長年の経験から恩恵を受けることができるように、Smithy を一般公開することにしました。Smithy の仕様とツールをリリースすることで、開発者がオープンソースの AWS SDK を維持しやすくなるようにしたいと考えています。
リクエストハンドラーなどの AWS SDK のコア仕様ではない実装は切り離して別のエコシステムで育てた方が得策だと判断されたようです。
参考
以上