---
title: "@unikvs/vercel-runtime-cache"
description: "Vercel のランタイムキャッシュに値を保存する @unikvs/vercel-runtime-cache の使い方を説明します。"
---

## 概要 [#overview]

`@unikvs/vercel-runtime-cache` は Vercel のランタイムキャッシュに値を保存するストレージです。

このストレージはランタイムキャッシュを自動検出して使い、見つからなければプロセス内の `Map` にフォールバックします。どちらの場合も TTL と最大件数による追い出しを行います。

- `name` は `VercelRuntimeCache` です。
- バックエンドを共有するときは `namespace` を指定してください。`namespace` を指定した場合、`clear` は現在のインスタンスが追跡しているキーだけを削除します。同じ名前空間で他のインスタンスやプロセスが書き込んだキーは削除されません。
- `maxEntries` による追い出しと失効したキーの削除は、インスタンスごとの追跡に基づきます。そのため、共有バックエンドは `maxEntries` を超えるキーを保持することがあります。
- バックエンドの追い出しは書き込みが古い順 (FIFO) で、フォールバックの追い出しは最も古く使われた順 (LRU) です。
- `namespace` が空でバックエンドが `clear` を持つ場合は、`clear` はバックエンド全体を削除します。
- `isOpen` は常に `true` です。`open()`・`close()` は中断の確認のみ行います。
- `delete` は存在しないキーを指定した場合は `KeyNotFoundError` を投げます。
- ストリームの読み書きに対応しています。

インストールは次のコマンドで行います。

```package-install
npm install @unikvs/vercel-runtime-cache
```

## 使い方 [#usage]

VercelRuntimeCache は IStorage を実装しています。UniKvs には persist() で渡します。

```ts
import { VercelRuntimeCache } from "@unikvs/vercel-runtime-cache";
```

### `VercelRuntimeCache` [#vercel-runtime-cache]

Vercel Runtime Cache を使うストレージです。

コンストラクターの引数は次のとおりです。

| Prop | Type | Default | Description |
| - | - | - | - |
| `ttlSeconds?` | `[#vercel-runtime-cache-ttl-seconds] number` | `60` | エントリの有効期限 (秒) です。 |
| `maxEntries?` | `[#vercel-runtime-cache-max-entries] number` | - | 保持するエントリの最大数です。未指定なら無制限です。バックエンドでは書き込みが古い順 (FIFO)、フォールバックでは最終使用が古い順 (LRU) に追い出します。 |
| `namespace?` | `[#vercel-runtime-cache-namespace] string` | `""` | バックエンドのキーに付与する名前空間です。複数のストレージで同じバックエンドを共有するときに使います。 |
| `clone?` | `[#vercel-runtime-cache-clone] <T>(value: T) => T` | - | 値の複製に使用する関数です。既定では structuredClone を使います。 |
| `backend?` | `[#vercel-runtime-cache-backend] VercelRuntimeCacheBackend` | - | 使用するバックエンドです。未指定のときは自動検出し、見つからなければプロセス内の Map にフォールバックします。 |
| `now?` | `[#vercel-runtime-cache-now] () => number` | - | 現在時刻を返す関数です。テストで時刻を固定するときに使います。 |

以下は、値を保存して読み戻す例です。

```ts
import { VercelRuntimeCache } from "@unikvs/vercel-runtime-cache";
import * as unikvs from "unikvs";

const kvs = new unikvs.Builder<{
  foo: unikvs.Value<string>;
}>()
  .persist(new VercelRuntimeCache())
  .build();

await kvs.open();
await kvs.set("foo", "hello");

const data = await kvs.get("foo");
console.log(data); // "hello"

await kvs.close();
```

## データ型 [#data-types]

| 操作                                    | 対応するデータ型                     |
| --------------------------------------- | ------------------------------------ |
| `write`・`read`                         | 任意の値（文字列・オブジェクトなど） |
| `getWritable`・`getReadable` のチャンク | `Uint8Array<ArrayBuffer>`            |

- 任意の値を保存できます。既定では `structuredClone` で複製するので、`structuredClone` で複製できる値を扱います。
- 期限切れのエントリは存在しないものとして扱い、読み取り時に掃除します。
- `getWritable` で取得したストリームは、`Uint8Array<ArrayBuffer>` のチャンクを蓄積し、`close` 時にまとめて保存します。
- `getReadable` は保存値が `Uint8Array<ArrayBuffer>` の場合のみ使えます。

## エラー [#errors]

このパッケージが投げるエラーは次のとおりです。

### InvalidTtlSecondsError [#error-invalid-ttl-seconds]

#### 意味

`ttlSeconds` が 0 より大きい有限数ではないときに、構築時に投げます。

#### 対処方法

`ttlSeconds` には 0 より大きい有限数を指定します。

### InvalidMaxEntriesError [#error-invalid-max-entries]

#### 意味

`maxEntries` が 0 以上の整数ではないときに、構築時に投げます。

#### 対処方法

`maxEntries` には 0 以上の整数を指定します。

### InvalidNamespaceError [#error-invalid-namespace]

#### 意味

`namespace` が文字列ではないときに、構築時に投げます。

#### 対処方法

`namespace` には文字列を指定します。

### InvalidChunkTypeError [#error-invalid-chunk-type]

#### 意味

`getWritable` で取得したストリームに `Uint8Array<ArrayBuffer>` 以外のチャンクを書き込んだとき、または `getReadable` の対象値が `Uint8Array<ArrayBuffer>` ではないときに投げます。

#### 対処方法

ストリームで扱う値は `Uint8Array<ArrayBuffer>` にします。

### KeyNotFoundError [#error-key-not-found]

#### 意味

指定したキーが存在しないとき、または期限切れのときに `read`・`delete` が投げます。`@unikvs/core` の共通エラーです。

#### 対処方法

`exists` で確認してから読み出します。

#### 例

以下は、`KeyNotFoundError` を捕捉する例です。

```ts
import { KeyNotFoundError } from "@unikvs/vercel-runtime-cache";

try {
  const data = await kvs.get("missing-key");
} catch (ex) {
  if (ex instanceof KeyNotFoundError) {
    console.log("キーが見つかりません");
  } else {
    throw ex;
  }
}
```
