Michael Charles Aubrey

https://MichaelCharl.es/Aubrey

Node 'redis'ライブラリを使用してVercel KVに接続する方法

Node 'redis'ライブラリを使用してVercel KVに接続する方法

Michael Charles Aubrey // Mon Nov 13 2023

Vercel KV(Key-Value)は、Vercel が提供する革新的なサービスで、シンプルなサーバーレスのキーバリューストアソリューションを提供します。Upstash の Redis 機能を利用した Redis 上に構築されており、Vercel は独自の Node ライブラリ @vercel/kv を提供して、これと対話するためのインターフェースを提供しています。@vercel/kvライブラリは、NextJS のサーバーレスエッジ関数の一部としてキーバリューストレージを実装するのに最適です。

なぜ @vercel/kv だけを使わないの?

より正確に言えば、ライブラリが必要な Redis 機能へのアクセスを提供している限りは完璧なのです。Vercel KV の背後には完全な Redis インスタンスがあり、Redis クライアントプロトコル v6.2 までの互換性があります。しかし、提供されているライブラリは、基盤となる Redis インスタンスで利用可能なすべての機能を必ずしも実装しているわけではありません。

ライブラリが提供する機能で十分であれば、それを使い続けるのが良いでしょう。しかし、それでは不十分な場合でも問題ありません!Vercel KV は標準的な Redis インスタンスで動作しているため、redis(または他のお好みの Redis ライブラリ)を使用して接続することができます。

このプロセスはとても簡単ですが、オンラインでこれについて説明している記事が見つからなかったので、記事を書くことにしました。

料金体系

先に進む前に、Vercel KV の料金体系を確認し、理解しておく必要があります。これは従量課金制のモデルで、使用状況によっては月額 1 ドル程度で済む場合もあります。ただし、これらの価格は変更される可能性があるため、先に進む前に自分で料金を確認することをお勧めします。

Vercel KV のセットアップ

まず Vercel KV 自体をセットアップします。新しい Vercel KV ストレージソリューションを作成する必要があります。Vercel にログインした後、トップメニューの「Storage」をクリックします。これにより、作成可能ないくつかのストレージオプションが表示されます。

画像の説明

データベース名とリージョンを入力するダイアログが表示されます。これらを入力すると、新しく作成された Vercel KV Redis インスタンスが表示されます!

画像の説明

「Show Secret」をクリックすると、redis-cliコマンドラインツールを使用して Redis インスタンスに接続するための以下の文字列が表示されます。

redis-cli --tls -u redis://default:597961c4b7344b5f9ce9691ae5fb8bd4@dear-chigger-38419.upstash.io:38419

私たちが注目するのは -u の後の部分です。これが後でredisnode ライブラリを使用してインスタンスに接続する際に使用する Redis 接続文字列なので、安全な場所にコピーしておいてください。

既存の NextJS プロジェクトに Redis を追加する

ここでは既存のプロジェクトに追加することを前提としています。もしそうでない場合は、NextJS の入門ガイドに従ってください。セットアップに特別な手順は必要ありません。

NextJS プロジェクトができたら、redisライブラリをインストールしましょう。

npm i redis

環境変数

以前安全な場所にコピーした接続文字列にredisがアクセスできるようにする必要があります。そのために、.env.localに新しい環境変数を以下のように追加します。

REDIS_URL=redis://default:597961c4b7344b5f9ce9691ae5fb8bd4@dear-chigger-38419.upstash.io:38419

上記の接続文字列は、Vercel ダッシュボードからコピーした自分の接続文字列に置き換える必要があることを忘れないでください。

Redis 設定

読みやすさのため、また記事を流し読みする人のために、これを独立したセクションに分けました。以下が必要な設定です:

const REDIS_CONFIG = {
  url: process.env.REDIS_URL,
  socket: {
    tls: true,
  },
};

既に何をすべきか分かっている場合は、この設定をcreateClient関数に渡すだけで完了です。tlstrueに設定することが重要で、これがないと接続文字列を適切に指定しても機能しません。実際、それだけです。

まだ分からない場合は、次のセクションに進んでください。

Redis ボイラープレート

私のボイラープレートを使用する必要は必ずしもありませんが、現在のプロジェクトで使用しており、シングルトンを介して Redis クライアントを提供する効率的な方法だと考えています。以下は設定が既に組み込まれているコードです。私のプロジェクトでは、これを./redis/index.tsに配置しています。

import { createClient, RedisClientType } from "redis";

const REDIS_CONFIG = {
  url: process.env.REDIS_URL,
  socket: {
    tls: true,
  },
};

class RedisService {
  private static instance: RedisService;
  private client: RedisClientType;

  private constructor() {
    this.client = createClient(REDIS_CONFIG);
    this.client.on("error", (err) => console.log("Redis Client Error", err));
    this.client.connect();
  }

  public static getInstance(): RedisService {
    if (!RedisService.instance) {
      RedisService.instance = new RedisService();
    }
    return RedisService.instance;
  }

  getClient() {
    return this.client;
  }
}

export const getRedisClient = () => RedisService.getInstance().getClient();

上記のコードはgetRedisClient関数をエクスポートしており、これは Vercel KV Redis インスタンスに接続された Redis クライアントを返します。

Redis クライアントの使用

ここまで来た方は、実装したい Redis 機能があってここにいるのだと思うので、このセクションは必要ないかもしれません。ただし、単に興味本位でここに来て、試してみたいものがある場合は、以下に Redis を使用して実装された簡単なインクリメント/デクリメント機能の例を示します。これは、先ほどエクスポートしたgetRedisClient関数を使用しています。

import { getRedisClient } from "..";

const COUNTER_NAMESPACE = "counter";

export const incrementCount = async (
  increment: number = 1
): Promise<number> => {
  const client = getRedisClient();
  try {
    const newCount = await client.incrBy(`${COUNTER_NAMESPACE}`, increment);
    return newCount;
  } catch (error) {
    console.error(error);
    return 0;
  }
};

export const decrementCount = async (
  decrement: number = 1
): Promise<number> => {
  const client = getRedisClient();
  try {
    const newCount = await client.decrBy(`${COUNTER_NAMESPACE}`, decrement);
    if (newCount < 0) {
      await client.set(`${COUNTER_NAMESPACE}`, "0");
      return 0;
    }
    return newCount;
  } catch (error) {
    console.error(error);
    return 0;
  }
};

export const getCount = async (): Promise<number> => {
  const client = getRedisClient();
  try {
    const count = await client.get(`${COUNTER_NAMESPACE}`);
    if (count) {
      return parseInt(count);
    }
    return 0;
  } catch (error) {
    console.error(error);
    return 0;
  }
};

動作例

動作例を GitHub にアップロードしました。こちらからアクセスして、リポジトリをプルして自分で試すことができます。リポジトリを使用するには、Vercel KV インスタンスを作成し、接続文字列を取得して、クローンしたリポジトリの.env.localファイルに提供する必要があることを忘れないでください。

この記事は元々 dev.to に掲載されています。