unikvs 0.0.10 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/index.d.ts +1553 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4032 -0
- package/dist/index.js.map +1 -0
- package/package.json +35 -34
- package/src/_contexts.ts +1089 -0
- package/src/_logger.ts +5 -3
- package/src/_middleware.ts +207 -0
- package/src/_pipeline-graph.helpers.ts +183 -0
- package/src/_pipeline-graph.ts +1307 -0
- package/src/_pipeline-graph.types.ts +303 -0
- package/src/_pipeline-leaf-resolver.ts +70 -0
- package/src/_plugin-lifecycle.ts +201 -0
- package/src/_storage.ts +173 -96
- package/src/_streams.schemas.ts +21 -0
- package/src/_streams.ts +73 -0
- package/src/_to-value-stream.ts +22 -11
- package/src/_types.ts +237 -0
- package/src/_unikvs-branch.ts +94 -0
- package/src/_unikvs.schemas.ts +451 -0
- package/src/_valibot.ts +17 -3
- package/src/_value-schemas.ts +192 -0
- package/src/_value-validation.ts +57 -0
- package/src/errors.ts +446 -252
- package/src/index.ts +46 -26
- package/src/types.ts +13 -0
- package/src/unikvs-branch.ts +445 -0
- package/src/unikvs-builder.ts +706 -0
- package/src/unikvs.ts +1456 -971
- package/src/unikvs.types.ts +194 -0
- package/src/value-schemas.ts +98 -0
- package/dist/src/_logger.d.ts +0 -3
- package/dist/src/_logger.d.ts.map +0 -1
- package/dist/src/_logger.js +0 -3
- package/dist/src/_merge-context.d.ts +0 -13
- package/dist/src/_merge-context.d.ts.map +0 -1
- package/dist/src/_merge-context.js +0 -12
- package/dist/src/_storage.d.ts +0 -18
- package/dist/src/_storage.d.ts.map +0 -1
- package/dist/src/_storage.js +0 -94
- package/dist/src/_to-value-stream.d.ts +0 -12
- package/dist/src/_to-value-stream.d.ts.map +0 -1
- package/dist/src/_to-value-stream.js +0 -102
- package/dist/src/_transformer.d.ts +0 -13
- package/dist/src/_transformer.d.ts.map +0 -1
- package/dist/src/_transformer.js +0 -60
- package/dist/src/_valibot.d.ts +0 -15
- package/dist/src/_valibot.d.ts.map +0 -1
- package/dist/src/_valibot.js +0 -23
- package/dist/src/context.types.d.ts +0 -17
- package/dist/src/context.types.d.ts.map +0 -1
- package/dist/src/context.types.js +0 -1
- package/dist/src/errors.d.ts +0 -340
- package/dist/src/errors.d.ts.map +0 -1
- package/dist/src/errors.js +0 -250
- package/dist/src/index.d.ts +0 -10
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -3
- package/dist/src/unikvs-config.d.ts +0 -255
- package/dist/src/unikvs-config.d.ts.map +0 -1
- package/dist/src/unikvs-config.js +0 -105
- package/dist/src/unikvs.d.ts +0 -354
- package/dist/src/unikvs.d.ts.map +0 -1
- package/dist/src/unikvs.js +0 -867
- package/dist/src/utils.types.d.ts +0 -7
- package/dist/src/utils.types.d.ts.map +0 -1
- package/dist/src/utils.types.js +0 -1
- package/dist/src/value-stream.types.d.ts +0 -16
- package/dist/src/value-stream.types.d.ts.map +0 -1
- package/dist/src/value-stream.types.js +0 -1
- package/src/_merge-context.ts +0 -19
- package/src/_transformer.ts +0 -89
- package/src/context.types.ts +0 -19
- package/src/unikvs-config.ts +0 -426
- package/src/utils.types.ts +0 -6
- package/src/value-stream.types.ts +0 -19
package/dist/src/unikvs.js
DELETED
|
@@ -1,867 +0,0 @@
|
|
|
1
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
-
};
|
|
7
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
-
};
|
|
12
|
-
var _UniKvs_instances, _UniKvs_con, _UniKvs_acSet, _UniKvs_context, _UniKvs_destinations, _UniKvs_transformers, _UniKvs_close;
|
|
13
|
-
import { combineSignals } from "abort-signal-utils";
|
|
14
|
-
import { asyncmux, Asyncmux } from "asyncmux";
|
|
15
|
-
import logger from "./_logger.js";
|
|
16
|
-
import mergeContext from "./_merge-context.js";
|
|
17
|
-
import toValueStream from "./_to-value-stream.js";
|
|
18
|
-
import * as v from "./_valibot.js";
|
|
19
|
-
import { KeyNotFoundError, UniKvsIsOpenError, PluginOperationAggregateError, UniKvsIsNotOpenError, } from "./errors.js";
|
|
20
|
-
import UniKvsConfig from "./unikvs-config.js";
|
|
21
|
-
// -------------------------------------------------------------------------------------------------
|
|
22
|
-
//
|
|
23
|
-
// スキーマ
|
|
24
|
-
//
|
|
25
|
-
// -------------------------------------------------------------------------------------------------
|
|
26
|
-
const ContextKeySchema = v.string();
|
|
27
|
-
// 配列形式の context も正当な入力であるため、record スキーマより先に判定する必要があります。
|
|
28
|
-
// record スキーマは配列にもマッチして数値キーのオブジェクトに変換してしまうため、配列形式を先に処理しないと mergeContext での配列としてのマージが行われません。
|
|
29
|
-
const ContextSourceSchema = v.union([
|
|
30
|
-
v.array(v.tuple([ContextKeySchema, v.unknown()])),
|
|
31
|
-
v.record(v.any(), v.unknown()),
|
|
32
|
-
]);
|
|
33
|
-
const OpenOptionsSchema = v.object({
|
|
34
|
-
/**
|
|
35
|
-
* 処理の中断を通知するためのシグナルです。
|
|
36
|
-
*/
|
|
37
|
-
signal: v.optional(v.instance(AbortSignal)),
|
|
38
|
-
/**
|
|
39
|
-
* 実行時のコンテキスト情報です。
|
|
40
|
-
*/
|
|
41
|
-
context: v.optional(ContextSourceSchema),
|
|
42
|
-
});
|
|
43
|
-
const OpenArgsSchema = v.tuple([v.optional(OpenOptionsSchema)]);
|
|
44
|
-
const CloseOptionsSchema = v.object({
|
|
45
|
-
/**
|
|
46
|
-
* 処理の中断を通知するためのシグナルです。
|
|
47
|
-
*/
|
|
48
|
-
signal: v.optional(v.instance(AbortSignal)),
|
|
49
|
-
/**
|
|
50
|
-
* 実行時のコンテキスト情報です。
|
|
51
|
-
*/
|
|
52
|
-
context: v.optional(ContextSourceSchema),
|
|
53
|
-
});
|
|
54
|
-
const CloseArgsSchema = v.tuple([v.optional(CloseOptionsSchema)]);
|
|
55
|
-
const SetOptionsSchema = v.object({
|
|
56
|
-
key: v.string(),
|
|
57
|
-
value: v.unknown(),
|
|
58
|
-
signal: v.optional(v.instance(AbortSignal)),
|
|
59
|
-
context: v.optional(ContextSourceSchema),
|
|
60
|
-
});
|
|
61
|
-
const SetArgsSchema = v.union([
|
|
62
|
-
v.tuple([SetOptionsSchema]),
|
|
63
|
-
v.pipe(v.tuple([
|
|
64
|
-
SetOptionsSchema.entries.key,
|
|
65
|
-
SetOptionsSchema.entries.value,
|
|
66
|
-
v.optional(v.omit(SetOptionsSchema, ["key", "value"])),
|
|
67
|
-
]), v.transform(([key, value, options]) => [{ ...options, key, value }])),
|
|
68
|
-
]);
|
|
69
|
-
const GetOptionsSchema = v.object({
|
|
70
|
-
key: v.string(),
|
|
71
|
-
signal: v.optional(v.instance(AbortSignal)),
|
|
72
|
-
context: v.optional(ContextSourceSchema),
|
|
73
|
-
});
|
|
74
|
-
const GetArgsSchema = v.union([
|
|
75
|
-
v.tuple([GetOptionsSchema]),
|
|
76
|
-
v.pipe(v.tuple([GetOptionsSchema.entries.key, v.optional(v.omit(GetOptionsSchema, ["key"]))]), v.transform(([key, options]) => [{ ...options, key }])),
|
|
77
|
-
]);
|
|
78
|
-
const StreamOptionsSchema = v.object({
|
|
79
|
-
key: v.string(),
|
|
80
|
-
signal: v.optional(v.instance(AbortSignal)),
|
|
81
|
-
context: v.optional(ContextSourceSchema),
|
|
82
|
-
});
|
|
83
|
-
const StreamArgsSchema = v.union([
|
|
84
|
-
v.tuple([StreamOptionsSchema]),
|
|
85
|
-
v.pipe(v.tuple([StreamOptionsSchema.entries.key, v.optional(v.omit(StreamOptionsSchema, ["key"]))]), v.transform(([key, options]) => [{ ...options, key }])),
|
|
86
|
-
]);
|
|
87
|
-
const HasOptionsSchema = v.object({
|
|
88
|
-
key: v.string(),
|
|
89
|
-
signal: v.optional(v.instance(AbortSignal)),
|
|
90
|
-
context: v.optional(ContextSourceSchema),
|
|
91
|
-
});
|
|
92
|
-
const HasArgsSchema = v.union([
|
|
93
|
-
v.tuple([HasOptionsSchema]),
|
|
94
|
-
v.pipe(v.tuple([HasOptionsSchema.entries.key, v.optional(v.omit(HasOptionsSchema, ["key"]))]), v.transform(([key, options]) => [{ ...options, key }])),
|
|
95
|
-
]);
|
|
96
|
-
const DeleteOptionsSchema = v.object({
|
|
97
|
-
key: v.string(),
|
|
98
|
-
signal: v.optional(v.instance(AbortSignal)),
|
|
99
|
-
context: v.optional(ContextSourceSchema),
|
|
100
|
-
});
|
|
101
|
-
const DeleteArgsSchema = v.union([
|
|
102
|
-
v.tuple([DeleteOptionsSchema]),
|
|
103
|
-
v.pipe(v.tuple([DeleteOptionsSchema.entries.key, v.optional(v.omit(DeleteOptionsSchema, ["key"]))]), v.transform(([key, options]) => [{ ...options, key }])),
|
|
104
|
-
]);
|
|
105
|
-
const ClearOptionsSchema = v.object({
|
|
106
|
-
/**
|
|
107
|
-
* 処理の中断を通知するためのシグナルです。
|
|
108
|
-
*/
|
|
109
|
-
signal: v.optional(v.instance(AbortSignal)),
|
|
110
|
-
/**
|
|
111
|
-
* 実行時のコンテキスト情報です。
|
|
112
|
-
*/
|
|
113
|
-
context: v.optional(ContextSourceSchema),
|
|
114
|
-
});
|
|
115
|
-
const ClearArgsSchema = v.tuple([v.optional(ClearOptionsSchema)]);
|
|
116
|
-
// -------------------------------------------------------------------------------------------------
|
|
117
|
-
//
|
|
118
|
-
// UniKvs
|
|
119
|
-
//
|
|
120
|
-
// -------------------------------------------------------------------------------------------------
|
|
121
|
-
/**
|
|
122
|
-
* ストリームの読み取りロックを自動解放するための FinalizationRegistry です。
|
|
123
|
-
*/
|
|
124
|
-
const ioLockRegistry = typeof FinalizationRegistry !== "function"
|
|
125
|
-
? null
|
|
126
|
-
: new FinalizationRegistry((held) => {
|
|
127
|
-
if (!held.lock.released) {
|
|
128
|
-
held.lock.release();
|
|
129
|
-
}
|
|
130
|
-
// valueStream が読み取られないまま GC されたとき、ソースストリームが保持するリソース (S3 レスポンスボディなど) を解放するために破棄します。
|
|
131
|
-
// dispose は valueStream 自身を参照しないため、これを保持しても valueStream のガベージコレクションを妨げません。
|
|
132
|
-
// 失敗しても対処できないので無視します。
|
|
133
|
-
held.dispose().catch((ex) => {
|
|
134
|
-
logger.error `Failed to dispose value stream: ${ex}`;
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
/**
|
|
138
|
-
* UniKvs メインクラスです。
|
|
139
|
-
*
|
|
140
|
-
* 複数のストレージとトランスフォーマーを統合して KVS 操作を提供します。
|
|
141
|
-
*
|
|
142
|
-
* @template TKeyValueMapping キーと値のマッピング定義です。
|
|
143
|
-
*/
|
|
144
|
-
export default class UniKvs {
|
|
145
|
-
/**
|
|
146
|
-
* UniKvs の設定ビルダーを作成します。
|
|
147
|
-
*
|
|
148
|
-
* @template TKeyValueMapping マッピング定義です。
|
|
149
|
-
* @returns 設定ビルダーのインスタンスです。
|
|
150
|
-
* @example
|
|
151
|
-
* ```typescript
|
|
152
|
-
* import { Compression } from "@unikvs/compression";
|
|
153
|
-
* import { FileSystem } from "@unikvs/fs.node";
|
|
154
|
-
* import { UniKvs, type Value } from "unikvs";
|
|
155
|
-
*
|
|
156
|
-
* const kvs = UniKvs.config<{
|
|
157
|
-
* foo: Value<Uint8Array<ArrayBuffer>>;
|
|
158
|
-
* }>()
|
|
159
|
-
* .appendTransformer(new Compression("gzip"))
|
|
160
|
-
* .appendStorage(new FileSystem(".tmp"))
|
|
161
|
-
* .create();
|
|
162
|
-
*
|
|
163
|
-
* await kvs.open();
|
|
164
|
-
*
|
|
165
|
-
* await kvs.set("foo", Uint8Array.from([0, 1, 2]));
|
|
166
|
-
*
|
|
167
|
-
* await kvs.close();
|
|
168
|
-
* ```
|
|
169
|
-
*/
|
|
170
|
-
static config() {
|
|
171
|
-
return new UniKvsConfig(this);
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* インスタンスを初期化します。
|
|
175
|
-
*
|
|
176
|
-
* @internal UniKvs の設定ビルダー経由で使用します。
|
|
177
|
-
* @param context コンテキストです。
|
|
178
|
-
* @param destinations ストレージのリストです。
|
|
179
|
-
* @param transformers トランスフォーマーのリストです。
|
|
180
|
-
*/
|
|
181
|
-
constructor(context, destinations, transformers) {
|
|
182
|
-
_UniKvs_instances.add(this);
|
|
183
|
-
/**
|
|
184
|
-
* 現在の接続状態です。非接続時は null となります。
|
|
185
|
-
*/
|
|
186
|
-
_UniKvs_con.set(this, void 0);
|
|
187
|
-
_UniKvs_acSet.set(this, void 0);
|
|
188
|
-
/**
|
|
189
|
-
* 基本となる実行コンテキスト情報です。
|
|
190
|
-
*/
|
|
191
|
-
_UniKvs_context.set(this, void 0);
|
|
192
|
-
/**
|
|
193
|
-
* データの永続化先となるストレージのリストです。
|
|
194
|
-
*/
|
|
195
|
-
_UniKvs_destinations.set(this, void 0);
|
|
196
|
-
/**
|
|
197
|
-
* データの変換を行うトランスフォーマーのリストです。
|
|
198
|
-
*/
|
|
199
|
-
_UniKvs_transformers.set(this, void 0);
|
|
200
|
-
__classPrivateFieldSet(this, _UniKvs_con, null, "f");
|
|
201
|
-
__classPrivateFieldSet(this, _UniKvs_acSet, new Set(), "f");
|
|
202
|
-
__classPrivateFieldSet(this, _UniKvs_context, { ...context }, "f");
|
|
203
|
-
__classPrivateFieldSet(this, _UniKvs_destinations, destinations, "f");
|
|
204
|
-
__classPrivateFieldSet(this, _UniKvs_transformers, transformers, "f");
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* UniKvs が利用可能であるかを確認します。
|
|
208
|
-
*
|
|
209
|
-
* @returns 利用可能である場合は true、そうでない場合は false を返します。
|
|
210
|
-
*/
|
|
211
|
-
get isOpen() {
|
|
212
|
-
return __classPrivateFieldGet(this, _UniKvs_con, "f") !== null;
|
|
213
|
-
}
|
|
214
|
-
async open(...args) {
|
|
215
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") !== null) {
|
|
216
|
-
throw new UniKvsIsOpenError();
|
|
217
|
-
}
|
|
218
|
-
const [options = {}] = v.parseInput(OpenArgsSchema, args);
|
|
219
|
-
const { signal: signalOption, context: contextOption } = options;
|
|
220
|
-
const ac = new AbortController();
|
|
221
|
-
const signal = combineSignals([ac.signal, signalOption]);
|
|
222
|
-
const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
|
|
223
|
-
context["unikvs:action"] = "open";
|
|
224
|
-
signal.throwIfAborted();
|
|
225
|
-
__classPrivateFieldGet(this, _UniKvs_acSet, "f").add(ac);
|
|
226
|
-
const dispose = [];
|
|
227
|
-
const lock = await asyncmux(this, signal);
|
|
228
|
-
try {
|
|
229
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") !== null) {
|
|
230
|
-
throw new UniKvsIsOpenError();
|
|
231
|
-
}
|
|
232
|
-
const openFns = [];
|
|
233
|
-
// 各ストレージのオープン処理をリストに追加します。
|
|
234
|
-
for (const storage of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
|
|
235
|
-
openFns.push([
|
|
236
|
-
async () => {
|
|
237
|
-
await storage.open(context, signal);
|
|
238
|
-
dispose.push(async () => {
|
|
239
|
-
try {
|
|
240
|
-
await storage.close(context, signal);
|
|
241
|
-
}
|
|
242
|
-
catch (ex) {
|
|
243
|
-
logger.error `Failed to close storage: ${ex}`;
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
},
|
|
247
|
-
"storage",
|
|
248
|
-
]);
|
|
249
|
-
}
|
|
250
|
-
// 各トランスフォーマーのオープン処理をリストに追加します。
|
|
251
|
-
for (const transformer of __classPrivateFieldGet(this, _UniKvs_transformers, "f")) {
|
|
252
|
-
openFns.push([
|
|
253
|
-
async () => {
|
|
254
|
-
await transformer.open(context, signal);
|
|
255
|
-
dispose.push(async () => {
|
|
256
|
-
try {
|
|
257
|
-
await transformer.close(context, signal);
|
|
258
|
-
}
|
|
259
|
-
catch (ex) {
|
|
260
|
-
logger.error `Failed to close transformer: ${ex}`;
|
|
261
|
-
}
|
|
262
|
-
});
|
|
263
|
-
},
|
|
264
|
-
"transformer",
|
|
265
|
-
]);
|
|
266
|
-
}
|
|
267
|
-
// すべての処理を並列に実行し、エラーが発生した場合は集約します。
|
|
268
|
-
const errors = [];
|
|
269
|
-
await Promise.all(openFns.map(async ([f, plugin]) => {
|
|
270
|
-
try {
|
|
271
|
-
await f();
|
|
272
|
-
}
|
|
273
|
-
catch (reason) {
|
|
274
|
-
errors.push({ plugin, reason });
|
|
275
|
-
}
|
|
276
|
-
}));
|
|
277
|
-
if (errors.length > 0) {
|
|
278
|
-
// 中断以外の失敗が混在しない場合は、abort 理由が集約エラーに埋もれないようにそのまま投げます。
|
|
279
|
-
if (signal.aborted && errors.every((error) => error.reason === signal.reason)) {
|
|
280
|
-
throw signal.reason;
|
|
281
|
-
}
|
|
282
|
-
throw new PluginOperationAggregateError({ action: "open", errors });
|
|
283
|
-
}
|
|
284
|
-
// すべてのプラグインのオープンが成功した後も、待機中に中断されていないか最終確認します。
|
|
285
|
-
// 中断済みのシグナルを持つ接続を作成すると、isOpen が true でありながら以降のすべての操作が即座に失敗する壊れた状態になります。
|
|
286
|
-
signal.throwIfAborted();
|
|
287
|
-
__classPrivateFieldSet(this, _UniKvs_con, {
|
|
288
|
-
ac,
|
|
289
|
-
io: new Asyncmux(),
|
|
290
|
-
}, "f");
|
|
291
|
-
}
|
|
292
|
-
catch (ex) {
|
|
293
|
-
if (dispose.length > 0) {
|
|
294
|
-
await Promise.all(dispose.map(async (f) => {
|
|
295
|
-
await f();
|
|
296
|
-
}));
|
|
297
|
-
}
|
|
298
|
-
throw ex;
|
|
299
|
-
}
|
|
300
|
-
finally {
|
|
301
|
-
__classPrivateFieldGet(this, _UniKvs_acSet, "f").delete(ac);
|
|
302
|
-
lock.release();
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
close(...args) {
|
|
306
|
-
try {
|
|
307
|
-
const [options = {}] = v.parseInput(CloseArgsSchema, args);
|
|
308
|
-
const { signal = AbortSignal.timeout(10e3), context: contextOption } = options;
|
|
309
|
-
const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
|
|
310
|
-
context["unikvs:action"] = "close";
|
|
311
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
|
|
312
|
-
const acArr = [...__classPrivateFieldGet(this, _UniKvs_acSet, "f")];
|
|
313
|
-
__classPrivateFieldGet(this, _UniKvs_acSet, "f").clear();
|
|
314
|
-
for (const ac of acArr) {
|
|
315
|
-
if (!ac.signal.aborted) {
|
|
316
|
-
ac.abort(new UniKvsIsNotOpenError());
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
throw new UniKvsIsNotOpenError();
|
|
320
|
-
}
|
|
321
|
-
const con = __classPrivateFieldGet(this, _UniKvs_con, "f");
|
|
322
|
-
const { ac } = con;
|
|
323
|
-
const acArr = [ac, ...__classPrivateFieldGet(this, _UniKvs_acSet, "f")];
|
|
324
|
-
__classPrivateFieldGet(this, _UniKvs_acSet, "f").clear();
|
|
325
|
-
for (const ac of acArr) {
|
|
326
|
-
if (!ac.signal.aborted) {
|
|
327
|
-
ac.abort(new UniKvsIsNotOpenError());
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
return __classPrivateFieldGet(this, _UniKvs_instances, "m", _UniKvs_close).call(this, context, signal, con).catch(async (ex) => {
|
|
331
|
-
// #close が失敗した場合、コネクションの AbortController は既に abort 済みであり、以降の操作がすべて即座に失敗する壊れた状態になります。
|
|
332
|
-
// そこで接続を破棄して isOpen=false の一貫した状態にし、ベストエフォートでプラグインのクローズ処理を実行します。
|
|
333
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === con) {
|
|
334
|
-
__classPrivateFieldSet(this, _UniKvs_con, null, "f");
|
|
335
|
-
const disposeSignal = AbortSignal.timeout(10e3);
|
|
336
|
-
await Promise.all([...__classPrivateFieldGet(this, _UniKvs_destinations, "f"), ...__classPrivateFieldGet(this, _UniKvs_transformers, "f")].map(async (plugin) => {
|
|
337
|
-
try {
|
|
338
|
-
await plugin.close(context, disposeSignal);
|
|
339
|
-
}
|
|
340
|
-
catch (reason) {
|
|
341
|
-
logger.error `Failed to close plugin after close failure: ${reason}`;
|
|
342
|
-
}
|
|
343
|
-
}));
|
|
344
|
-
}
|
|
345
|
-
throw ex;
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
catch (ex) {
|
|
349
|
-
return Promise.reject(ex);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
/**
|
|
353
|
-
* UniKvs が開いている場合にクローズします。
|
|
354
|
-
*
|
|
355
|
-
* `await using` 構文による自動クローズに使用されます。
|
|
356
|
-
*
|
|
357
|
-
* @returns 完了を通知する Promise です。
|
|
358
|
-
*/
|
|
359
|
-
async [(_UniKvs_con = new WeakMap(), _UniKvs_acSet = new WeakMap(), _UniKvs_context = new WeakMap(), _UniKvs_destinations = new WeakMap(), _UniKvs_transformers = new WeakMap(), _UniKvs_instances = new WeakSet(), _UniKvs_close = async function _UniKvs_close(context, signal, con) {
|
|
360
|
-
const lock = await asyncmux(this, signal);
|
|
361
|
-
try {
|
|
362
|
-
// ロック待機中に接続状態が変更されていないか再確認します。
|
|
363
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") !== con) {
|
|
364
|
-
throw new UniKvsIsNotOpenError();
|
|
365
|
-
}
|
|
366
|
-
const { io } = __classPrivateFieldGet(this, _UniKvs_con, "f");
|
|
367
|
-
const lock = await io.lock({ signal });
|
|
368
|
-
try {
|
|
369
|
-
const closeFns = [];
|
|
370
|
-
// ストレージのクローズ処理を登録します。
|
|
371
|
-
for (const plugin of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
|
|
372
|
-
closeFns.push([
|
|
373
|
-
async () => {
|
|
374
|
-
await plugin.close(context, signal);
|
|
375
|
-
},
|
|
376
|
-
"storage",
|
|
377
|
-
]);
|
|
378
|
-
}
|
|
379
|
-
// トランスフォーマーのクローズ処理を登録します。
|
|
380
|
-
for (const plugin of __classPrivateFieldGet(this, _UniKvs_transformers, "f")) {
|
|
381
|
-
closeFns.push([
|
|
382
|
-
async () => {
|
|
383
|
-
await plugin.close(context, signal);
|
|
384
|
-
},
|
|
385
|
-
"transformer",
|
|
386
|
-
]);
|
|
387
|
-
}
|
|
388
|
-
// すべての処理を並列に実行し、エラーが発生した場合は集約します。
|
|
389
|
-
const errors = [];
|
|
390
|
-
await Promise.all(closeFns.map(async ([f, plugin]) => {
|
|
391
|
-
try {
|
|
392
|
-
await f();
|
|
393
|
-
}
|
|
394
|
-
catch (reason) {
|
|
395
|
-
errors.push({ plugin, reason });
|
|
396
|
-
}
|
|
397
|
-
}));
|
|
398
|
-
if (errors.length > 0) {
|
|
399
|
-
throw new PluginOperationAggregateError({ action: "close", errors });
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
finally {
|
|
403
|
-
lock.release();
|
|
404
|
-
}
|
|
405
|
-
__classPrivateFieldSet(this, _UniKvs_con, null, "f");
|
|
406
|
-
}
|
|
407
|
-
finally {
|
|
408
|
-
lock.release();
|
|
409
|
-
}
|
|
410
|
-
}, Symbol.asyncDispose)]() {
|
|
411
|
-
if (!this.isOpen) {
|
|
412
|
-
return;
|
|
413
|
-
}
|
|
414
|
-
await this.close({
|
|
415
|
-
signal: AbortSignal.timeout(10e3),
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
async set(...args) {
|
|
419
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
|
|
420
|
-
throw new UniKvsIsNotOpenError();
|
|
421
|
-
}
|
|
422
|
-
const [options] = v.parseInput(SetArgsSchema, args);
|
|
423
|
-
const { key, value, signal: signalOption, context: contextOption } = options;
|
|
424
|
-
const { ac, io } = __classPrivateFieldGet(this, _UniKvs_con, "f");
|
|
425
|
-
const signal = combineSignals([ac.signal, signalOption]);
|
|
426
|
-
const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
|
|
427
|
-
context["unikvs:action"] = "set";
|
|
428
|
-
context["unikvs:key"] = key;
|
|
429
|
-
const lock = await asyncmux(this, signal);
|
|
430
|
-
try {
|
|
431
|
-
// ロック待機中に接続状態が変更されていないか再確認します。
|
|
432
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
|
|
433
|
-
throw new UniKvsIsNotOpenError();
|
|
434
|
-
}
|
|
435
|
-
const errors = [];
|
|
436
|
-
const errorStorageSet = new Set();
|
|
437
|
-
if (value instanceof ReadableStream) {
|
|
438
|
-
// 各トランスフォーマーを通してデータをエンコードストリームへ変換します。
|
|
439
|
-
let data = value;
|
|
440
|
-
try {
|
|
441
|
-
for (const transformer of __classPrivateFieldGet(this, _UniKvs_transformers, "f")) {
|
|
442
|
-
const e = await transformer.getEncodable(context, signal);
|
|
443
|
-
data = data.pipeThrough(e);
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
catch (ex) {
|
|
447
|
-
// チェーンの構築中に失敗した場合、パイプが保持するソースストリームのリソースを解放するためにキャンセルします。
|
|
448
|
-
// キャンセルしないとソースストリームはロックされたままリークします。
|
|
449
|
-
try {
|
|
450
|
-
await data.cancel(ex);
|
|
451
|
-
}
|
|
452
|
-
catch {
|
|
453
|
-
// キャンセルに失敗しても元の例外の伝播を優先します。
|
|
454
|
-
}
|
|
455
|
-
throw ex;
|
|
456
|
-
}
|
|
457
|
-
const lock = await io.lock({ key, signal });
|
|
458
|
-
try {
|
|
459
|
-
await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async (storage, i) => {
|
|
460
|
-
// tee ブランチはキャンセルされるまで健康なブランチの読み取り分のチャンクを保持し続けるため、失敗時に放棄したブランチを確実にキャンセルできるよう参照を保持します。
|
|
461
|
-
let branch = null;
|
|
462
|
-
try {
|
|
463
|
-
// 複数のストレージがある場合は、tee メソッドを使用してストリームを分岐させます。
|
|
464
|
-
let r = data;
|
|
465
|
-
if (i !== __classPrivateFieldGet(this, _UniKvs_destinations, "f").length - 1) {
|
|
466
|
-
[r, data] = data.tee();
|
|
467
|
-
}
|
|
468
|
-
branch = r;
|
|
469
|
-
const w = await storage.getWritable(context, signal, key);
|
|
470
|
-
await r.pipeTo(w, { signal });
|
|
471
|
-
}
|
|
472
|
-
catch (reason) {
|
|
473
|
-
if (branch !== null) {
|
|
474
|
-
try {
|
|
475
|
-
await branch.cancel(reason);
|
|
476
|
-
}
|
|
477
|
-
catch {
|
|
478
|
-
// キャンセルに失敗してもエラー集約を優先します。
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
errors.push({ reason });
|
|
482
|
-
errorStorageSet.add(storage);
|
|
483
|
-
}
|
|
484
|
-
}));
|
|
485
|
-
}
|
|
486
|
-
finally {
|
|
487
|
-
lock.release();
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
else {
|
|
491
|
-
// 登録されているトランスフォーマーを順番に適用してデータをエンコードします。
|
|
492
|
-
let data = value;
|
|
493
|
-
for (const transformer of __classPrivateFieldGet(this, _UniKvs_transformers, "f")) {
|
|
494
|
-
data = await transformer.encode(context, signal, data);
|
|
495
|
-
}
|
|
496
|
-
const lock = await io.lock({ key, signal });
|
|
497
|
-
try {
|
|
498
|
-
await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async (storage) => {
|
|
499
|
-
try {
|
|
500
|
-
await storage.write(context, signal, key, data);
|
|
501
|
-
}
|
|
502
|
-
catch (reason) {
|
|
503
|
-
errors.push({ reason });
|
|
504
|
-
errorStorageSet.add(storage);
|
|
505
|
-
}
|
|
506
|
-
}));
|
|
507
|
-
}
|
|
508
|
-
finally {
|
|
509
|
-
lock.release();
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
// エラーが発生した場合は集約します。
|
|
513
|
-
if (errors.length > 0) {
|
|
514
|
-
const error = new PluginOperationAggregateError({
|
|
515
|
-
plugin: "storage",
|
|
516
|
-
action: "write",
|
|
517
|
-
errors,
|
|
518
|
-
});
|
|
519
|
-
{
|
|
520
|
-
const errors = [];
|
|
521
|
-
await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async (storage) => {
|
|
522
|
-
if (errorStorageSet.has(storage)) {
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
try {
|
|
526
|
-
await storage.onOtherWriteError(context, signal, key, error);
|
|
527
|
-
}
|
|
528
|
-
catch (ex) {
|
|
529
|
-
errors.push(ex);
|
|
530
|
-
}
|
|
531
|
-
}));
|
|
532
|
-
if (errors.length > 0) {
|
|
533
|
-
logger.error(new AggregateError(errors, "Failed to handle error"));
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
throw error;
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
finally {
|
|
540
|
-
lock.release();
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
async get(...args) {
|
|
544
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
|
|
545
|
-
throw new UniKvsIsNotOpenError();
|
|
546
|
-
}
|
|
547
|
-
const [options] = v.parseInput(GetArgsSchema, args);
|
|
548
|
-
const { key, signal: signalOption, context: contextOption } = options;
|
|
549
|
-
const { ac, io } = __classPrivateFieldGet(this, _UniKvs_con, "f");
|
|
550
|
-
const signal = combineSignals([ac.signal, signalOption]);
|
|
551
|
-
const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
|
|
552
|
-
context["unikvs:action"] = "get";
|
|
553
|
-
context["unikvs:key"] = key;
|
|
554
|
-
const lock = await asyncmux.readonly(this, signal);
|
|
555
|
-
try {
|
|
556
|
-
// ロック待機中に接続状態が変更されていないか再確認します。
|
|
557
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
|
|
558
|
-
throw new UniKvsIsNotOpenError();
|
|
559
|
-
}
|
|
560
|
-
const NONE = {};
|
|
561
|
-
let data = NONE;
|
|
562
|
-
const errors = [];
|
|
563
|
-
const lock = await io.rLock({ key, signal });
|
|
564
|
-
try {
|
|
565
|
-
// 各ストレージを巡回し、最初に見つかったデータを取得します。
|
|
566
|
-
// あるストレージの読み取りに失敗しても、他のストレージからデータを取得できるようにフォールバックします。
|
|
567
|
-
for (const storage of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
|
|
568
|
-
try {
|
|
569
|
-
if (!(await storage.exists(context, signal, key))) {
|
|
570
|
-
continue;
|
|
571
|
-
}
|
|
572
|
-
data = await storage.read(context, signal, key);
|
|
573
|
-
break;
|
|
574
|
-
}
|
|
575
|
-
catch (ex) {
|
|
576
|
-
if (signal.aborted) {
|
|
577
|
-
throw ex;
|
|
578
|
-
}
|
|
579
|
-
errors.push({ reason: ex });
|
|
580
|
-
logger.error `Failed to read from a storage: ${ex}`;
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
finally {
|
|
585
|
-
lock.release();
|
|
586
|
-
}
|
|
587
|
-
if (data === NONE) {
|
|
588
|
-
const args = { key };
|
|
589
|
-
switch (errors.length) {
|
|
590
|
-
case 0:
|
|
591
|
-
break;
|
|
592
|
-
case 1:
|
|
593
|
-
args.cause = errors[0].reason;
|
|
594
|
-
break;
|
|
595
|
-
default:
|
|
596
|
-
args.cause = new PluginOperationAggregateError({
|
|
597
|
-
plugin: "storage",
|
|
598
|
-
action: "read",
|
|
599
|
-
errors,
|
|
600
|
-
});
|
|
601
|
-
}
|
|
602
|
-
throw new KeyNotFoundError(args);
|
|
603
|
-
}
|
|
604
|
-
// トランスフォーマーを逆順に適用してデータをデコードします。
|
|
605
|
-
if (__classPrivateFieldGet(this, _UniKvs_transformers, "f").length > 0) {
|
|
606
|
-
for (const transformer of __classPrivateFieldGet(this, _UniKvs_transformers, "f").toReversed()) {
|
|
607
|
-
data = await transformer.decode(context, signal, data);
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
return data;
|
|
611
|
-
}
|
|
612
|
-
finally {
|
|
613
|
-
lock.release();
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
async stream(...args) {
|
|
617
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
|
|
618
|
-
throw new UniKvsIsNotOpenError();
|
|
619
|
-
}
|
|
620
|
-
const [options] = v.parseInput(StreamArgsSchema, args);
|
|
621
|
-
const { key, signal: signalOption, context: contextOption } = options;
|
|
622
|
-
const { ac, io } = __classPrivateFieldGet(this, _UniKvs_con, "f");
|
|
623
|
-
const signal = combineSignals([ac.signal, signalOption]);
|
|
624
|
-
const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
|
|
625
|
-
context["unikvs:action"] = "stream";
|
|
626
|
-
context["unikvs:key"] = key;
|
|
627
|
-
const lock = await asyncmux.readonly(this, signal);
|
|
628
|
-
try {
|
|
629
|
-
// ロック待機中に接続状態が変更されていないか再確認します。
|
|
630
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
|
|
631
|
-
throw new UniKvsIsNotOpenError();
|
|
632
|
-
}
|
|
633
|
-
const NONE = {};
|
|
634
|
-
let r = NONE;
|
|
635
|
-
const errors = [];
|
|
636
|
-
const lock = await io.rLock({ key, signal });
|
|
637
|
-
try {
|
|
638
|
-
// 各ストレージを巡回し、最初に見つかったデータを取得します。
|
|
639
|
-
// あるストレージの読み取りに失敗しても、他のストレージからデータを取得できるようにフォールバックします。
|
|
640
|
-
for (const storage of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
|
|
641
|
-
try {
|
|
642
|
-
if (!(await storage.exists(context, signal, key))) {
|
|
643
|
-
continue;
|
|
644
|
-
}
|
|
645
|
-
r = await storage.getReadable(context, signal, key);
|
|
646
|
-
break;
|
|
647
|
-
}
|
|
648
|
-
catch (ex) {
|
|
649
|
-
if (signal.aborted) {
|
|
650
|
-
throw ex;
|
|
651
|
-
}
|
|
652
|
-
errors.push({ reason: ex });
|
|
653
|
-
logger.error `Failed to read from a storage: ${ex}`;
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
if (r === NONE) {
|
|
657
|
-
const args = { key };
|
|
658
|
-
switch (errors.length) {
|
|
659
|
-
case 0:
|
|
660
|
-
break;
|
|
661
|
-
case 1:
|
|
662
|
-
args.cause = errors[0].reason;
|
|
663
|
-
break;
|
|
664
|
-
default:
|
|
665
|
-
args.cause = new PluginOperationAggregateError({
|
|
666
|
-
plugin: "storage",
|
|
667
|
-
action: "read",
|
|
668
|
-
errors,
|
|
669
|
-
});
|
|
670
|
-
}
|
|
671
|
-
throw new KeyNotFoundError(args);
|
|
672
|
-
}
|
|
673
|
-
// トランスフォーマーを逆順に適用し、デコード用トランスフォームを連結します。
|
|
674
|
-
for (const transformer of __classPrivateFieldGet(this, _UniKvs_transformers, "f").toReversed()) {
|
|
675
|
-
const d = await transformer.getDecodable(context, signal);
|
|
676
|
-
r = r.pipeThrough(d);
|
|
677
|
-
}
|
|
678
|
-
if (!ioLockRegistry) {
|
|
679
|
-
return toValueStream(r, async () => {
|
|
680
|
-
try {
|
|
681
|
-
lock.release();
|
|
682
|
-
}
|
|
683
|
-
catch { }
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
const unregisterToken = {};
|
|
687
|
-
const valueStream = toValueStream(r, async () => {
|
|
688
|
-
try {
|
|
689
|
-
ioLockRegistry.unregister(unregisterToken);
|
|
690
|
-
}
|
|
691
|
-
catch { }
|
|
692
|
-
try {
|
|
693
|
-
lock.release();
|
|
694
|
-
}
|
|
695
|
-
catch { }
|
|
696
|
-
});
|
|
697
|
-
// valueStream が GC されるタイミングでストリームが終了していなければロックを自動解放するとともに、ソースストリームが保持するリソース (S3 レスポンスボディなど) を解放できるように dispose を記録します。
|
|
698
|
-
ioLockRegistry.register(valueStream, {
|
|
699
|
-
lock,
|
|
700
|
-
dispose: valueStream.dispose,
|
|
701
|
-
}, unregisterToken);
|
|
702
|
-
return valueStream;
|
|
703
|
-
}
|
|
704
|
-
catch (ex) {
|
|
705
|
-
if (r !== NONE) {
|
|
706
|
-
// getReadable 成功後のセットアップ中に失敗した場合、ソースストリームが保持するリソース (S3 レスポンスボディなど) を解放するためにキャンセルします。
|
|
707
|
-
try {
|
|
708
|
-
await r.cancel(ex);
|
|
709
|
-
}
|
|
710
|
-
catch { }
|
|
711
|
-
}
|
|
712
|
-
lock.release();
|
|
713
|
-
throw ex;
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
finally {
|
|
717
|
-
lock.release();
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
async has(...args) {
|
|
721
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
|
|
722
|
-
throw new UniKvsIsNotOpenError();
|
|
723
|
-
}
|
|
724
|
-
const [options] = v.parseInput(HasArgsSchema, args);
|
|
725
|
-
const { key, signal: signalOption, context: contextOption } = options;
|
|
726
|
-
const { ac, io } = __classPrivateFieldGet(this, _UniKvs_con, "f");
|
|
727
|
-
const signal = combineSignals([ac.signal, signalOption]);
|
|
728
|
-
const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
|
|
729
|
-
context["unikvs:action"] = "has";
|
|
730
|
-
context["unikvs:key"] = key;
|
|
731
|
-
const lock = await asyncmux.readonly(this, signal);
|
|
732
|
-
try {
|
|
733
|
-
// ロック待機中に接続状態が変更されていないか再確認します。
|
|
734
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
|
|
735
|
-
throw new UniKvsIsNotOpenError();
|
|
736
|
-
}
|
|
737
|
-
const lock = await io.rLock({ key, signal });
|
|
738
|
-
try {
|
|
739
|
-
// いずれかのストレージに存在すれば true を返します。
|
|
740
|
-
// あるストレージの存在確認に失敗しても、他のストレージで存在を確認できるようにフォールバックします。
|
|
741
|
-
const errors = [];
|
|
742
|
-
for (const storage of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
|
|
743
|
-
try {
|
|
744
|
-
if (await storage.exists(context, signal, key)) {
|
|
745
|
-
return true;
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
catch (ex) {
|
|
749
|
-
if (signal.aborted) {
|
|
750
|
-
throw ex;
|
|
751
|
-
}
|
|
752
|
-
errors.push({ reason: ex });
|
|
753
|
-
logger.error `Failed to check existence in a storage: ${ex}`;
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
// すべてのストレージで存在を確認できなかった場合は結果が不明のため、get() と同様にエラーとして報告します。
|
|
757
|
-
if (errors.length > 0) {
|
|
758
|
-
const args = { key };
|
|
759
|
-
switch (errors.length) {
|
|
760
|
-
case 1:
|
|
761
|
-
args.cause = errors[0].reason;
|
|
762
|
-
break;
|
|
763
|
-
default:
|
|
764
|
-
args.cause = new PluginOperationAggregateError({
|
|
765
|
-
plugin: "storage",
|
|
766
|
-
action: "read",
|
|
767
|
-
errors,
|
|
768
|
-
});
|
|
769
|
-
}
|
|
770
|
-
throw new KeyNotFoundError(args);
|
|
771
|
-
}
|
|
772
|
-
return false;
|
|
773
|
-
}
|
|
774
|
-
finally {
|
|
775
|
-
lock.release();
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
finally {
|
|
779
|
-
lock.release();
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
async delete(...args) {
|
|
783
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
|
|
784
|
-
throw new UniKvsIsNotOpenError();
|
|
785
|
-
}
|
|
786
|
-
const [options] = v.parseInput(DeleteArgsSchema, args);
|
|
787
|
-
const { key, signal: signalOption, context: contextOption } = options;
|
|
788
|
-
const { ac, io } = __classPrivateFieldGet(this, _UniKvs_con, "f");
|
|
789
|
-
const signal = combineSignals([ac.signal, signalOption]);
|
|
790
|
-
const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
|
|
791
|
-
context["unikvs:action"] = "delete";
|
|
792
|
-
context["unikvs:key"] = key;
|
|
793
|
-
const lock = await asyncmux(this, signal);
|
|
794
|
-
try {
|
|
795
|
-
// ロック待機中に接続状態が変更されていないか再確認します。
|
|
796
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
|
|
797
|
-
throw new UniKvsIsNotOpenError();
|
|
798
|
-
}
|
|
799
|
-
const lock = await io.lock({ key, signal });
|
|
800
|
-
try {
|
|
801
|
-
// すべてのストレージから対象データを削除します。
|
|
802
|
-
// すべての処理を並列に実行し、エラーが発生した場合は集約します。
|
|
803
|
-
const errors = [];
|
|
804
|
-
await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async (storage) => {
|
|
805
|
-
try {
|
|
806
|
-
if (await storage.exists(context, signal, key)) {
|
|
807
|
-
await storage.delete(context, signal, key);
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
catch (reason) {
|
|
811
|
-
errors.push({ reason });
|
|
812
|
-
}
|
|
813
|
-
}));
|
|
814
|
-
if (errors.length > 0) {
|
|
815
|
-
throw new PluginOperationAggregateError({ plugin: "storage", action: "delete", errors });
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
finally {
|
|
819
|
-
lock.release();
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
finally {
|
|
823
|
-
lock.release();
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
async clear(...args) {
|
|
827
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
|
|
828
|
-
throw new UniKvsIsNotOpenError();
|
|
829
|
-
}
|
|
830
|
-
const [options = {}] = v.parseInput(ClearArgsSchema, args);
|
|
831
|
-
const { signal: signalOption, context: contextOption } = options;
|
|
832
|
-
const { ac, io } = __classPrivateFieldGet(this, _UniKvs_con, "f");
|
|
833
|
-
const signal = combineSignals([ac.signal, signalOption]);
|
|
834
|
-
const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
|
|
835
|
-
context["unikvs:action"] = "clear";
|
|
836
|
-
const lock = await asyncmux(this, signal);
|
|
837
|
-
try {
|
|
838
|
-
// ロック待機中に接続状態が変更されていないか再確認します。
|
|
839
|
-
if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
|
|
840
|
-
throw new UniKvsIsNotOpenError();
|
|
841
|
-
}
|
|
842
|
-
const lock = await io.lock({ signal });
|
|
843
|
-
try {
|
|
844
|
-
// すべてのストレージで一括削除を実行します。
|
|
845
|
-
// すべての処理を並列に実行し、エラーが発生した場合は集約します。
|
|
846
|
-
const errors = [];
|
|
847
|
-
await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async (storage) => {
|
|
848
|
-
try {
|
|
849
|
-
await storage.clear(context, signal);
|
|
850
|
-
}
|
|
851
|
-
catch (reason) {
|
|
852
|
-
errors.push({ reason });
|
|
853
|
-
}
|
|
854
|
-
}));
|
|
855
|
-
if (errors.length > 0) {
|
|
856
|
-
throw new PluginOperationAggregateError({ plugin: "storage", action: "clear", errors });
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
finally {
|
|
860
|
-
lock.release();
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
finally {
|
|
864
|
-
lock.release();
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
}
|