前回の記事で,このブログのコンテンツが格納されているS3とクライアントの間にCloudFrontを設置しました。

しかし、CloudFrontはコンテンツをエッジにキャッシュします。CloudFrontエッジキャッシュにオブジェクトを保持する時間を指定したりもできますが、即時反映させるには、エッジキャッシュからオブジェクトを削除し、オブジェクトを無効化する必要があります。

コンソール上のCloudFrontの画面からInvalidationを実行することもできますが、ブログを更新するたびに手作業でInvalidationするの面倒なので、以下のようなLambda関数を作成しました。

architecture.png

var AWS = require('aws-sdk');
var cf = new AWS.CloudFront();
//CloudFrontのディストリビューションID
var distributionId = '--DistributionID--';

exports.handler = async (event, context) => {
    var timestamp = new Date().getTime().toString();
    var paths = getPathsFromEvent(event);
    var params = {
        DistributionId: distributionId,
        InvalidationBatch: {
            //CallerReferenceはInvalidation requestを一意に識別する値。ここではtimestampを使う。Stringでないとだめ。
            CallerReference: timestamp,
            Paths: paths,
        }
    };

    //cf.createInvalidation(params)だとAWSのRequestインスタンスが帰ってくる。Requestインスタンスのpromiseメソッドを使って、レスポンスのpromiseを返す。
    var data = await cf.createInvalidation(params).promise();
    console.log('invalidate: ' + paths.Items[0]);
    return;
};

function getPathsFromEvent(event) {
    return {
        Quantity: 1,
        Items: ['/' + event.Records[0].s3.object.key],
    };
}

AWSのJavaScriptのSDKのメソッド、createInvalidationを使います。

async awaitを使っています。ポイントは以下。

  • promiseに対応した非同期処理の関数はpromiseを返す。
  • promiseをawaitすると非同期処理の結果が返ってくる。
  • Node.jsでI/O処理(ファイルの読み書き、データベースへのアクセス、APIの呼び出しなどネットワーク越しの処理など)は基本的に非同期処理
  • 同期処理用のメソッドが提供されているものもある
  • とにかくI/Oがからむと非同期処理!!

async awaitはふんわりとしか理解できてない気がするので、ブログにまとめるなりしてちゃんと理解したいです。