ueberdb2 5.0.43 → 5.0.45

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.
Files changed (23) hide show
  1. package/dist/{lib/AbstractDatabase.js → AbstractDatabase-a4jdIEuT.js} +7 -2
  2. package/dist/{databases/cassandra_db.js → cassandra_db-C5K2zZew.js} +3 -3
  3. package/dist/{_virtual/_rolldown/runtime.js → chunk-8l464Juk.js} +6 -1
  4. package/dist/{databases/couch_db.js → couch_db-BVd81sS7.js} +5 -5
  5. package/dist/{databases/dirty_db.js → dirty_db-C9zUhXIG.js} +4 -4
  6. package/dist/{databases/dirty_git_db.js → dirty_git_db-Cj3oEEyZ.js} +4 -4
  7. package/dist/{databases/elasticsearch_db.js → elasticsearch_db-DjnZ1DHG.js} +4 -4
  8. package/dist/index.js +502 -22
  9. package/dist/{lib/logging.js → logging-DmqnZRde.js} +6 -1
  10. package/dist/{databases/memory_db.js → memory_db-SlQsh4tk.js} +2 -2
  11. package/dist/{databases/mock_db.js → mock_db-BBijMErd.js} +2 -2
  12. package/dist/{databases/mongodb_db.js → mongodb_db-ByZscnbs.js} +3 -3
  13. package/dist/{databases/mssql_db.js → mssql_db-C9-gmVgP.js} +5 -5
  14. package/dist/{databases/mysql_db.js → mysql_db-CRYtP-Mk.js} +4 -4
  15. package/dist/{databases/postgres_db.js → postgres_db-CVDQiNwN.js} +5 -5
  16. package/dist/{databases/postgrespool_db.js → postgrespool_db-CynysVC1.js} +1 -1
  17. package/dist/{databases/redis_db.js → redis_db-CDma40om.js} +3 -3
  18. package/dist/{databases/rethink_db.js → rethink_db-D7NvPe_4.js} +5 -5
  19. package/dist/{databases/rusty_db.js → rusty_db-CaVGu0z7.js} +3 -3
  20. package/dist/{databases/sqlite_db.js → sqlite_db-B-nmfVje.js} +3 -4
  21. package/dist/{databases/surrealdb_db.js → surrealdb_db-JmcyCabz.js} +3 -3
  22. package/package.json +4 -5
  23. package/dist/lib/CacheAndBufferLayer.js +0 -484
@@ -1,484 +0,0 @@
1
- const require_runtime = require("../_virtual/_rolldown/runtime.js");
2
- let util = require("util");
3
- util = require_runtime.__toESM(util);
4
- //#region lib/CacheAndBufferLayer.ts
5
- /**
6
- * 2011 Peter 'Pita' Martischka
7
- *
8
- * Licensed under the Apache License, Version 2.0 (the "License");
9
- * you may not use this file except in compliance with the License.
10
- * You may obtain a copy of the License at
11
- *
12
- * http://www.apache.org/licenses/LICENSE-2.0
13
- *
14
- * Unless required by applicable law or agreed to in writing, software
15
- * distributed under the License is distributed on an "AS-IS" BASIS,
16
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
- * See the License for the specific language governing permissions and
18
- * limitations under the License.
19
- */
20
- /**
21
- * This module is made for the case, you want to use a SQL-Based Databse or a KeyValue Database that
22
- * can only save strings(and no objects), as a JSON KeyValue Store.
23
- *
24
- * The idea of the dbWrapper is to provide following features:
25
- *
26
- * * automatic JSON serialize/deserialize to abstract that away from the database driver and the
27
- * module user.
28
- * * cache reads. A amount of KeyValues are hold in the memory, so that reading is faster.
29
- * * Buffer DB Writings. Sets and deletes should be buffered to make them in a setted interval
30
- * with a bulk. This reduces the overhead of database transactions and makes the database
31
- * faster. But there is also a danger to loose data integrity, to keep that, we should provide a
32
- * flush function.
33
- *
34
- * All Features can be disabled or configured. The Wrapper provides default settings that can be
35
- * overwriden by the driver and by the module user.
36
- */
37
- /**
38
- * Cache with Least Recently Used eviction policy.
39
- */
40
- var LRU = class {
41
- /**
42
- * @param evictable Optional predicate that dictates whether it is permissable to evict the entry
43
- * if it is old and the cache is over capacity. The predicate is passed two arguments (key,
44
- * value). If no predicate is provided, all entries are evictable. Warning: Non-evictable
45
- * entries can cause the cache to go over capacity. If the number of non-evictable entries is
46
- * greater than or equal to the capacity, all new evictable entries will be evicted
47
- * immediately.
48
- */
49
- constructor(capacity, evictable = (k, v) => true) {
50
- this._capacity = capacity;
51
- this._evictable = evictable;
52
- this._cache = /* @__PURE__ */ new Map();
53
- }
54
- /**
55
- * The entries accessed via this iterator are not considered to have been "used" (for purposes of
56
- * determining least recently used).
57
- */
58
- [Symbol.iterator]() {
59
- return this._cache.entries();
60
- }
61
- /**
62
- * @param isUse Optional boolean indicating whether this get() should be considered a "use" of the
63
- * entry (for determining least recently used). Defaults to true.
64
- * @returns undefined if there is no entry matching the given key.
65
- */
66
- get(k, isUse = true) {
67
- if (!this._cache.has(k)) return;
68
- const v = this._cache.get(k);
69
- if (isUse) {
70
- this._cache.delete(k);
71
- this._cache.set(k, v);
72
- }
73
- return v;
74
- }
75
- /**
76
- * Adds or updates an entry in the cache. This marks the entry as the most recently used entry.
77
- */
78
- set(k, v) {
79
- this._cache.delete(k);
80
- this._cache.set(k, v);
81
- this.evictOld();
82
- }
83
- /**
84
- * Evicts the oldest evictable entries until the number of entries is equal to or less than the
85
- * cache's capacity. This method is automatically called by set(). Call this if you need to evict
86
- * newly evictable entries before the next call to set().
87
- */
88
- evictOld() {
89
- for (const [k, v] of this._cache.entries()) {
90
- if (this._cache.size <= this._capacity) break;
91
- if (!this._evictable(k, v)) continue;
92
- this._cache.delete(k);
93
- }
94
- }
95
- };
96
- var SelfContainedPromise = class extends Promise {
97
- constructor(executor = null) {
98
- let done;
99
- super((resolve, reject) => {
100
- done = (err, val) => err != null ? reject(err) : resolve(val);
101
- if (executor != null) executor(resolve, reject);
102
- });
103
- this.done = done;
104
- }
105
- };
106
- const defaultSettings = {
107
- bulkLimit: 0,
108
- cache: 1e4,
109
- writeInterval: 100,
110
- json: true,
111
- charset: "utf8mb4"
112
- };
113
- const Database = class {
114
- /**
115
- * @param wrappedDB The Database that should be wrapped
116
- * @param settings (optional) The settings that should be applied to the wrapper
117
- */
118
- constructor(wrappedDB, settings, logger) {
119
- if (wrappedDB.isAsync) this.wrappedDB = wrappedDB;
120
- else {
121
- this.wrappedDB = {};
122
- for (const fn of [
123
- "close",
124
- "doBulk",
125
- "findKeys",
126
- "get",
127
- "init",
128
- "remove",
129
- "set"
130
- ]) {
131
- const f = wrappedDB[fn];
132
- if (typeof f !== "function") continue;
133
- this.wrappedDB[fn] = util.default.promisify(f.bind(wrappedDB));
134
- }
135
- }
136
- this.logger = logger;
137
- this.settings = Object.freeze({
138
- ...defaultSettings,
139
- ...wrappedDB.settings || {},
140
- ...settings || {}
141
- });
142
- this.buffer = new LRU(this.settings.cache, (k, v) => !v.dirty && !v.writingInProgress);
143
- this._flushPaused = null;
144
- this._locks = /* @__PURE__ */ new Map();
145
- this.metrics = {
146
- lockAwaits: 0,
147
- lockAcquires: 0,
148
- lockReleases: 0,
149
- reads: 0,
150
- readsFailed: 0,
151
- readsFinished: 0,
152
- readsFromCache: 0,
153
- readsFromDb: 0,
154
- readsFromDbFailed: 0,
155
- readsFromDbFinished: 0,
156
- writes: 0,
157
- writesFailed: 0,
158
- writesFinished: 0,
159
- writesObsoleted: 0,
160
- writesToDb: 0,
161
- writesToDbFailed: 0,
162
- writesToDbFinished: 0,
163
- writesToDbRetried: 0
164
- };
165
- this.flushInterval = this.settings.writeInterval > 0 ? setInterval(() => this.flush(), this.settings.writeInterval) : null;
166
- }
167
- async _lock(key) {
168
- while (true) {
169
- const l = this._locks.get(key);
170
- if (l == null) break;
171
- ++this.metrics.lockAwaits;
172
- await l;
173
- }
174
- ++this.metrics.lockAcquires;
175
- this._locks.set(key, new SelfContainedPromise());
176
- }
177
- async _unlock(key) {
178
- ++this.metrics.lockReleases;
179
- this._locks.get(key).done();
180
- this._locks.delete(key);
181
- }
182
- _pauseFlush() {
183
- if (this._flushPaused == null) {
184
- this._flushPaused = new SelfContainedPromise();
185
- this._flushPaused.count = 0;
186
- }
187
- ++this._flushPaused.count;
188
- }
189
- _resumeFlush() {
190
- if (--this._flushPaused.count > 0) return;
191
- this._flushPaused.done();
192
- this._flushPaused = null;
193
- }
194
- /**
195
- * wraps the init function of the original DB
196
- */
197
- async init() {
198
- await this.wrappedDB.init();
199
- }
200
- /**
201
- * wraps the close function of the original DB
202
- */
203
- async close() {
204
- clearInterval(this.flushInterval);
205
- await this.flush();
206
- await this.wrappedDB.close();
207
- this.wrappedDB = null;
208
- }
209
- /**
210
- * Gets the value trough the wrapper.
211
- */
212
- async get(key) {
213
- let v;
214
- await this._lock(key);
215
- try {
216
- v = await this._getLocked(key);
217
- } finally {
218
- this._unlock(key);
219
- }
220
- return clone(v);
221
- }
222
- async _getLocked(key) {
223
- ++this.metrics.reads;
224
- try {
225
- const entry = this.buffer.get(key);
226
- if (entry != null) {
227
- ++this.metrics.readsFromCache;
228
- if (this.logger.isDebugEnabled()) this.logger.debug(`GET - ${key} - ${JSON.stringify(entry.value)} - from ${entry.dirty ? "dirty buffer" : "cache"}`);
229
- return entry.value;
230
- }
231
- let value;
232
- ++this.metrics.readsFromDb;
233
- try {
234
- value = await this.wrappedDB.get(key);
235
- } catch (err) {
236
- ++this.metrics.readsFromDbFailed;
237
- throw err;
238
- } finally {
239
- ++this.metrics.readsFromDbFinished;
240
- }
241
- if (this.settings.json) try {
242
- value = JSON.parse(value);
243
- } catch (err) {
244
- this.logger.error(`JSON-PROBLEM:${value}`);
245
- throw err;
246
- }
247
- if (this.settings.cache > 0) this.buffer.set(key, {
248
- value,
249
- dirty: null,
250
- writingInProgress: false
251
- });
252
- if (this.logger.isDebugEnabled()) this.logger.debug(`GET - ${key} - ${JSON.stringify(value)} - from database `);
253
- return value;
254
- } catch (err) {
255
- ++this.metrics.readsFailed;
256
- throw err;
257
- } finally {
258
- ++this.metrics.readsFinished;
259
- }
260
- }
261
- /**
262
- * Find keys function searches the db sets for matching entries and
263
- * returns the key entries via callback.
264
- */
265
- async findKeys(key, notKey) {
266
- await this.flush();
267
- const keyValues = await this.wrappedDB.findKeys(key, notKey);
268
- if (this.logger.isDebugEnabled()) this.logger.debug(`GET - ${key}-${notKey} - ${JSON.stringify(keyValues)} - from database `);
269
- return clone(keyValues);
270
- }
271
- /**
272
- * Remove a record from the database
273
- */
274
- async remove(key) {
275
- if (this.logger.isDebugEnabled()) this.logger.debug(`DELETE - ${key} - from database `);
276
- await this.set(key, null);
277
- }
278
- /**
279
- * Sets the value trough the wrapper
280
- */
281
- async set(key, value) {
282
- value = clone(value);
283
- let p;
284
- this._pauseFlush();
285
- try {
286
- await this._lock(key);
287
- try {
288
- p = this._setLocked(key, value);
289
- } finally {
290
- this._unlock(key);
291
- }
292
- } finally {
293
- this._resumeFlush();
294
- }
295
- await p;
296
- }
297
- async _setLocked(key, value) {
298
- ++this.metrics.writes;
299
- try {
300
- let entry = this.buffer.get(key);
301
- if (!entry || entry.writingInProgress) entry = {};
302
- else if (entry.dirty) ++this.metrics.writesObsoleted;
303
- entry.value = value;
304
- if (!entry.dirty) entry.dirty = new SelfContainedPromise();
305
- this.buffer.set(key, entry);
306
- const buffered = this.settings.writeInterval > 0;
307
- if (this.logger.isDebugEnabled()) this.logger.debug(`SET - ${key} - ${JSON.stringify(value)} - to ${buffered ? "buffer" : "database"}`);
308
- if (!buffered) this._write([[key, entry]]);
309
- await entry.dirty;
310
- } catch (err) {
311
- ++this.metrics.writesFailed;
312
- throw err;
313
- } finally {
314
- ++this.metrics.writesFinished;
315
- }
316
- }
317
- /**
318
- * Sets a subvalue
319
- */
320
- async setSub(key, sub, value) {
321
- value = clone(value);
322
- if (this.logger.isDebugEnabled()) this.logger.debug(`SETSUB - ${key}${JSON.stringify(sub)} - ${JSON.stringify(value)}`);
323
- let p;
324
- this._pauseFlush();
325
- try {
326
- await this._lock(key);
327
- try {
328
- let base;
329
- try {
330
- const fullValue = await this._getLocked(key);
331
- base = { fullValue };
332
- const ptr = {
333
- obj: base,
334
- prop: "fullValue"
335
- };
336
- for (let i = 0; i < sub.length; i++) {
337
- if (sub[i] === "__proto__") throw new Error("Modifying object prototype is not supported for security reasons");
338
- let o = ptr.obj[ptr.prop];
339
- if (o == null) ptr.obj[ptr.prop] = o = {};
340
- if (typeof o !== "object") throw new TypeError(`Cannot set property ${JSON.stringify(sub[i])} on non-object ${JSON.stringify(o)} (key: ${JSON.stringify(key)} value in db: ${JSON.stringify(fullValue)} sub: ${JSON.stringify(sub.slice(0, i + 1))})`);
341
- ptr.obj = ptr.obj[ptr.prop];
342
- ptr.prop = sub[i];
343
- }
344
- if (value == null) delete ptr.obj[ptr.prop];
345
- else ptr.obj[ptr.prop] = value;
346
- } catch (err) {
347
- ++this.metrics.writes;
348
- ++this.metrics.writesFailed;
349
- ++this.metrics.writesFinished;
350
- throw err;
351
- }
352
- p = this._setLocked(key, base.fullValue);
353
- } finally {
354
- await this._unlock(key);
355
- }
356
- } finally {
357
- this._resumeFlush();
358
- }
359
- await p;
360
- }
361
- /**
362
- * Returns a sub value of the object
363
- * @param sub is a array, for example if you want to access object.test.bla, the array is ["test",
364
- * "bla"]
365
- */
366
- async getSub(key, sub) {
367
- await this._lock(key);
368
- try {
369
- let v = await this._getLocked(key);
370
- for (const k of sub) {
371
- if (typeof v !== "object" || v != null && !Object.prototype.hasOwnProperty.call(v, k) || k === "__proto__") v = null;
372
- if (v == null) break;
373
- v = v[k];
374
- }
375
- if (this.logger.isDebugEnabled()) this.logger.debug(`GETSUB - ${key}${JSON.stringify(sub)} - ${JSON.stringify(v)}`);
376
- return clone(v);
377
- } finally {
378
- this._unlock(key);
379
- }
380
- }
381
- /**
382
- * Writes all dirty values to the database
383
- */
384
- async flush() {
385
- if (this._flushDone == null) this._flushDone = (async () => {
386
- while (true) {
387
- while (this._flushPaused != null) await this._flushPaused;
388
- const dirtyEntries = [];
389
- for (const entry of this.buffer) if (entry[1].dirty && !entry[1].writingInProgress) {
390
- dirtyEntries.push(entry);
391
- if (this.settings.bulkLimit && dirtyEntries.length >= this.settings.bulkLimit) break;
392
- }
393
- if (dirtyEntries.length === 0) return;
394
- await this._write(dirtyEntries);
395
- }
396
- })();
397
- await this._flushDone;
398
- this._flushDone = null;
399
- }
400
- async _write(dirtyEntries) {
401
- const markDone = (entry, err) => {
402
- if (entry.writingInProgress) {
403
- entry.writingInProgress = false;
404
- if (err != null) ++this.metrics.writesToDbFailed;
405
- ++this.metrics.writesToDbFinished;
406
- }
407
- entry.dirty.done(err);
408
- entry.dirty = null;
409
- };
410
- const ops = [];
411
- const entries = [];
412
- for (const [key, entry] of dirtyEntries) {
413
- let value = entry.value;
414
- try {
415
- value = this.settings.json && value != null ? JSON.stringify(value) : clone(value);
416
- } catch (err) {
417
- markDone(entry, err);
418
- continue;
419
- }
420
- entry.writingInProgress = true;
421
- ops.push({
422
- type: value == null ? "remove" : "set",
423
- key,
424
- value
425
- });
426
- entries.push(entry);
427
- }
428
- if (ops.length === 0) return;
429
- this.metrics.writesToDb += ops.length;
430
- const writeOneOp = async (op, entry) => {
431
- let writeErr = null;
432
- try {
433
- switch (op.type) {
434
- case "remove":
435
- await this.wrappedDB.remove(op.key);
436
- break;
437
- case "set":
438
- await this.wrappedDB.set(op.key, op.value);
439
- break;
440
- default: throw new Error(`unsupported operation type: ${op.type}`);
441
- }
442
- } catch (err) {
443
- writeErr = err || new Error(err);
444
- }
445
- markDone(entry, writeErr);
446
- };
447
- if (ops.length === 1) await writeOneOp(ops[0], entries[0]);
448
- else {
449
- let success = false;
450
- try {
451
- await this.wrappedDB.doBulk(ops);
452
- success = true;
453
- } catch (err) {
454
- this.logger.error(`Bulk write of ${ops.length} ops failed, retrying individually: ${err.stack || err}`);
455
- this.metrics.writesToDbRetried += ops.length;
456
- await Promise.all(ops.map(async (op, i) => await writeOneOp(op, entries[i])));
457
- }
458
- if (success) entries.forEach((entry) => markDone(entry, null));
459
- }
460
- this.buffer.evictOld();
461
- }
462
- };
463
- const clone = (obj, key = "") => {
464
- if (null == obj || "object" !== typeof obj) return obj;
465
- if (typeof obj.toJSON === "function") return clone(obj.toJSON(key));
466
- if (obj instanceof Date) {
467
- const copy = /* @__PURE__ */ new Date();
468
- copy.setTime(obj.getTime());
469
- return copy;
470
- }
471
- if (obj instanceof Array) {
472
- const copy = [];
473
- for (let i = 0, len = obj.length; i < len; ++i) copy[i] = clone(obj[i], String(i));
474
- return copy;
475
- }
476
- if (obj instanceof Object) {
477
- const copy = {};
478
- for (const attr in obj) if (Object.prototype.hasOwnProperty.call(obj, attr)) copy[attr] = clone(obj[attr], attr);
479
- return copy;
480
- }
481
- throw new Error("Unable to copy obj! Its type isn't supported.");
482
- };
483
- //#endregion
484
- exports.Database = Database;