🦕

Deno DeployでKVを使ってみる

2023/06/10に公開

Denoにデフォルト搭載のKeyValueストアが実装されました。

以下記事に詳しく書かれています。

https://zenn.dev/uki00a/articles/kv-store-introduced-in-deno-v1-32

さて、自分はDeno Deployに有料でいいからストレージがほしい!!!と叫び続けているのですが、こちら以下のページを見る限り以下のように書かれています。

https://deno.com/deploy/docs/kv

  • Deno DeployはDeno KVと呼ばれる組み込みのサーバーレスKeyValueストアを提供する
  • まだクローズドベータテスト中
    • その間の料金は無料らしいので実際に提供されたときの金額は不明
    • Deno Deployにログインして https://dash.deno.com/kv からwaitlistに登録可能
  • 1ユーザー辺り最大1GBのストレージが割り当てられる

使ってみたらエラーで登録しないといけないということで5/6に申請し、6/9に使えるようになったので実際に使ってみたいと思います。

ただ書き込む

とりあえず書き込んでみましょう。以下コードはDeno DeployのPlaygroundで実行しています。

import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';

const VERSION = 1;

async function GetVersions() {
  const kv = await Deno.openKv();
  // await kv.delete(['versions']);
  const versions = await kv.get(['versions']);

  console.log(versions);
  if (!versions.value) {
    await kv.set(['versions'], [VERSION]);
    return [VERSION];
  }
  if (versions.value.includes(VERSION)) {
    return versions.value;
  }
  versions.value.push(VERSION);
  kv.set(['versions'], versions.value);
  return versions.value;
}

const versions = await GetVersions();

serve((req: Request) => {
  return new Response(versions.join(','));
});

ログを見ます。

1回目
{
  key: [ "versions" ],
  value: null,
  versionstamp: null
}

もう一度デプロイしてみます。

2回目
{
  key: [ "versions" ],
  value: [ 1 ],
  versionstamp: "000007fea43a72c30000"
}

ちゃんとデプロイ後もデータを保存できてますね。

データを追加

今回はバージョンを新しくするとそれをどんどん追加する作りになっているので、バージョンを変更してみます。

import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';

const VERSION = 2;

async function GetVersions() {
  const kv = await Deno.openKv();
  // await kv.delete(['versions']);
  const versions = await kv.get(['versions']);

  console.log(versions);
  if (!versions.value) {
    await kv.set(['versions'], [VERSION]);
    return [VERSION];
  }
  if (versions.value.includes(VERSION)) {
    return versions.value;
  }
  versions.value.push(VERSION);
  kv.set(['versions'], versions.value);
  return versions.value;
}

const versions = await GetVersions();

serve((req: Request) => {
  return new Response(versions.join(','));
});
VERSIONを2に変更
{
  key: [ "versions" ],
  value: [ 1, 2 ],
  versionstamp: "000007feca6701e80000"
}

無事変更されています。

複数ユーザーの情報を使い分ける

DenoKVのキーは複数の値を設定できます。これを使えばユーザー情報の管理も可能です。

import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';

async function AddUser(kv, userId, name) {
  await kv.set(['users', userId], {
    userId: userId,
    name: name,
  });
}

async function GetAllUser(kv) {
  const users = [];
  for await (const entry of kv.list({ prefix: ['users'] })) {
    console.log(entry);
    users.push(entry.value);
  }
  return users;
}

const kv = await Deno.openKv();
/*for await (const entry of kv.list({ prefix: ["users"] })) {
	await kv.delete(entry.key);
}*/
await AddUser(kv, 1, 'Alice');
await AddUser(kv, 2, 'Bob');
const users = await GetAllUser(kv);

serve((req: Request) => {
  return new Response(JSON.stringify(users));
});

こちらusersは以下のようになります。

[{ "userId": 1, "name": "Alice" }, { "userId": 2, "name": "Bob" }]

簡単なユーザー登録とその一覧を取得できましたね。もちろん上のコードを使って await kv.get(['users', 1]) ユーザーIDを指定すればAliceのデータだけ取得できます。

全データ削除

最後に簡単に全データを消しておきましょう

import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';

const kv = await Deno.openKv();
for await (const entry of kv.list({ prefix: [] })) {
  console.log(entry);
  await kv.delete(entry.key);
}

serve((req: Request) => {
  return new Response('test');
});

実行結果は以下です。

{
  key: [ "users", 1 ],
  value: { userId: 1, name: "Alice" },
  versionstamp: "000007fef3d6bf840000"
}
{
  key: [ "users", 2 ],
  value: { userId: 2, name: "Bob" },
  versionstamp: "000007fef3d92bd90000"
}
{
  key: [ "versions" ],
  value: [ 1, 2 ],
  versionstamp: "000007feca6701e80000"
}

無事前回いじったversions含めすべてのデータを削除できました。

まとめ

今回はものすごくざっくりとDeno KVをDeno Deployで利用しました。
単純なオブジェクトのようなものではなく、キーを複数指定してテーブルのような使い方も可能となっています。通常のDenoでも --unstable を指定すれば使えるようなので、便利な簡易DBとして使えると思います。

ストレージが使えるとDeno Deployでできることの幅が広がるので、色々と使ってみたいですね。

Discussion