[日本語Alexa] Alexa-SDK Ver2 永続化情報の保存先をS3にしてみた 〜PersistenceAdapterの置き換え〜
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の設計すごいと思います。勉強になります。