@unikvs/ttl
相対秒数や絶対時刻で TTL を付与し、期限切れを欠落として扱うミドルウェアです。
概要
Ttl は書き込んだ値に相対秒数や絶対時刻の有効期限を付与し、期限切れの読み取りを欠落として扱います。Middleware
短命なキャッシュやセッション的なデータの保持に使います。プレーン値とストリームで失効の管理方式が異なります。
nameはTtlです。isOpenは常にtrueです。- 期限の指定は操作ごとの変数
@unikvs/ttl:ttl・@unikvs/ttl:expiresAt(非名前空間名ttl・expiresAtも後方互換で受付) と、既定値defaultTtlで行います。 - 期限切れの
get・has・stream・copy・moveはKeyNotFoundError相当として扱います。 copyとmoveは、このミドルウェアが適用された分岐で TTL の対象となるすべての宛先がcommittedになったときに限り、コピー元・移動元の有効期限をコピー先・移動先へ引き継ぎます。
インストールは次のコマンドで行います。
npm install @unikvs/ttlpnpm add @unikvs/ttlyarn add @unikvs/ttlbun add @unikvs/ttlnub add @unikvs/ttlaube add @unikvs/ttl使い方
Ttl は IMiddleware を実装しています。UniKvs には use() で渡します。
import { Ttl } from "@unikvs/ttl";
コンストラクターの引数は次のとおりです。
defaultTtl?TtlInput
書き込みごとの指定がないときに使う既定の TTL です。相対秒数、絶対時刻、オブジェクト形式のいずれも指定できます。
TtlInputnow?() => number
現在時刻 (epoch ミリ秒) を返す関数です。テストで時刻を固定するときに使います。
() => numberDate.now以下は、既定の TTL を 60 秒に設定し、書き込みごとに上書きする例です。
import { Memory } from "@unikvs/memory";
import { Ttl } from "@unikvs/ttl";
import * as unikvs from "unikvs";
const kvs = new unikvs.Builder<{ report: unikvs.PlainValue<string> }>()
.use(new Ttl({ defaultTtl: 60 }))
.persist(new Memory())
.build();
await kvs.open();
await kvs.set("report", "hello");
await kvs.set("short", "bye", { vars: { "@unikvs/ttl:ttl": 10 } });
console.log(await kvs.get("report")); // "hello"
await kvs.close();
Ttl
有効期限エンベロープと操作内記録で失効を管理するミドルウェアです。読み取り前に失効を判定し、存在確認では存在しないものとして扱います。
TtlOptions
Ttl のコンストラクターが受け取るオプションです。既定の TTL と時刻取得を指定します。
TtlInput
書き込みごとに指定できる TTL 値です。number は相対秒数 (小数も可、0 以下は即時失効)、Date は絶対失効時刻、オブジェクト形式では ttl に相対秒数、expiresAt に epoch ミリ秒または Date を指定します。
データ型
| メソッド | 入力 | 出力 |
|---|---|---|
encode |
unknown |
エンベロープか透過 |
decode |
エンベロープか任意値 | unknown |
encodeStream |
unknown (チャンク) |
unknown (チャンク、透過) |
decodeStream |
unknown (チャンク) |
unknown (チャンク、透過) |
encodeは TTL があるときに{ "@unikvs/ttl": 1, expiresAt: number, data: unknown }の形に包みます。TTL がない上書きではデータを透過させます。decodeは期限内であれば包みを剥がして元の値を返し、期限切れではKeyNotFoundErrorを投げます。再起動後などで記録が欠けているときはエンベロープから記録を復元します。- ストリームはチャンクの型制約に合わせるため帯域内に期限を埋め込まず、記録だけで管理します。
encodeStreamとdecodeStreamはデータを透過します。 - TTL の解決は
ttl変数を優先し、次にexpiresAt変数、最後にdefaultTtlを使います。名前空間付き変数が非名前空間名より優先されます。
記録の確定タイミング
このミドルウェアはストレージの成否を afterUse で受け取り、記録を確定します。use・encode・encodeStream の時点では記録を変更せず、操作内の変数に確定待ちの値を保存します。そのため、書き込みに失敗したときに、存在しない値へ期限だけが付くことはありません。afterUse に渡される宛先は、このミドルウェアが適用された分岐のものだけです。
setはすべての宛先が確定したときに、保存した期限を記録へ反映します。TTL なしの上書きでは記録を消します。失敗したときは以前の記録を残します。copyは、このミドルウェアが適用された分岐で TTL の対象となるすべての宛先がcommittedになったときに、コピー元の期限をコピー先へ引き継ぎます。コピー元に記録がなければコピー先の記録を消します。一部でもnotFoundやfailedがある場合は、コピー先の記録を変更しません。moveは、このミドルウェアが適用された分岐で TTL の対象となるすべての宛先がcommittedになったときに、移動先の記録を更新して移動元の記録を消します。一部でもnotFoundやfailedがある場合は、移動元の記録を残し、移動先の記録は変更しません。- ストレージの確定後に操作が中断された場合でも、このミドルウェアが適用された分岐で TTL の対象となるすべての宛先が
committedなら、その結果を記録へ反映します。未確定の宛先があれば、失敗時と同じく記録を変更しません。 - コピー元・移動元の期限は
useの時点で固定せず、転送完了後のafterUse(キーロック保持中) に記録から読み直します。useの後に並行するsetが期限を更新した場合も、その現在の期限を引き継ぎます。 deleteとclearは成功したときだけ記録を消します。部分成功では残っている値の期限を失わないよう、記録を残します。- 期限切れのコピー元・移動元は
KeyNotFoundErrorになりますが、記録は残します。ストリームは帯域内に期限を持たないため、失敗したコピー・移動の後でも失効を判定できます。成功したsetは記録を新しい期限で置き換え (TTL なしなら削除し)、成功したdelete・clearは記録を消します。 decodeStreamが期限切れを検出しても記録は残します。同じキーへのdecodeStreamは引き続きKeyNotFoundErrorになります。get・streamのrepairによる書き戻しは読み取りの一部として扱われ、afterUseは呼ばれません。そのため、書き戻し先のストレージには期限エンベロープを持たないストリームの記録が読み取り側のインスタンスに確定されません。
エラー
このパッケージが投げるエラーは次のとおりです。
TtlInvalidValueError
actualunknown
指定された TTL の値です。
unknown意味
TTL 値が相対秒数・絶対時刻・オブジェクト形式のいずれとしても解釈できないときに、このエラーが投げられます。コンストラクターの defaultTtl と書き込みごとの変数の両方が検証対象です。
対処方法
有限の数値 (相対秒数)、Date、または { ttl } や { expiresAt } の形のオブジェクトを指定してください。文字列や非有限値は受け付けません。
例
以下は、TtlInvalidValueError を捕捉する例です。
import { TtlInvalidValueError } from "@unikvs/ttl";
try {
await kvs.set("report", "hello", { vars: { ttl: "60" } });
} catch (ex) {
if (ex instanceof TtlInvalidValueError) {
console.log(ex.meta); // { actual: "60" }
} else {
throw ex;
}
}
期限切れの読み取りは @unikvs/core の KeyNotFoundError として失敗します。詳細はエラーを参照してください。