@unikvs/soft-delete
削除を復元可能な墓標として保持する @unikvs/soft-delete の使い方を説明します。
概要
@unikvs/soft-delete は削除されたデータを復元可能な墓標 (tombstone) として保持するラッパーです。
このラッパーは delete を物理削除ではなく同じキーへの墓標書き込みとして処理し、restore で値を戻せるようにします。墓標と台帳は委譲先のストレージに保存されるため、複製先にも複製されます。
nameはSoftDeleteです。isOpenは委譲先のストレージに従います。retentionMsを指定すると、保持期限を過ぎた墓標は掃除されます。- ストリームの対応有無とチャンク型は委譲先のストレージに従います。
- 変更操作はキーごとに直列化され、異なるキーの操作は並行して進みます。対象は
write・delete・restore・purge・listTombstones、期限切れの墓標を検出したときの掃除、ストリームの close 時の台帳の掃除です。read・exists・getReadableは、期限切れの墓標を掃除する場合を除いてキーごとのロックを取りません。台帳の更新は同一インスタンス内でキーをまたいで直列化されます。同じ委譲先ストレージを共有する複数のインスタンスでは、台帳を更新し得る操作が競合するため、これらの操作は 1 つのインスタンスに集約してください。
インストールは次のコマンドで行います。
npm install @unikvs/soft-deletepnpm add @unikvs/soft-deleteyarn add @unikvs/soft-deletebun add @unikvs/soft-deletenub add @unikvs/soft-deleteaube add @unikvs/soft-delete使い方
SoftDelete は IStorage を実装しています。UniKvs には persist() で渡します。
import { SoftDelete } from "@unikvs/soft-delete";
SoftDelete
削除されたデータを復元可能な墓標として保持するラッパーです。
コンストラクターの引数は次のとおりです。委譲先の storage を第一引数に渡します。
storageIStorage
削除墓標の実体を保持する委譲先のストレージです。
IStorageretentionMs?number
削除墓標を保持する期間 (ミリ秒) です。未指定なら保持し続けます。
number以下は、削除した値を復元する例です。
import { Memory } from "@unikvs/memory";
import { SoftDelete } from "@unikvs/soft-delete";
import * as unikvs from "unikvs";
const softDelete = new SoftDelete(new Memory());
const kvs = new unikvs.Builder<{
foo: unikvs.Value<Uint8Array>;
}>()
.persist(softDelete)
.build();
await kvs.open();
await kvs.set("foo", new Uint8Array([0, 1, 2]));
await kvs.delete("foo"); // 墓標として残ります
console.log(await kvs.has("foo")); // false
await softDelete.restore("foo");
console.log(await kvs.has("foo")); // true
await kvs.close();
ミドルウェアとしても使えます。use() に渡すと、このミドルウェアは墓標が読み出し経路へ紛れ込んだときは存在しないキーとして扱います。
以下は、ミドルウェアとして使う例です。
import { Memory } from "@unikvs/memory";
import { SoftDelete } from "@unikvs/soft-delete";
import * as unikvs from "unikvs";
const inner = new Memory();
const kvs = new unikvs.Builder<{
foo: unikvs.Value<Uint8Array>;
}>()
.use(new SoftDelete(inner))
.persist(inner)
.build();
データ型
| 操作 | 対応するデータ型 |
|---|---|
write・read |
任意の値(文字列・オブジェクトなど) |
getWritable・getReadable のチャンク |
委譲先のストレージに従います |
- 任意の値を保存できます。墓標は内部形式のレコードとして同じキーに保存します。
- 墓標と台帳は委譲先のストレージに保存されます。台帳には予約キー
__unikvs_soft_delete_registry__を使います。 - ストリームの対応有無とチャンク型は委譲先のストレージに従います。対応しないときは取得関数が未定義のままです。
- ミドルウェアとしては透過します。墓標が読み出し経路へ紛れ込んだときは、このミドルウェアは
KeyNotFoundErrorを投げます。 purge(key)は墓標を消したときtrueを返し、この呼び出しで墓標を消せなかったときはfalseを返します。falseは墓標がない場合だけでなく、復元済みや新しい墓標への置き換えによって対象の墓標が残っていない場合も含みます。キーを省略したpurge()は台帳のスナップショットを対象に墓標を消し、実行中に他の操作が競合しても、実際に消せた件数を返します。
エラー
このパッケージが投げるエラーは次のとおりです。
TombstoneNotFoundError
意味
復元の対象に墓標がないとき、または墓標が保持期限を過ぎているときに restore が投げます。
purge(key) は墓標がないときでもこのエラーを投げず、この呼び出しで墓標を消せなかったことを示す false を返します。保持期限を過ぎた墓標も purge(key) の対象で、削除できたときは true を返します。
対処方法
listTombstones で墓標の一覧を確認してから操作します。purge(key) の false はこの呼び出しで墓標を消せなかったことを示し、墓標が存在しないことを意味するとは限りません。復元できないこととは区別して扱います。
SoftDeleteInvalidRetentionError
意味
retentionMs が 0 以上の有限数ではないときに、構築時に投げます。
対処方法
retentionMs には 0 以上の有限数 (ミリ秒) を指定するか、未指定にします。
KeyNotFoundError
意味
墓標だけが残るキーや存在しないキーを読み出したときに投げます。@unikvs/core の共通エラーです。
対処方法
exists で確認してから読み出します。削除済みの値が必要なときは restore を使います。
例
以下は、KeyNotFoundError を捕捉する例です。
import { KeyNotFoundError } from "@unikvs/soft-delete";
try {
const data = await kvs.get("missing-key");
} catch (ex) {
if (ex instanceof KeyNotFoundError) {
console.log("キーが見つかりません");
} else {
throw ex;
}
}