unikvs 0.0.4 → 0.0.6

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/src/unikvs.ts CHANGED
@@ -1,14 +1,13 @@
1
- import type { Context, IReadableStream, Key } from "@unikvs/core";
1
+ import type { Context, IReadableStream, IStorage } from "@unikvs/core";
2
2
  import { asyncmux, Asyncmux, type AsyncmuxLock } from "asyncmux";
3
- import * as v from "valibot";
4
3
 
5
4
  import combineSignals from "./_combine-signals.js";
6
5
  import logger from "./_logger.js";
7
6
  import mergeContext from "./_merge-context.js";
8
- import { UniKvsStorage } from "./_storage.js";
7
+ import UniKvsStorage from "./_storage.js";
9
8
  import toValueStream from "./_to-value-stream.js";
10
9
  import UniKvsTransformer from "./_transformer.js";
11
- import { parse } from "./_valibot.js";
10
+ import * as v from "./_valibot.js";
12
11
  import type { ContextSource } from "./context.types.js";
13
12
  import {
14
13
  KeyNotFoundError,
@@ -68,39 +67,149 @@ export type KeyofKeyValueMappingHasStreamValue<TKeyValueMapping extends KeyValue
68
67
 
69
68
  // -------------------------------------------------------------------------------------------------
70
69
  //
71
- // 型定義
70
+ // スキーマ
72
71
  //
73
72
  // -------------------------------------------------------------------------------------------------
74
73
 
75
- /**
76
- * オープン操作時のオプションです。
77
- */
78
- export type OpenOptions = {
74
+ const ContextKeySchema = v.string();
75
+
76
+ const ContextSourceSchema = v.union([
77
+ v.record(v.any(), v.unknown()),
78
+ v.array(v.tuple([ContextKeySchema, v.unknown()])),
79
+ ]);
80
+
81
+ const OpenOptionsSchema = v.object({
79
82
  /**
80
83
  * 処理の中断を通知するためのシグナルです。
81
84
  */
82
- readonly signal?: AbortSignal | undefined;
85
+ signal: v.optional(v.instance(AbortSignal)),
83
86
 
84
87
  /**
85
88
  * 実行時のコンテキスト情報です。
86
89
  */
87
- readonly context?: ContextSource | undefined;
88
- };
90
+ context: v.optional(ContextSourceSchema),
91
+ });
89
92
 
90
- /**
91
- * クローズ操作時のオプションです。
92
- */
93
- export type CloseOptions = {
93
+ const OpenArgsSchema = v.tuple([v.optional(OpenOptionsSchema)]);
94
+
95
+ const CloseOptionsSchema = v.object({
94
96
  /**
95
97
  * 処理の中断を通知するためのシグナルです。
96
98
  */
97
- readonly signal?: AbortSignal | undefined;
99
+ signal: v.optional(v.instance(AbortSignal)),
98
100
 
99
101
  /**
100
102
  * 実行時のコンテキスト情報です。
101
103
  */
102
- readonly context?: ContextSource | undefined;
103
- };
104
+ context: v.optional(ContextSourceSchema),
105
+ });
106
+
107
+ const CloseArgsSchema = v.tuple([v.optional(CloseOptionsSchema)]);
108
+
109
+ const SetOptionsSchema = v.object({
110
+ key: v.string(),
111
+ value: v.unknown(),
112
+ signal: v.optional(v.instance(AbortSignal)),
113
+ context: v.optional(ContextSourceSchema),
114
+ });
115
+
116
+ const SetArgsSchema = v.union([
117
+ v.tuple([SetOptionsSchema]),
118
+ v.pipe(
119
+ v.tuple([
120
+ SetOptionsSchema.entries.key,
121
+ SetOptionsSchema.entries.value,
122
+ v.optional(v.omit(SetOptionsSchema, ["key", "value"])),
123
+ ]),
124
+ v.transform(([key, value, options]) => [{ ...options, key, value }]),
125
+ ),
126
+ ]);
127
+
128
+ const GetOptionsSchema = v.object({
129
+ key: v.string(),
130
+ signal: v.optional(v.instance(AbortSignal)),
131
+ context: v.optional(ContextSourceSchema),
132
+ });
133
+
134
+ const GetArgsSchema = v.union([
135
+ v.tuple([GetOptionsSchema]),
136
+ v.pipe(
137
+ v.tuple([GetOptionsSchema.entries.key, v.optional(v.omit(GetOptionsSchema, ["key"]))]),
138
+ v.transform(([key, options]) => [{ ...options, key }]),
139
+ ),
140
+ ]);
141
+
142
+ const StreamOptionsSchema = v.object({
143
+ key: v.string(),
144
+ signal: v.optional(v.instance(AbortSignal)),
145
+ context: v.optional(ContextSourceSchema),
146
+ });
147
+
148
+ const StreamArgsSchema = v.union([
149
+ v.tuple([StreamOptionsSchema]),
150
+ v.pipe(
151
+ v.tuple([StreamOptionsSchema.entries.key, v.optional(v.omit(StreamOptionsSchema, ["key"]))]),
152
+ v.transform(([key, options]) => [{ ...options, key }]),
153
+ ),
154
+ ]);
155
+
156
+ const HasOptionsSchema = v.object({
157
+ key: v.string(),
158
+ signal: v.optional(v.instance(AbortSignal)),
159
+ context: v.optional(ContextSourceSchema),
160
+ });
161
+
162
+ const HasArgsSchema = v.union([
163
+ v.tuple([HasOptionsSchema]),
164
+ v.pipe(
165
+ v.tuple([HasOptionsSchema.entries.key, v.optional(v.omit(HasOptionsSchema, ["key"]))]),
166
+ v.transform(([key, options]) => [{ ...options, key }]),
167
+ ),
168
+ ]);
169
+
170
+ const DeleteOptionsSchema = v.object({
171
+ key: v.string(),
172
+ signal: v.optional(v.instance(AbortSignal)),
173
+ context: v.optional(ContextSourceSchema),
174
+ });
175
+
176
+ const DeleteArgsSchema = v.union([
177
+ v.tuple([DeleteOptionsSchema]),
178
+ v.pipe(
179
+ v.tuple([DeleteOptionsSchema.entries.key, v.optional(v.omit(DeleteOptionsSchema, ["key"]))]),
180
+ v.transform(([key, options]) => [{ ...options, key }]),
181
+ ),
182
+ ]);
183
+
184
+ const ClearOptionsSchema = v.object({
185
+ /**
186
+ * 処理の中断を通知するためのシグナルです。
187
+ */
188
+ signal: v.optional(v.instance(AbortSignal)),
189
+
190
+ /**
191
+ * 実行時のコンテキスト情報です。
192
+ */
193
+ context: v.optional(ContextSourceSchema),
194
+ });
195
+
196
+ const ClearArgsSchema = v.tuple([v.optional(ClearOptionsSchema)]);
197
+
198
+ // -------------------------------------------------------------------------------------------------
199
+ //
200
+ // 型定義
201
+ //
202
+ // -------------------------------------------------------------------------------------------------
203
+
204
+ /**
205
+ * オープン操作時のオプションです。
206
+ */
207
+ export type OpenOptions = v.InferInput<typeof OpenOptionsSchema>;
208
+
209
+ /**
210
+ * クローズ操作時のオプションです。
211
+ */
212
+ export type CloseOptions = v.InferInput<typeof CloseOptionsSchema>;
104
213
 
105
214
  /**
106
215
  * 保存操作時のオプションです。
@@ -138,7 +247,7 @@ export type SetOptions<
138
247
  *
139
248
  * @template TKey 対象となるキーの型です。
140
249
  */
141
- export type GetOptions<TKey = Key> = {
250
+ export type GetOptions<TKey = IStorage.Key> = {
142
251
  /**
143
252
  * 操作対象を識別するためのキーです。
144
253
  */
@@ -160,7 +269,7 @@ export type GetOptions<TKey = Key> = {
160
269
  *
161
270
  * @template TKey 対象となるキーの型です。
162
271
  */
163
- export type StreamOptions<TKey = Key> = {
272
+ export type StreamOptions<TKey = IStorage.Key> = {
164
273
  /**
165
274
  * 操作対象を識別するためのキーです。
166
275
  */
@@ -182,7 +291,7 @@ export type StreamOptions<TKey = Key> = {
182
291
  *
183
292
  * @template TKey 対象となるキーの型です。
184
293
  */
185
- export type HasOptions<TKey = Key> = {
294
+ export type HasOptions<TKey = IStorage.Key> = {
186
295
  /**
187
296
  * 操作対象を識別するためのキーです。
188
297
  */
@@ -204,7 +313,7 @@ export type HasOptions<TKey = Key> = {
204
313
  *
205
314
  * @template TKey 対象となるキーの型です。
206
315
  */
207
- export type DeleteOptions<TKey = Key> = {
316
+ export type DeleteOptions<TKey = IStorage.Key> = {
208
317
  /**
209
318
  * 操作対象を識別するためのキーです。
210
319
  */
@@ -224,126 +333,7 @@ export type DeleteOptions<TKey = Key> = {
224
333
  /**
225
334
  * 全削除操作時のオプションです。
226
335
  */
227
- export type ClearOptions = {
228
- /**
229
- * 処理の中断を通知するためのシグナルです。
230
- */
231
- readonly signal?: AbortSignal | undefined;
232
-
233
- /**
234
- * 実行時のコンテキスト情報です。
235
- */
236
- readonly context?: ContextSource | undefined;
237
- };
238
-
239
- // -------------------------------------------------------------------------------------------------
240
- //
241
- // スキーマ
242
- //
243
- // -------------------------------------------------------------------------------------------------
244
-
245
- const ContextKeySchema = v.union([v.string(), v.symbol(), v.number()]);
246
-
247
- const ContextSourceSchema = v.union([
248
- v.record(v.any(), v.unknown()),
249
- v.array(v.tuple([ContextKeySchema, v.unknown()])),
250
- ]);
251
-
252
- const OpenOptionsSchema = v.object({
253
- signal: v.optional(v.instance(AbortSignal)),
254
- context: v.optional(ContextSourceSchema),
255
- });
256
-
257
- const OpenArgsSchema = v.tuple([v.optional(OpenOptionsSchema)]);
258
-
259
- const CloseOptionsSchema = v.object({
260
- signal: v.optional(v.instance(AbortSignal)),
261
- context: v.optional(ContextSourceSchema),
262
- });
263
-
264
- const CloseArgsSchema = v.tuple([v.optional(CloseOptionsSchema)]);
265
-
266
- const SetOptionsSchema = v.object({
267
- key: v.string(),
268
- value: v.unknown(),
269
- signal: v.optional(v.instance(AbortSignal)),
270
- context: v.optional(ContextSourceSchema),
271
- });
272
-
273
- const SetArgsSchema = v.union([
274
- v.tuple([SetOptionsSchema]),
275
- v.pipe(
276
- v.tuple([
277
- SetOptionsSchema.entries.key,
278
- SetOptionsSchema.entries.value,
279
- v.optional(v.omit(SetOptionsSchema, ["key", "value"])),
280
- ]),
281
- v.transform(([key, value, options]) => [{ ...options, key, value }]),
282
- ),
283
- ]);
284
-
285
- const GetOptionsSchema = v.object({
286
- key: v.string(),
287
- signal: v.optional(v.instance(AbortSignal)),
288
- context: v.optional(ContextSourceSchema),
289
- });
290
-
291
- const GetArgsSchema = v.union([
292
- v.tuple([GetOptionsSchema]),
293
- v.pipe(
294
- v.tuple([GetOptionsSchema.entries.key, v.optional(v.omit(GetOptionsSchema, ["key"]))]),
295
- v.transform(([key, options]) => [{ ...options, key }]),
296
- ),
297
- ]);
298
-
299
- const StreamOptionsSchema = v.object({
300
- key: v.string(),
301
- signal: v.optional(v.instance(AbortSignal)),
302
- context: v.optional(ContextSourceSchema),
303
- });
304
-
305
- const StreamArgsSchema = v.union([
306
- v.tuple([StreamOptionsSchema]),
307
- v.pipe(
308
- v.tuple([StreamOptionsSchema.entries.key, v.optional(v.omit(StreamOptionsSchema, ["key"]))]),
309
- v.transform(([key, options]) => [{ ...options, key }]),
310
- ),
311
- ]);
312
-
313
- const HasOptionsSchema = v.object({
314
- key: v.string(),
315
- signal: v.optional(v.instance(AbortSignal)),
316
- context: v.optional(ContextSourceSchema),
317
- });
318
-
319
- const HasArgsSchema = v.union([
320
- v.tuple([HasOptionsSchema]),
321
- v.pipe(
322
- v.tuple([HasOptionsSchema.entries.key, v.optional(v.omit(HasOptionsSchema, ["key"]))]),
323
- v.transform(([key, options]) => [{ ...options, key }]),
324
- ),
325
- ]);
326
-
327
- const DeleteOptionsSchema = v.object({
328
- key: v.string(),
329
- signal: v.optional(v.instance(AbortSignal)),
330
- context: v.optional(ContextSourceSchema),
331
- });
332
-
333
- const DeleteArgsSchema = v.union([
334
- v.tuple([DeleteOptionsSchema]),
335
- v.pipe(
336
- v.tuple([DeleteOptionsSchema.entries.key, v.optional(v.omit(DeleteOptionsSchema, ["key"]))]),
337
- v.transform(([key, options]) => [{ ...options, key }]),
338
- ),
339
- ]);
340
-
341
- const ClearOptionsSchema = v.object({
342
- signal: v.optional(v.instance(AbortSignal)),
343
- context: v.optional(ContextSourceSchema),
344
- });
345
-
346
- const ClearArgsSchema = v.tuple([v.optional(ClearOptionsSchema)]);
336
+ export type ClearOptions = v.InferInput<typeof ClearOptionsSchema>;
347
337
 
348
338
  // -------------------------------------------------------------------------------------------------
349
339
  //
@@ -359,7 +349,7 @@ const ioLockRegistry: FinalizationRegistry<AsyncmuxLock> | null =
359
349
  ? null
360
350
  : new FinalizationRegistry((lock) => {
361
351
  try {
362
- lock.unlock();
352
+ lock.release();
363
353
  } catch {}
364
354
  });
365
355
 
@@ -370,12 +360,12 @@ type Connection = {
370
360
  /**
371
361
  * 接続全体を管理する AbortController です。
372
362
  */
373
- readonly conAc: AbortController;
363
+ readonly ac: AbortController;
374
364
 
375
365
  /**
376
366
  * I/O の多重化を制御する Asyncmux インスタンスです。
377
367
  */
378
- readonly ioMux: Asyncmux;
368
+ readonly io: Asyncmux;
379
369
  };
380
370
 
381
371
  /**
@@ -422,6 +412,8 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
422
412
  */
423
413
  #con: Connection | null;
424
414
 
415
+ readonly #acSet: Set<AbortController>;
416
+
425
417
  /**
426
418
  * 基本となる実行コンテキスト情報です。
427
419
  */
@@ -451,10 +443,8 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
451
443
  transformers: readonly UniKvsTransformer[],
452
444
  ) {
453
445
  this.#con = null;
454
- this.#context = {
455
- ...context,
456
- "unikvs:instance": this,
457
- };
446
+ this.#acSet = new Set();
447
+ this.#context = { ...context };
458
448
  this.#destinations = destinations;
459
449
  this.#transformers = transformers;
460
450
  }
@@ -465,7 +455,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
465
455
  * @returns 利用可能である場合は true、そうでない場合は false を返します。
466
456
  */
467
457
  public get isOpen(): boolean {
468
- return !!this.#con;
458
+ return this.#con !== null;
469
459
  }
470
460
 
471
461
  /**
@@ -477,134 +467,114 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
477
467
  public open(options?: OpenOptions): Promise<void>;
478
468
 
479
469
  public async open(...args: any): Promise<void> {
480
- if (this.#con) {
470
+ if (this.#con !== null) {
481
471
  throw new UniKvsIsOpenError();
482
472
  }
483
473
 
484
- this.#con = {
485
- conAc: new AbortController(),
486
- ioMux: new Asyncmux(),
487
- };
488
- try {
489
- const [options = {}] = parse(OpenArgsSchema, args);
490
- const { signal: signalOption, context: contextOption } = options;
474
+ const [options = {}] = v.parseInput(OpenArgsSchema, args);
475
+ const { signal: signalOption, context: contextOption } = options;
491
476
 
492
- const { conAc } = this.#con;
493
- const signal = combineSignals([conAc.signal, signalOption]);
477
+ const ac = new AbortController();
478
+ const signal = combineSignals([ac.signal, signalOption]);
494
479
 
495
- const context = mergeContext(this.#context, contextOption);
496
- context["unikvs:action"] = "open";
480
+ const context = mergeContext(this.#context, contextOption);
481
+ context["unikvs:action"] = "open";
482
+
483
+ signal.throwIfAborted();
484
+
485
+ this.#acSet.add(ac);
486
+
487
+ const dispose: (() => Promise<void>)[] = [];
488
+
489
+ const lock = await asyncmux(this, signal);
490
+ try {
491
+ if (this.#con !== null) {
492
+ throw new UniKvsIsOpenError();
493
+ }
497
494
 
498
495
  const openFns: [() => Promise<void>, plugin: "storage" | "transformer"][] = [];
499
- const dispose: (() => Promise<void>)[] = [];
500
- const lock = await asyncmux(this, signal);
501
- try {
502
- // ロック待機中に接続状態が変更されていないか再確認します。
503
- if (this.#con.conAc !== conAc) {
504
- throw new UniKvsIsOpenError();
505
- }
506
496
 
507
- // 各ストレージのオープン処理をリストに追加します。
508
- for (const storage of this.#destinations) {
509
- openFns.push([
510
- async () => {
511
- await storage.open(context, signal);
497
+ // 各ストレージのオープン処理をリストに追加します。
498
+ for (const storage of this.#destinations) {
499
+ openFns.push([
500
+ async () => {
501
+ await storage.open(context, signal);
512
502
 
513
- dispose.push(async () => {
514
- try {
515
- await storage.close(context, signal);
516
- } catch (ex) {
517
- logger.error`Failed to close storage: ${ex}`;
518
- }
519
- });
520
- },
521
- "storage",
522
- ]);
523
- }
503
+ dispose.push(async () => {
504
+ try {
505
+ await storage.close(context, signal);
506
+ } catch (ex) {
507
+ logger.error`Failed to close storage: ${ex}`;
508
+ }
509
+ });
510
+ },
511
+ "storage",
512
+ ]);
513
+ }
524
514
 
525
- // 各トランスフォーマーのオープン処理をリストに追加します。
526
- for (const transformer of this.#transformers) {
527
- openFns.push([
528
- async () => {
529
- await transformer.open(context, signal);
515
+ // 各トランスフォーマーのオープン処理をリストに追加します。
516
+ for (const transformer of this.#transformers) {
517
+ openFns.push([
518
+ async () => {
519
+ await transformer.open(context, signal);
530
520
 
531
- dispose.push(async () => {
532
- try {
533
- await transformer.close(context, signal);
534
- } catch (ex) {
535
- logger.error`Failed to close transformer: ${ex}`;
536
- }
537
- });
538
- },
539
- "transformer",
540
- ]);
541
- }
521
+ dispose.push(async () => {
522
+ try {
523
+ await transformer.close(context, signal);
524
+ } catch (ex) {
525
+ logger.error`Failed to close transformer: ${ex}`;
526
+ }
527
+ });
528
+ },
529
+ "transformer",
530
+ ]);
531
+ }
542
532
 
543
- // すべての処理を並列に実行し、エラーが発生した場合は集約します。
544
- const errors: { plugin: "storage" | "transformer"; reason: unknown }[] = [];
533
+ // すべての処理を並列に実行し、エラーが発生した場合は集約します。
534
+ const errors: { plugin: "storage" | "transformer"; reason: unknown }[] = [];
535
+ await Promise.all(
536
+ openFns.map(async ([f, plugin]) => {
537
+ try {
538
+ await f();
539
+ } catch (reason) {
540
+ errors.push({ plugin, reason });
541
+ }
542
+ }),
543
+ );
544
+ if (errors.length > 0) {
545
+ throw new PluginOperationAggregateError({ action: "open", errors });
546
+ }
547
+
548
+ this.#con = {
549
+ ac,
550
+ io: new Asyncmux(),
551
+ };
552
+ } catch (ex) {
553
+ if (dispose.length > 0) {
545
554
  await Promise.all(
546
- openFns.map(async ([f, plugin]) => {
547
- try {
548
- await f();
549
- } catch (reason) {
550
- errors.push({ plugin, reason });
551
- }
555
+ dispose.map(async (f) => {
556
+ await f();
552
557
  }),
553
558
  );
554
- if (errors.length > 0) {
555
- throw new PluginOperationAggregateError({ action: "open", errors });
556
- }
557
- } catch (ex) {
558
- this.#con = null; // unlock の前に null に戻します。
559
-
560
- if (dispose.length > 0) {
561
- await Promise.all(
562
- dispose.map(async (f) => {
563
- await f();
564
- }),
565
- );
566
- }
567
-
568
- throw ex;
569
- } finally {
570
- lock.unlock();
571
559
  }
572
- } catch (ex) {
573
- this.#con = null;
560
+
574
561
  throw ex;
562
+ } finally {
563
+ this.#acSet.delete(ac);
564
+ lock.release();
575
565
  }
576
566
  }
577
567
 
578
- /**
579
- * ストレージをクローズします。
580
- *
581
- * @param options クローズ時のオプションです。
582
- * @returns 完了を通知する Promise です。
583
- */
584
- public close(options?: CloseOptions): Promise<void>;
585
-
586
- public async close(...args: any): Promise<void> {
587
- if (!this.#con) {
588
- throw new UniKvsIsNotOpenError();
589
- }
590
-
591
- const [options = {}] = parse(CloseArgsSchema, args);
592
- const { signal = AbortSignal.timeout(10e3), context: contextOption } = options;
593
-
594
- const context = mergeContext(this.#context, contextOption);
595
- context["unikvs:action"] = "close";
596
-
597
- const { conAc, ioMux } = this.#con;
598
- conAc.abort(new UniKvsIsNotOpenError()); // 実行中の他の操作をすべて中断させるために signal を発火させます。
599
-
568
+ async #close(context: Context, signal: AbortSignal, con: Connection): Promise<void> {
600
569
  const lock = await asyncmux(this, signal);
601
570
  try {
602
571
  // ロック待機中に接続状態が変更されていないか再確認します。
603
- if (!this.#con) {
572
+ if (this.#con !== con) {
604
573
  throw new UniKvsIsNotOpenError();
605
574
  }
606
575
 
607
- const lock = await ioMux.lock({ signal });
576
+ const { io } = this.#con;
577
+ const lock = await io.lock({ signal });
608
578
  try {
609
579
  const closeFns: [() => Promise<void>, plugin: "storage" | "transformer"][] = [];
610
580
 
@@ -643,11 +613,55 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
643
613
  throw new PluginOperationAggregateError({ action: "close", errors });
644
614
  }
645
615
  } finally {
646
- lock.unlock();
616
+ lock.release();
647
617
  }
648
- } finally {
618
+
649
619
  this.#con = null;
650
- lock.unlock();
620
+ } finally {
621
+ lock.release();
622
+ }
623
+ }
624
+
625
+ /**
626
+ * ストレージをクローズします。
627
+ *
628
+ * @param options クローズ時のオプションです。
629
+ * @returns 完了を通知する Promise です。
630
+ */
631
+ public close(options?: CloseOptions): Promise<void>;
632
+
633
+ public close(...args: any): Promise<void> {
634
+ try {
635
+ const [options = {}] = v.parseInput(CloseArgsSchema, args);
636
+ const { signal = AbortSignal.timeout(10e3), context: contextOption } = options;
637
+
638
+ const context = mergeContext(this.#context, contextOption);
639
+ context["unikvs:action"] = "close";
640
+
641
+ if (this.#con === null) {
642
+ const acArr = [...this.#acSet];
643
+ this.#acSet.clear();
644
+ for (const ac of acArr) {
645
+ if (!ac.signal.aborted) {
646
+ ac.abort(new UniKvsIsNotOpenError());
647
+ }
648
+ }
649
+
650
+ throw new UniKvsIsNotOpenError();
651
+ }
652
+
653
+ const { ac } = this.#con;
654
+ const acArr = [ac, ...this.#acSet];
655
+ this.#acSet.clear();
656
+ for (const ac of acArr) {
657
+ if (!ac.signal.aborted) {
658
+ ac.abort(new UniKvsIsNotOpenError());
659
+ }
660
+ }
661
+
662
+ return this.#close(context, signal, this.#con);
663
+ } catch (ex) {
664
+ return Promise.reject(ex);
651
665
  }
652
666
  }
653
667
 
@@ -688,15 +702,15 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
688
702
  ): Promise<void>;
689
703
 
690
704
  public async set(...args: any): Promise<void> {
691
- if (!this.#con) {
705
+ if (this.#con === null) {
692
706
  throw new UniKvsIsNotOpenError();
693
707
  }
694
708
 
695
- const [options] = parse(SetArgsSchema, args);
709
+ const [options] = v.parseInput(SetArgsSchema, args);
696
710
  const { key, value, signal: signalOption, context: contextOption } = options;
697
711
 
698
- const { conAc, ioMux } = this.#con;
699
- const signal = combineSignals([conAc.signal, signalOption]);
712
+ const { ac, io } = this.#con;
713
+ const signal = combineSignals([ac.signal, signalOption]);
700
714
 
701
715
  const context = mergeContext(this.#context, contextOption);
702
716
  context["unikvs:action"] = "set";
@@ -705,7 +719,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
705
719
  const lock = await asyncmux(this, signal);
706
720
  try {
707
721
  // ロック待機中に接続状態が変更されていないか再確認します。
708
- if (!this.#con) {
722
+ if (this.#con === null) {
709
723
  throw new UniKvsIsNotOpenError();
710
724
  }
711
725
 
@@ -719,7 +733,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
719
733
  data = data.pipeThrough(e);
720
734
  }
721
735
 
722
- const lock = await ioMux.lock({ key, signal });
736
+ const lock = await io.lock({ key, signal });
723
737
  try {
724
738
  await Promise.all(
725
739
  this.#destinations.map(async (storage, i) => {
@@ -739,7 +753,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
739
753
  }),
740
754
  );
741
755
  } finally {
742
- lock.unlock();
756
+ lock.release();
743
757
  }
744
758
  } else {
745
759
  // 登録されているトランスフォーマーを順番に適用してデータをエンコードします。
@@ -748,7 +762,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
748
762
  data = await transformer.encode(context, signal, data);
749
763
  }
750
764
 
751
- const lock = await ioMux.lock({ key, signal });
765
+ const lock = await io.lock({ key, signal });
752
766
  try {
753
767
  await Promise.all(
754
768
  this.#destinations.map(async (storage) => {
@@ -761,7 +775,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
761
775
  }),
762
776
  );
763
777
  } finally {
764
- lock.unlock();
778
+ lock.release();
765
779
  }
766
780
  }
767
781
 
@@ -795,7 +809,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
795
809
  throw error;
796
810
  }
797
811
  } finally {
798
- lock.unlock();
812
+ lock.release();
799
813
  }
800
814
  }
801
815
 
@@ -824,15 +838,15 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
824
838
  ): Promise<$InferPlainValueData<TKeyValueMapping[TKey]>>;
825
839
 
826
840
  public async get(...args: any): Promise<unknown> {
827
- if (!this.#con) {
841
+ if (this.#con === null) {
828
842
  throw new UniKvsIsNotOpenError();
829
843
  }
830
844
 
831
- const [options] = parse(GetArgsSchema, args);
845
+ const [options] = v.parseInput(GetArgsSchema, args);
832
846
  const { key, signal: signalOption, context: contextOption } = options;
833
847
 
834
- const { conAc, ioMux } = this.#con;
835
- const signal = combineSignals([conAc.signal, signalOption]);
848
+ const { ac, io } = this.#con;
849
+ const signal = combineSignals([ac.signal, signalOption]);
836
850
 
837
851
  const context = mergeContext(this.#context, contextOption);
838
852
  context["unikvs:action"] = "get";
@@ -841,14 +855,14 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
841
855
  const lock = await asyncmux.readonly(this, signal);
842
856
  try {
843
857
  // ロック待機中に接続状態が変更されていないか再確認します。
844
- if (!this.#con) {
858
+ if (this.#con === null) {
845
859
  throw new UniKvsIsNotOpenError();
846
860
  }
847
861
 
848
862
  const NONE = {};
849
- let data = NONE;
863
+ let data: any = NONE;
850
864
 
851
- const lock = await ioMux.rLock({ key, signal });
865
+ const lock = await io.rLock({ key, signal });
852
866
  try {
853
867
  // 各ストレージを巡回し、最初に見つかったデータを取得します。
854
868
  for (const storage of this.#destinations) {
@@ -858,7 +872,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
858
872
  }
859
873
  }
860
874
  } finally {
861
- lock.unlock();
875
+ lock.release();
862
876
  }
863
877
 
864
878
  if (data === NONE) {
@@ -874,7 +888,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
874
888
 
875
889
  return data;
876
890
  } finally {
877
- lock.unlock();
891
+ lock.release();
878
892
  }
879
893
  }
880
894
 
@@ -903,15 +917,15 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
903
917
  ): Promise<ValueStream<$InferStreamValueChunkData<TKeyValueMapping[TKey]>>>;
904
918
 
905
919
  public async stream(...args: any): Promise<ValueStream> {
906
- if (!this.#con) {
920
+ if (this.#con === null) {
907
921
  throw new UniKvsIsNotOpenError();
908
922
  }
909
923
 
910
- const [options] = parse(StreamArgsSchema, args);
924
+ const [options] = v.parseInput(StreamArgsSchema, args);
911
925
  const { key, signal: signalOption, context: contextOption } = options;
912
926
 
913
- const { conAc, ioMux } = this.#con;
914
- const signal = combineSignals([conAc.signal, signalOption]);
927
+ const { ac, io } = this.#con;
928
+ const signal = combineSignals([ac.signal, signalOption]);
915
929
 
916
930
  const context = mergeContext(this.#context, contextOption);
917
931
  context["unikvs:action"] = "stream";
@@ -920,14 +934,14 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
920
934
  const lock = await asyncmux(this, signal);
921
935
  try {
922
936
  // ロック待機中に接続状態が変更されていないか再確認します。
923
- if (!this.#con) {
937
+ if (this.#con === null) {
924
938
  throw new UniKvsIsNotOpenError();
925
939
  }
926
940
 
927
941
  const NONE: any = {};
928
942
  let r: IReadableStream = NONE;
929
943
 
930
- const lock = await ioMux.rLock({ key, signal });
944
+ const lock = await io.rLock({ key, signal });
931
945
  try {
932
946
  // 各ストレージを巡回し、最初に見つかったデータを取得します。
933
947
  for (const storage of this.#destinations) {
@@ -955,7 +969,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
955
969
  await r.cancel();
956
970
  } catch {}
957
971
  try {
958
- lock.unlock();
972
+ lock.release();
959
973
  } catch {}
960
974
  });
961
975
  }
@@ -969,7 +983,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
969
983
  await r.cancel();
970
984
  } catch {}
971
985
  try {
972
- lock.unlock();
986
+ lock.release();
973
987
  } catch {}
974
988
  });
975
989
 
@@ -978,11 +992,11 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
978
992
 
979
993
  return valueStream;
980
994
  } catch (ex) {
981
- lock.unlock();
995
+ lock.release();
982
996
  throw ex;
983
997
  }
984
998
  } finally {
985
- lock.unlock();
999
+ lock.release();
986
1000
  }
987
1001
  }
988
1002
 
@@ -1007,15 +1021,15 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1007
1021
  public has(options: HasOptions<KeyofKeyValueMapping<TKeyValueMapping>>): Promise<boolean>;
1008
1022
 
1009
1023
  public async has(...args: any): Promise<boolean> {
1010
- if (!this.#con) {
1024
+ if (this.#con === null) {
1011
1025
  throw new UniKvsIsNotOpenError();
1012
1026
  }
1013
1027
 
1014
- const [options] = parse(HasArgsSchema, args);
1028
+ const [options] = v.parseInput(HasArgsSchema, args);
1015
1029
  const { key, signal: signalOption, context: contextOption } = options;
1016
1030
 
1017
- const { conAc, ioMux } = this.#con;
1018
- const signal = combineSignals([conAc.signal, signalOption]);
1031
+ const { ac, io } = this.#con;
1032
+ const signal = combineSignals([ac.signal, signalOption]);
1019
1033
 
1020
1034
  const context = mergeContext(this.#context, contextOption);
1021
1035
  context["unikvs:action"] = "has";
@@ -1024,11 +1038,11 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1024
1038
  const lock = await asyncmux(this, signal);
1025
1039
  try {
1026
1040
  // ロック待機中に接続状態が変更されていないか再確認します。
1027
- if (!this.#con) {
1041
+ if (this.#con === null) {
1028
1042
  throw new UniKvsIsNotOpenError();
1029
1043
  }
1030
1044
 
1031
- const lock = await ioMux.rLock({ key, signal });
1045
+ const lock = await io.rLock({ key, signal });
1032
1046
  try {
1033
1047
  // いずれかのストレージに存在すれば true を返します。
1034
1048
  for (const storage of this.#destinations) {
@@ -1039,10 +1053,10 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1039
1053
 
1040
1054
  return false;
1041
1055
  } finally {
1042
- lock.unlock();
1056
+ lock.release();
1043
1057
  }
1044
1058
  } finally {
1045
- lock.unlock();
1059
+ lock.release();
1046
1060
  }
1047
1061
  }
1048
1062
 
@@ -1067,15 +1081,15 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1067
1081
  public delete(options: DeleteOptions<KeyofKeyValueMapping<TKeyValueMapping>>): Promise<void>;
1068
1082
 
1069
1083
  public async delete(...args: any): Promise<void> {
1070
- if (!this.#con) {
1084
+ if (this.#con === null) {
1071
1085
  throw new UniKvsIsNotOpenError();
1072
1086
  }
1073
1087
 
1074
- const [options] = parse(DeleteArgsSchema, args);
1088
+ const [options] = v.parseInput(DeleteArgsSchema, args);
1075
1089
  const { key, signal: signalOption, context: contextOption } = options;
1076
1090
 
1077
- const { conAc, ioMux } = this.#con;
1078
- const signal = combineSignals([conAc.signal, signalOption]);
1091
+ const { ac, io } = this.#con;
1092
+ const signal = combineSignals([ac.signal, signalOption]);
1079
1093
 
1080
1094
  const context = mergeContext(this.#context, contextOption);
1081
1095
  context["unikvs:action"] = "delete";
@@ -1084,11 +1098,11 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1084
1098
  const lock = await asyncmux(this, signal);
1085
1099
  try {
1086
1100
  // ロック待機中に接続状態が変更されていないか再確認します。
1087
- if (!this.#con) {
1101
+ if (this.#con === null) {
1088
1102
  throw new UniKvsIsNotOpenError();
1089
1103
  }
1090
1104
 
1091
- const lock = await ioMux.lock({ key, signal });
1105
+ const lock = await io.lock({ key, signal });
1092
1106
  try {
1093
1107
  // すべてのストレージから対象データを削除します。
1094
1108
  // すべての処理を並列に実行し、エラーが発生した場合は集約します。
@@ -1108,10 +1122,10 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1108
1122
  throw new PluginOperationAggregateError({ plugin: "storage", action: "delete", errors });
1109
1123
  }
1110
1124
  } finally {
1111
- lock.unlock();
1125
+ lock.release();
1112
1126
  }
1113
1127
  } finally {
1114
- lock.unlock();
1128
+ lock.release();
1115
1129
  }
1116
1130
  }
1117
1131
 
@@ -1124,15 +1138,15 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1124
1138
  public async clear(options?: ClearOptions): Promise<void>;
1125
1139
 
1126
1140
  public async clear(...args: any): Promise<void> {
1127
- if (!this.#con) {
1141
+ if (this.#con === null) {
1128
1142
  throw new UniKvsIsNotOpenError();
1129
1143
  }
1130
1144
 
1131
- const [options = {}] = parse(ClearArgsSchema, args);
1145
+ const [options = {}] = v.parseInput(ClearArgsSchema, args);
1132
1146
  const { signal: signalOption, context: contextOption } = options;
1133
1147
 
1134
- const { conAc, ioMux } = this.#con;
1135
- const signal = combineSignals([conAc.signal, signalOption]);
1148
+ const { ac, io } = this.#con;
1149
+ const signal = combineSignals([ac.signal, signalOption]);
1136
1150
 
1137
1151
  const context = mergeContext(this.#context, contextOption);
1138
1152
  context["unikvs:action"] = "clear";
@@ -1140,11 +1154,11 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1140
1154
  const lock = await asyncmux(this, signal);
1141
1155
  try {
1142
1156
  // ロック待機中に接続状態が変更されていないか再確認します。
1143
- if (!this.#con) {
1157
+ if (this.#con === null) {
1144
1158
  throw new UniKvsIsNotOpenError();
1145
1159
  }
1146
1160
 
1147
- const lock = await ioMux.lock({ signal });
1161
+ const lock = await io.lock({ signal });
1148
1162
  try {
1149
1163
  // すべてのストレージで一括削除を実行します。
1150
1164
  // すべての処理を並列に実行し、エラーが発生した場合は集約します。
@@ -1162,10 +1176,10 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1162
1176
  throw new PluginOperationAggregateError({ plugin: "storage", action: "clear", errors });
1163
1177
  }
1164
1178
  } finally {
1165
- lock.unlock();
1179
+ lock.release();
1166
1180
  }
1167
1181
  } finally {
1168
- lock.unlock();
1182
+ lock.release();
1169
1183
  }
1170
1184
  }
1171
1185
  }