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