Closed4
Athena-Queryを使ってみる。
ピン留めされたアイテム
DevIOでブログ化した。
Athena-Queryを使ってみる。
AWS SDKを生で使ってAthenaクエリをしようとするとポーリング処理を設ける必要があり面倒(Amazon Athenaのクエリ実行と実行結果の取得をAWS SDKでやってみた(exponential-backoff) | DevelopersIO)。Athena-Queryを使えば記述をシンプルにできる。
インストール
npm install @classmethod/athena-query @aws-sdk/client-athena
使う
import { Athena } from '@aws-sdk/client-athena';
import AthenaQuery from '@classmethod/athena-query';
const athena = new Athena({});
const athenaQuery = new AthenaQuery(athena, {
db: 'default',
workgroup: 'athenaWorkGroup',
catalog: 'AwsDataCatalog',
});
const main = async () => {
for await (const item of athenaQuery.query('SELECT * FROM device_table;')) {
console.log(item); // You can get all items across pagination.
}
};
main();
試行1
実行したらコンストラクタじゃないと言われる。
$ npx ts-node query.ts
/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app/query.ts:5
const athenaQuery = new AthenaQuery(athena);
^
TypeError: athena_query_1.default is not a constructor
at Object.<anonymous> (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app/query.ts:5:21)
at Module._compile (node:internal/modules/cjs/loader:1105:14)
at Module.m._compile (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app/node_modules/ts-node/src/index.ts:1618:23)
at Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
at Object.require.extensions.<computed> [as .ts] (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app/node_modules/ts-node/src/index.ts:1621:12)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
at phase4 (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app/node_modules/ts-node/src/bin.ts:649:14)
at bootstrap (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app/node_modules/ts-node/src/bin.ts:95:10)
AthenaQuery
がdefault exportされていないから。
Another solution would be to add "esModuleInterop": true, into tsconfig.json.
esModuleInterop allows default imports from modules with no default export.
自分、以前にも同じ事象でハマっていた。
tsconfig.json
のcompilerOptionsに"esModuleInterop": true
を設定したら、実行成功した。
$ npx ts-node query.ts
{ amount: 15, deviceid: 'device_01' }
{ amount: 1, deviceid: 'あああ' }
試行2
tsx
を使えば、esModuleInterop
を設定しなくても、CommonJSモジュールを実行できる。
tsx is a CLI command (alternative to node) for seamlessly running TypeScript & ESM, in both commonjs & module package types.
esModuleInterop
を設定せずに実行できた。
$ npx tsx query.ts
Need to install the following packages:
tsx
Ok to proceed? (y) y
{ amount: 15, deviceid: 'device_01' }
{ amount: 1, deviceid: 'あああ' }
AWS Lambda上で使ってみる
実装
- lib/cdk-sample-app.queryDevicesFunc.ts
import { Athena } from '@aws-sdk/client-athena';
import AthenaQuery from '@classmethod/athena-query';
const athena = new Athena({});
const athenaQuery = new AthenaQuery(athena, {
db: 'default',
workgroup: 'primary',
catalog: 'AwsDataCatalog',
});
export const handler = async () => {
const items = [];
for await (const item of athenaQuery.query('SELECT * FROM device_table;')) {
items.push(item);
}
return items;
};
デプロイはCDKで行う。GlueやAthena周りのリソースは別途作成済み。権限付与は簡略化。
- lib/cdk-sample-app.ts
import { Construct } from 'constructs';
import { aws_lambda_nodejs, aws_iam, Stack, StackProps } from 'aws-cdk-lib';
export class CdkSampleStack extends Stack {
constructor(scope: Construct, id: string, props: StackProps) {
super(scope, id, props);
const queryDevicesFunc = new aws_lambda_nodejs.NodejsFunction(
this,
'queryDevicesFunc'
);
queryDevicesFunc.addToRolePolicy(
new aws_iam.PolicyStatement({
actions: ['athena:*', 'glue:*', 'athena:*'],
resources: ['*'],
})
);
}
}
デプロイ。
npx cdk deploy "*" --require-approval never
動作確認
実行できた。
[
{
"amount": 1,
"deviceid": "あああ"
},
{
"amount": 15,
"deviceid": "device_01"
}
]
このスクラップは2023/01/31にクローズされました