notebook

都内でWEB系エンジニアやってます。

Deno KVを使ってみる

とりあえず触ってみたときのメモ

Deno KV

DenoのKey Valueストア

料金

Deno Deploy Pricing | Deno

料金を見るとfreeでも1GiBと結構使える

さらにread, writeもかなりの数が無料枠で使える

軌道に乗ったらわからないが、個人サービスとかなら十分すぎる感じがする

サンプル

Simple API server

とりあえずサンプルのdeployを使ってKVを使ってみる

基本的にドキュメントの通りに進めた

server.tsを用意して起動、動作確認のために何かデータ入れてみて確認する

お題目がリダイレクタなので適当に自身のtilのURLをPOSTで突っ込んだ

curl --header "Content-Type: application/json" -XPOST --data '{"url":"https://til.swfz.io/","slug":"til"}' https://{sample}.deno.dev/

https://{sample}.deno.dev/til

へアクセスすると設定したtil(https://til.swfz.io)へリダイレクトされた

ローカルでもdeno deployでも確認できた

Productionへのアクセス

本番で動いているKVデータへのアクセス方法

管理画面のKVタブを押下すると使い方、状況など出してくれるのでこれを読めば良さそう

一番下に今あるデータの一覧も表示してくれる

少なければこれでもOKだが、細かく見ていきたいときはあるはず

同画面中のConnect to this database from Deno CLIを見ると本番につなぐコードはこれだよっていわれている

別途DENO_KV_ACCESS_TOKENが必要なのでリンクからTOKENの生成画面へ遷移し、TOKENを生成してコピーしておく

生成したTOKENは実行時に必要なのでDENO_KV_ACCESS_TOKEN環境変数にセットしておく

Operations

操作はこの辺をみて実装する

list

  • denokv.ts
const kv = await Deno.openKv("https://api.deno.com/databases/${UUID}/connect");

const links = kv.list({ prefix: ["links"] })
console.log(links)

for await (const link of links) {
  console.log(link)
}
❯ deno run --allow-env --allow-net --unstable-kv denokv.ts  
KvListIterator {}  
{  
  key: [ "links", "til" ],  
  value: "https://til.swfz.io/",  
  versionstamp: "01000000001005900000"  
}

格納されているデータが表示できた

執筆時はまだBetaなので実行時--unstable-kvフラグが必要だった

あとは、環境変数を見に行くので--allow-env、APIをたたくので--allow-netも必要

これで、ローカルから本番のデータを取得できた

管理ツールとかはCLIで作っておくというのができるので良い

key

Key Space

docs.deno.com

配列で渡すけど内部的には結合させているよう

listで取得するときのprefixの指定は配列の各要素完全一致のようだったのでこのキーをどう設計するかは結構重要そう

他操作

set

お題目とは違うデータを違うキースペースで試しにSetした

  • denokv.ts
const kv = await Deno.openKv("https://api.deno.com/databases/hogehoge/connect");

const setObject = async () => {
  const res = await kv.set(["object", "hoge"], { name: "Deno", version: "1.0.0" });
  console.log(res)
}

setObject()
$ deno run --allow-env --allow-net --unstable-kv denokv.ts
{ ok: true, versionstamp: "01000000004016400000" }

get

  • denokv.ts
const kv = await Deno.openKv("https://api.deno.com/databases/hogehoge/connect");

const getObject = async () => {
  const res = await kv.get(["object", "hoge"]);
  console.log(res)
}

getObject()
deno run --allow-env --allow-net --unstable-kv denokv.ts  
{  
  key: [ "object", "hoge" ],  
  value: { name: "Deno", version: "1.0.0" },  
  versionstamp: "01000000004016400000"  
}

Objectをそのまま渡しても保ったまま保存してくれるようだった、これは便利

expire

入れたデータの有効期限を設定できる

Deno Reference for Deno.Kv

指定はmillisecondsを指定するって書いてある

const setObject = async () => {
  const res = await kv.set(["object", "hoge", "fuga"], { name: "Deno", version: "1.0.0" }, { expireIn: 1000 * 60 });
  console.log(res)
}

サンプルでは60秒で設定した

ドキュメントには最短で消されると書いてあったが、バッチでの削除なのかな?

20分くらい待って確認したけどまだ削除されていなかった(後日確認したら削除されていた)

ローカルで別プロセス間のデータ共有をしたい

たとえば、サーバ側でKVへデータを入れる、CLIで入れたデータを確認するとかそういうケース

const kv = await Deno.openKv("samplekv");

openKvの引数で指定する

openKvは引数でDatabaseの指定を行うためここで同一の文字列を指定すればOK

指定すると、ローカルにはファイルができる(この場合はsamplekv)、それを参照する

SQLite

前項のsamplekvファイル、中身はSQLiteになっているのでクエリできる

$ sqlite3 samplekv
sqlite> .table  
data_version migration_state queue_running  
kv queue

sqlite> .schema kv  
CREATE TABLE kv (  
k blob primary key,  
v blob not null,  
v_encoding integer not null,  
version integer not null  
, seq integer not null default 0, expiration_ms integer not null default -1) without rowid;  
CREATE INDEX kv_expiration_ms_idx on kv (expiration_ms);

sqlite> select * from kv;  
object|o"name"ephemeral object"version"1.0.0{|1|50|0|1726122628971  
object|o"name"parmanent object"version"1.0.0{|1|52|0|-

kvテーブルの中に実データがはいっているようだった

k,vともにblob型なので一部しか見れていないがデータが入っていることは分かる

おわり

いまさらながらDeno KVを使ってみたのでメモ

内部でSQLite使っているのは面白いなーと感じた

活用用途はたくさんありそうなので今後使っていきたい