この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
Alexa SDK V2では、永続化情報を簡単に扱うためにAttributesManagerというオブジェクトが提供されています。
参考:[日本語Alexa] Alexa-SDK Ver2(その4) スキル属性
AttributesManagerでは、セッションを跨いだ永続化データは、デフォルトでDynamoDBに保存されるようになっています。
今回は、ask-sdk-s3-persistence-adapter(ASK SDK S3 Persistence Adapterパッケージ)を使用して、保存先をS3にする手順を確認してみました。
https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs/tree/2.0.x/ask-sdk-s3-persistence-adapter
注意:Amazon S3では、既存オブジェクトの更新は、結果整合性となるため、保存したデータのリアルタイムな整合性が必要な場合には、従来のDynamoDBの利用が必要です。
2 インストール
インストールは下記の要領となります。
npm install --save ask-sdk-s3-persistence-adapter
ASK SDK S3 Persistence Adapterは、単体では動作できないためask-sdk-core若しくは、ask-sdkが必要です。
コードでインポートする要領は、次のようになります。
TypeScript
import * as Adapter from 'ask-sdk-s3-persistence-adapter';
JavaScript
const Adapter = require('ask-sdk-s3-persistence-adapter');
3 使ってみた
TypeScriptで使ってみたコードは、下記のとおりです。
import * as Alexa from 'ask-sdk';
import { RequestEnvelope } from 'ask-sdk-model';
import * as Adapter from 'ask-sdk-s3-persistence-adapter';
let skill: Alexa.Skill;
exports.handler = async function (event: RequestEnvelope, context: any) {
const s3PersistenceAdapter = new Adapter.S3PersistenceAdapter({
bucketName: 'alexa-s3-persistence-adapter'
})
if (!skill) {
skill = Alexa.SkillBuilders.custom()
.addRequestHandlers(TestHandler)
.withPersistenceAdapter(s3PersistenceAdapter)
.create();
}
return skill.invoke(event, context);
}
const TestHandler: Alexa.RequestHandler = {
canHandle(_h: Alexa.HandlerInput) {
return true;
},
async handle(h: Alexa.HandlerInput) {
// 永続化情報の取得
let attributes = await h.attributesManager.getPersistentAttributes()
if(!attributes.counter){
attributes.counter = 0;
}
attributes.counter++;
// 永続化情報の保存
h.attributesManager.setPersistentAttributes(attributes);
await h.attributesManager.savePersistentAttributes();
return h.responseBuilder
.speak('カウンターは' + attributes.counter + 'です')
.getResponse();
}
}
SkillBuilderで.withPersistenceAdapterを使用して、永続化情報用のアダプタとして、S3PersistenceAdapterをセットしています。これで、デフォルトのDynamoDBを使用したDynamoDbPersistenceAdapterを置き換えたことになります。
アダプタを置き換えれば、AttributesManagerを使用したデータの保存場所は、S3となります。
ここで、少し注意が必要なのは、withAutoCreateTable(true) は、使えないため、バケットは、予め作成しておく必要があります。
4 Key名
S3PersistenceAdapterのコンストラクタを確認すると、ObjectKeyGeneratorが指定されていない場合、ObjectKeyGenerator.userIdで初期化されていることが確認できます。
ask-sdk-s3-persistence-adapter/lib/attributes/persistence/S3PersistenceAdapter.ts
export class S3PersistenceAdapter implements PersistenceAdapter {
protected bucketName : string;
protected s3Client : S3;
protected objectKeyGenerator : ObjectKeyGenerator;
protected pathPrefix : string;
constructor(config : {
bucketName : string,
s3Client? : S3,
objectKeyGenerator? : ObjectKeyGenerator,
pathPrefix? : string,
}) {
this.bucketName = config.bucketName;
this.s3Client = config.s3Client ? config.s3Client : new S3({apiVersion : 'latest'});
this.objectKeyGenerator = config.objectKeyGenerator ? config.objectKeyGenerator : ObjectKeyGenerators.userId;
this.pathPrefix = config.pathPrefix ? config.pathPrefix : '';
}
・・・省略・・・
ObjectKeyGenerators.userIdは、DynamoDbPersistenceAdapterと同じように、AlexaからのリクエストからuserIdを抽出して利用しているのが分かります。
ask-sdk-s3-persistence-adapter/tst/attributes/persistence/ObjectKeyGenerators.spec.ts
export const ObjectKeyGenerators = {
/**
* Gets attributes id using user id.
* @param {RequestEnvelope} requestEnvelope
* @returns {string}
*/
userId(requestEnvelope : RequestEnvelope) : string {
if (!(requestEnvelope
&& requestEnvelope.context
&& requestEnvelope.context.System
&& requestEnvelope.context.System.user
&& requestEnvelope.context.System.user.userId)) {
throw createAskSdkError(
'PartitionKeyGenerators',
'Cannot retrieve user id from request envelope!',
);
}
return requestEnvelope.context.System.user.userId;
},
この部分を置き換えることで、Key名を変更できるでしょう。要領としては、下記のブログで紹介した「プライマリーキーを変える」要領と同じです。
参考:[日本語Alexa] Alexa-SDK Ver2 DynamoDB利用時のTips 〜リージョンを指定したり、プライマリーキーを変えて、スキルで共通のデータを保存したり〜
5 最後に
今回は、Alexa SDK V2に提供されている、永続化情報の保存先をS3に変更する要領を確認してみました。このアダプターの置き換えを利用すると、DynamoDB,S3以外のリソースも、簡単に保存先に変更できることが分かります。
ほんと、このSDKの設計すごいと思います。勉強になります。