MomentoでHTTP APIが使えるようになったのでCloudflare Workersから試してみる

2023.07.26

Introduction

MomentoキャッシュがHTTP APIを提供するようになりました
本稿ではその機能を利用し、Cloudflare Workersから
Momentoキャッシュにアクセスしてみます。

Momento?

このblogでも度々紹介している、
クラウドネイティブな高速キャッシュサービスで、下記のような特徴をもっています。

  • セットアップが簡単
  • プロビジョニングの必要がない(自動でうまくやってくれる)
  • 料金はデータの転送量($0.50/GB)のみ。月50GBまでは無料

Cloudflare Workers?

Cloudflare Workersは、Cloudflareが提供するサーバーレスプラットフォームで、
グローバルエッジネットワーク上でコードを実行できるサービスです。

Cloudflare Workersの主な特徴は以下です。 

  • サーバーレス
    サーバーを用意する必要はなく、
    コードをデプロイするだけで実行できます。

  • グローバルエッジネットワーク
    WorkersはCloudflareのエッジネットワーク上で実行するため、
    ユーザーに最も近いエッジサーバで処理が実行されるので
    パフォーマンスがよいです。

  • イベントドリブン
    Workersはイベント駆動型のアーキテクチャを採用しています。
    httpやタイマーイベントなどに応じてコードが実行されます。

  • プログラム言語
    Workersではさまざまな言語で実装することができます。

Developers.ioのCloudflare Workers関連記事はこちらです。
あわせてご確認ください。

Environment

  • MacBook Pro (13-inch, M1, 2020)
  • OS : MacOS 13.0.1
  • wrangler : 3.3.0

Cloudflareのアカウントについては
登録済みとします。

Try

Momentoの設定

まずはMomentoキャッシュと認証トークンを作成します。
Momento Consoleにアクセスしましょう。

momento-cloudflare-0

アカウントがまだないならここでSignupしてログインします。
ログインしたら、キャッシュ一覧からキャッシュ作成を選択し、
キャッシュ名を記述してクラウドプロバイダーとリージョンを指定します。
現在、Cloudflareのサポートに必要な
Momento Cache HTTP APIは、AWSでのみ利用可能となっているので、
プロバイダに「AWS」、リージョンに「us-west-2」を選択してキャッシュを作成しましょう。

momento-cloudflare-2

次に、トークンのページにアクセスして、
先ほど作成したキャッシュのアクセス権限を持つ
Fine-Grained Access Tokenを生成します。

momento-cloudflare-3

「トークンを生成する」ボタンをクリックするとトークンが生成されるので、
Auth TokenとHTTP Endpointの値をコピーします。
このHTTP Endpointを使ってMomento Cacheへのアクセスができます。

Workersの動作を確認する

ここにWorkersからMomentoにアクセスするサンプルコードがあるので、
cloneでもってきて確認してみましょう。

% git clone https://github.com/momentohq/client-sdk-javascript.git
% cd client-sdk-javascript/examples/cloudflare-workers
% npm install

Workersの設定はwrangler.tomlに記述します。
さきほどのHTTP Endpointと作成したキャッシュ名を設定しましょう。

name = "<プロジェクト名>"
main = "src/worker.ts"
compatibility_date = "2023-07-10"

[vars]
MOMENTO_REST_ENDPOINT="<Http Endpoint>"
MOMENTO_CACHE_NAME = "<キャッシュ名>"

認証トークンは.dev.varsファイルに記述します。

MOMENTO_AUTH_TOKEN="<認証トークン>"

ローカルだけで動かすにはこれでよいのですが、
トークンなどの秘密情報は下記のようにwrangler secretで定義しておきます。

% wrangler secret put MOMENTO_AUTH_TOKEN

#認証トークンを入力

必要な情報を設定したらプログラムを実行してみましょう。

% npm run start

> shy-bush-898e@0.0.0 start
> wrangler dev

 ⛅️ wrangler 3.2.0 (update available 3.3.0)
-----------------------------------------------------
wrangler dev now uses local mode by default, powered by ? Miniflare and ? workerd.
To run an edge preview session for your Worker, use wrangler dev --remote
Using vars defined in .dev.vars
Your worker has access to the following bindings:
- Vars:
  - MOMENTO_REST_ENDPOINT: "..."
  - MOMENTO_CACHE_NAME: "..."
  - MOMENTO_AUTH_TOKEN: "(hidden)"
⎔ Starting local server...
[mf:inf] Ready on http://127.0.0.1:8787/
╭─────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ [b] open a browser, [d] open Devtools, [l] turn off local mode,  clear console, [x] to exit          │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯

これでローカルの開発サーバーが起動します。
http://localhost:8787にアクセスすると、
Momentoキャッシュから返された値が表示されます。

次にCloudflareにデプロイしてみましょう。
デプロイが完了するとURLが表示されます。
URLにアクセスすると、ローカルと同じように動作します。

% npm run deploy

ではWorkersのコード(抜粋)をみてみましょう。
やっていることはシンプルで、これらのAPIをラップしているだけです。

MomentoFetcherではfetchを使って
MomentoのHTTPエンドポイントにアクセスしています。

//src/workers.ts

class MomentoFetcher {
    private readonly apiToken: string;
    private readonly baseurl: string;

  ・・・

    async get(cacheName: string, key: string) {
        const resp = await fetch(`${this.baseurl}/${cacheName}?key=${key}&token=${this.apiToken}`);
        if (resp.status < 300) {
            console.log(`successfully retrieved ${key} from cache`)
        } else {
            throw new Error(`failed to retrieve item from cache: ${cacheName}`)
        }

        return await resp.text();
    }

    async set(cacheName: string, key: string, value: string, ttl_seconds: number = 30) {
        const resp = await fetch(`${this.baseurl}/${cacheName}?key=${key}&token=${this.apiToken}&&ttl_seconds=${ttl_seconds}`, {
            method: 'PUT',
            body: value
        });

        if (resp.status < 300) {
            console.log(`successfully set ${key} into cache`);
        } else {
            throw new Error(`failed to set item into cache message: ${resp.statusText} status: ${resp.status} cache: ${cacheName}`);
        }

        return;
    }
}

Workersのメイン処理ではMomentoFetcherを作成して、
Momentoへget/set/deleteの処理を行っています。

export interface Env {
    MOMENTO_AUTH_TOKEN: string;
    MOMENTO_REST_ENDPOINT: string;
    MOMENTO_CACHE_NAME: string;
}

export default {
    async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
        const client = new MomentoFetcher(env.MOMENTO_AUTH_TOKEN, env.MOMENTO_REST_ENDPOINT);
        const cache = env.MOMENTO_CACHE_NAME;
        const key = "key";
        const value = "value";

                // setting a value into cache
        const setResp = await client.set(cache, key, value);

        console.log("setResp", setResp);

        // getting a value from cache
        const getResp = await client.get(cache, key)
        console.log("getResp", getResp);

        // deleting a value from cache
        const deleteResp = await client.delete(cache, key);
        console.log("deleteResp", deleteResp);

        return new Response(JSON.stringify({ response: getResp}));
    },
};

Summary

サンプルのWorkersでは、MomentoのHTTPエンドポイントを使ってアクセスしています。
Workersに限らず、クライアント側やいろいろなFaas系サービスなど、
どこからでもアクセス可能です。
さまざまな活用方法ができそうですね。

Seminar Announcement about Momento

最後にMomentoセミナーのお知らせです。
2023年8月22日(火)および2023年9月27日(水)にMomentoのセミナーを開催します。
興味があるかたはぜひご参加ください。

また、Momentoについてのお問い合わせはこちらになります。
こちらもお気軽にお問い合わせください。

References