@e-mc/core 0.13.5 → 0.13.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/README.md +13 -10
- package/index.js +308 -187
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
## Interface
|
|
11
11
|
|
|
12
|
-
* [View Source](https://www.unpkg.com/@e-mc/types@0.13.
|
|
12
|
+
* [View Source](https://www.unpkg.com/@e-mc/types@0.13.6/lib/index.d.ts)
|
|
13
13
|
|
|
14
14
|
```typescript
|
|
15
15
|
import type { DataSource, LogStatus, WorkerAction } from "./squared";
|
|
@@ -132,10 +132,13 @@ interface ClientDbConstructor extends ClientConstructor<IHost, ClientModule> {
|
|
|
132
132
|
convertTime(value: number | string): number;
|
|
133
133
|
findResult(source: string, credential: unknown, queryString: string, timeout: number, sessionKey?: string | boolean, renewCache?: boolean): QueryResult | undefined;
|
|
134
134
|
storeResult(source: string, credential: unknown, queryString: string, result: QueryResult, options: StoreResultOptions): QueryResult;
|
|
135
|
+
/** @deprecated */
|
|
135
136
|
storeResult(source: string, credential: unknown, queryString: string, result: QueryResult, sessionKey: string, sessionExpires: number): QueryResult;
|
|
136
137
|
storeResult(source: string, credential: unknown, queryString: string, result: QueryResult, cache: DbCacheValue): QueryResult;
|
|
137
|
-
storeResult(source: string, credential: unknown, queryString: string, result: QueryResult, cache: DbCacheValue | undefined, options: StoreResultOptions): QueryResult;
|
|
138
|
-
|
|
138
|
+
storeResult(source: string, credential: unknown, queryString: string, result: QueryResult, cache: DbCacheValue | undefined, options: Omit<StoreResultOptions, "cache">): QueryResult;
|
|
139
|
+
findSession(source: string, user: string, key: string): unknown;
|
|
140
|
+
storeSession(source: string, user: string, key: string, result: unknown, expires?: number): void;
|
|
141
|
+
purgeResult(prefix?: string, lru?: boolean | number): Promise<number>;
|
|
139
142
|
extractUUID(credential: unknown): string;
|
|
140
143
|
setPoolConfig(value: unknown): void;
|
|
141
144
|
getPoolConfig(source: string): unknown;
|
|
@@ -319,13 +322,13 @@ NOTE: **@e-mc/core** is mostly a collection of abstract base classes which canno
|
|
|
319
322
|
|
|
320
323
|
## References
|
|
321
324
|
|
|
322
|
-
- https://www.unpkg.com/@e-mc/types@0.13.
|
|
323
|
-
- https://www.unpkg.com/@e-mc/types@0.13.
|
|
324
|
-
- https://www.unpkg.com/@e-mc/types@0.13.
|
|
325
|
-
- https://www.unpkg.com/@e-mc/types@0.13.
|
|
326
|
-
- https://www.unpkg.com/@e-mc/types@0.13.
|
|
327
|
-
- https://www.unpkg.com/@e-mc/types@0.13.
|
|
328
|
-
- https://www.unpkg.com/@e-mc/types@0.13.
|
|
325
|
+
- https://www.unpkg.com/@e-mc/types@0.13.6/lib/squared.d.ts
|
|
326
|
+
- https://www.unpkg.com/@e-mc/types@0.13.6/lib/core.d.ts
|
|
327
|
+
- https://www.unpkg.com/@e-mc/types@0.13.6/lib/db.d.ts
|
|
328
|
+
- https://www.unpkg.com/@e-mc/types@0.13.6/lib/dom.d.ts
|
|
329
|
+
- https://www.unpkg.com/@e-mc/types@0.13.6/lib/logger.d.ts
|
|
330
|
+
- https://www.unpkg.com/@e-mc/types@0.13.6/lib/node.d.ts
|
|
331
|
+
- https://www.unpkg.com/@e-mc/types@0.13.6/lib/settings.d.ts
|
|
329
332
|
|
|
330
333
|
* https://www.npmjs.com/package/@types/node
|
|
331
334
|
|
package/index.js
CHANGED
|
@@ -3,7 +3,6 @@ var _a;
|
|
|
3
3
|
exports.Module = exports.Permission = exports.AbortComponent = exports.WorkerChannel = exports.WorkerGroup = exports.ClientDb = exports.Client = exports.Host = void 0;
|
|
4
4
|
const path = require("node:path");
|
|
5
5
|
const fs = require("node:fs");
|
|
6
|
-
const os = require("node:os");
|
|
7
6
|
const pm = require("picomatch");
|
|
8
7
|
const ipaddr = require("ipaddr.js");
|
|
9
8
|
const EventEmitter = require("node:events");
|
|
@@ -15,7 +14,7 @@ exports.Module = module_1;
|
|
|
15
14
|
const kHost = Symbol.for('host:constructor');
|
|
16
15
|
const kClient = Symbol.for('client:constructor');
|
|
17
16
|
const kClientDb = Symbol.for('clientdb:constructor');
|
|
18
|
-
const CACHE_USER =
|
|
17
|
+
const CACHE_USER = Object.create(null);
|
|
19
18
|
const CACHE_SOURCE = Object.create(null);
|
|
20
19
|
const CACHE_SESSION = Object.create(null);
|
|
21
20
|
const ABORT_LISTENER = new WeakMap();
|
|
@@ -43,7 +42,7 @@ const HOST = {
|
|
|
43
42
|
LOG_PROGRESS_PAUSED: new Set()
|
|
44
43
|
};
|
|
45
44
|
const WORKER_GROUP = {
|
|
46
|
-
MAX:
|
|
45
|
+
MAX: module_1.availableParallelism(),
|
|
47
46
|
TIMEOUT: Infinity,
|
|
48
47
|
LOCKED: true
|
|
49
48
|
};
|
|
@@ -159,65 +158,13 @@ function resumeHostQueue(item, aborted) {
|
|
|
159
158
|
function encryptText(data, iv) {
|
|
160
159
|
return HOST.CIPHER && (0, types_1.isString)(data) && (0, types_1.encryptUTF8)(HOST.CIPHER.algorithm, HOST.CIPHER.key, iv, data) || '';
|
|
161
160
|
}
|
|
162
|
-
function clearSourceResult(data) {
|
|
163
|
-
const result = data[1];
|
|
164
|
-
data[1] = null;
|
|
165
|
-
if (typeof result === 'string') {
|
|
166
|
-
fs.unlink(result, () => { });
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
function addSourceResult(source, data) {
|
|
170
|
-
const { items, config } = CACHE_SOURCE[source] ||= { items: [] };
|
|
171
|
-
if (config && items.length >= config.limit) {
|
|
172
|
-
const { percent, min } = config;
|
|
173
|
-
if (percent === 1) {
|
|
174
|
-
for (const item of items) {
|
|
175
|
-
clearSourceResult(item);
|
|
176
|
-
}
|
|
177
|
-
items.length = 0;
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
items.sort((a, b) => a[2] - b[2]);
|
|
181
|
-
for (let i = 0, length = Math.floor(items.length * percent); i < length; ++i) {
|
|
182
|
-
const item = items[i];
|
|
183
|
-
if (min === 0 || item[3] < min) {
|
|
184
|
-
clearSourceResult(item);
|
|
185
|
-
items.splice(i--, 1);
|
|
186
|
-
--length;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
items.push(data);
|
|
192
|
-
}
|
|
193
|
-
function deleteSourceResult(source, data) {
|
|
194
|
-
const stored = CACHE_SOURCE[source];
|
|
195
|
-
if (stored) {
|
|
196
|
-
const items = stored.items;
|
|
197
|
-
const index = items.findIndex(item => item === data);
|
|
198
|
-
if (index !== -1) {
|
|
199
|
-
items.splice(index, 1);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
function incrementSourceCount(source, data, cacheData, queryString) {
|
|
204
|
-
const count = ++data[3];
|
|
205
|
-
const stored = CACHE_SOURCE[source];
|
|
206
|
-
if (stored?.config && count >= stored.config.max) {
|
|
207
|
-
clearSourceResult(data);
|
|
208
|
-
deleteSourceResult(source, data);
|
|
209
|
-
if (cacheData && queryString) {
|
|
210
|
-
delete cacheData[queryString];
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
161
|
function getSettingsValue(options, name, component) {
|
|
215
162
|
const result = options[name];
|
|
216
163
|
return component ? (0, types_1.isObject)(result) ? result[component] : undefined : result;
|
|
217
164
|
}
|
|
218
165
|
function isInvalidRange(result, range) {
|
|
219
166
|
const [lower, upper = 0] = range;
|
|
220
|
-
return result.length <= lower || upper > 0 && result.length > upper;
|
|
167
|
+
return Array.isArray(result) && (result.length <= lower || upper > 0 && result.length > upper);
|
|
221
168
|
}
|
|
222
169
|
function asPosix(value) {
|
|
223
170
|
if (module_1.PLATFORM_WIN32) {
|
|
@@ -251,6 +198,192 @@ function parseIp(value, kind) {
|
|
|
251
198
|
const readable = (value) => (0, types_1.isString)(value) || (0, types_1.isArray)(value);
|
|
252
199
|
const expireTime = (value) => Date.now() + value * 1000;
|
|
253
200
|
const convertSeconds = (value) => typeof value === 'string' && Math.ceil((0, types_1.parseTime)(value) / 1000) || 0;
|
|
201
|
+
class DbLRU {
|
|
202
|
+
static get(source) {
|
|
203
|
+
return CACHE_SOURCE[source] ||= new DbLRU();
|
|
204
|
+
}
|
|
205
|
+
static purge(source, value) {
|
|
206
|
+
const target = this.get(source);
|
|
207
|
+
const items = target.items;
|
|
208
|
+
for (let i = 0, length = items.length; i < length; ++i) {
|
|
209
|
+
const item = items[i];
|
|
210
|
+
if (item.value === value) {
|
|
211
|
+
item.delete(false);
|
|
212
|
+
items.splice(i, 1);
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
items = [];
|
|
219
|
+
config = null;
|
|
220
|
+
refresh(percent) {
|
|
221
|
+
const { items, config } = this;
|
|
222
|
+
let result = 0;
|
|
223
|
+
if (config && items.length >= config.limit || percent) {
|
|
224
|
+
percent = Math.min(1, percent ?? config.percent);
|
|
225
|
+
if (percent === 1) {
|
|
226
|
+
result = items.length;
|
|
227
|
+
for (let i = 0; i < result; ++i) {
|
|
228
|
+
items[i].delete(false);
|
|
229
|
+
}
|
|
230
|
+
items.length = 0;
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
const min = config?.min || 0;
|
|
234
|
+
const data = items.slice(0).sort((a, b) => a.lastAccessed - b.lastAccessed);
|
|
235
|
+
for (let i = 0, length = Math.floor(data.length * Math.min(percent, 1)); i < length; ++i) {
|
|
236
|
+
const item = data[i];
|
|
237
|
+
if (min === 0 || item.accessCount < min) {
|
|
238
|
+
item.delete(true);
|
|
239
|
+
++result;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return result;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
class DbCache {
|
|
248
|
+
source;
|
|
249
|
+
user;
|
|
250
|
+
query;
|
|
251
|
+
value;
|
|
252
|
+
expires;
|
|
253
|
+
accessCount = 0;
|
|
254
|
+
lastAccessed = Date.now();
|
|
255
|
+
disposed = false;
|
|
256
|
+
userData;
|
|
257
|
+
queryData;
|
|
258
|
+
sourceList;
|
|
259
|
+
constructor(source, user, query, value, expires) {
|
|
260
|
+
this.source = source;
|
|
261
|
+
this.user = user;
|
|
262
|
+
this.query = query;
|
|
263
|
+
this.value = value;
|
|
264
|
+
this.expires = expires;
|
|
265
|
+
this.userData = CACHE_USER[source] ||= Object.create(null);
|
|
266
|
+
this.queryData = this.userData[user] ||= Object.create(null);
|
|
267
|
+
this.queryData[query] = this;
|
|
268
|
+
this.sourceList = DbLRU.get(source);
|
|
269
|
+
this.sourceList.refresh();
|
|
270
|
+
this.sourceList.items.push(this);
|
|
271
|
+
}
|
|
272
|
+
get(seconds) {
|
|
273
|
+
const current = Date.now();
|
|
274
|
+
if (seconds > 0) {
|
|
275
|
+
this.expires = expireTime(seconds);
|
|
276
|
+
}
|
|
277
|
+
else if (current >= this.expires) {
|
|
278
|
+
this.delete(true);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
let result = this.value;
|
|
282
|
+
if (typeof result === 'string') {
|
|
283
|
+
try {
|
|
284
|
+
result = JSON.parse(fs.readFileSync(result, 'utf8'));
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
result = null;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (Array.isArray(result)) {
|
|
291
|
+
this.update(current);
|
|
292
|
+
return result;
|
|
293
|
+
}
|
|
294
|
+
this.delete(true);
|
|
295
|
+
}
|
|
296
|
+
update(current) {
|
|
297
|
+
const count = ++this.accessCount;
|
|
298
|
+
const config = this.sourceList.config;
|
|
299
|
+
if (config && count >= config.max) {
|
|
300
|
+
this.delete(true);
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
this.lastAccessed = current;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
delete(lru) {
|
|
307
|
+
if (!this.disposed) {
|
|
308
|
+
const value = this.value;
|
|
309
|
+
this.value = null;
|
|
310
|
+
this.queryData[this.query] = null;
|
|
311
|
+
this.disposed = true;
|
|
312
|
+
if (lru) {
|
|
313
|
+
const items = this.sourceList.items;
|
|
314
|
+
const index = items.findIndex(item => item === this);
|
|
315
|
+
if (index !== -1) {
|
|
316
|
+
items.splice(index, 1);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
void this.cleanup(value);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
async cleanup(value) {
|
|
323
|
+
const data = this.queryData;
|
|
324
|
+
let found = false;
|
|
325
|
+
for (const query in data) {
|
|
326
|
+
if (data[query]) {
|
|
327
|
+
found = true;
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (!found) {
|
|
332
|
+
delete this.userData[this.user];
|
|
333
|
+
}
|
|
334
|
+
if (typeof value === 'string') {
|
|
335
|
+
try {
|
|
336
|
+
fs.unlinkSync(value);
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
expired(current) {
|
|
343
|
+
if (current >= this.expires) {
|
|
344
|
+
this.delete(true);
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
class DbSession {
|
|
351
|
+
source;
|
|
352
|
+
sourceData = Object.create(null);
|
|
353
|
+
constructor(source) {
|
|
354
|
+
this.source = source;
|
|
355
|
+
const timer = setInterval(() => {
|
|
356
|
+
this.clear();
|
|
357
|
+
if (this.users.length === 0) {
|
|
358
|
+
CACHE_SESSION[source] = undefined;
|
|
359
|
+
clearInterval(timer);
|
|
360
|
+
}
|
|
361
|
+
}, 60000);
|
|
362
|
+
}
|
|
363
|
+
set(user, key, result, seconds) {
|
|
364
|
+
let data = this.sourceData[user];
|
|
365
|
+
if (!data) {
|
|
366
|
+
data = [Object.create(null), Date.now() + Math.trunc(seconds * 1000)];
|
|
367
|
+
this.sourceData[user] = data;
|
|
368
|
+
}
|
|
369
|
+
data[0][key] = result;
|
|
370
|
+
}
|
|
371
|
+
get(user, key) {
|
|
372
|
+
return this.sourceData[user]?.[0][key];
|
|
373
|
+
}
|
|
374
|
+
clear() {
|
|
375
|
+
const current = Date.now();
|
|
376
|
+
for (const user of this.users) {
|
|
377
|
+
const expires = this.sourceData[user][1];
|
|
378
|
+
if (expires >= current) {
|
|
379
|
+
delete this.sourceData[user];
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
get users() {
|
|
384
|
+
return Object.keys(this.sourceData);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
254
387
|
class Host extends module_1 {
|
|
255
388
|
static [kHost] = true;
|
|
256
389
|
static async purgeMemory(percent = 1, limit = 0, parent) {
|
|
@@ -897,7 +1030,6 @@ class ClientDb extends Client {
|
|
|
897
1030
|
const item = client[source];
|
|
898
1031
|
if ((0, types_1.isPlainObject)(item) && 'enabled' in item) {
|
|
899
1032
|
const key = name + '_' + source;
|
|
900
|
-
const stored = CACHE_SOURCE[key];
|
|
901
1033
|
const { enabled, limit = 0, min = 0, max = 0 } = item;
|
|
902
1034
|
if (enabled && +limit > 0) {
|
|
903
1035
|
let percent = item.percent || 0;
|
|
@@ -908,11 +1040,16 @@ class ClientDb extends Client {
|
|
|
908
1040
|
percent /= 100;
|
|
909
1041
|
}
|
|
910
1042
|
if (percent > 0) {
|
|
911
|
-
(
|
|
1043
|
+
DbLRU.get(key).config = {
|
|
1044
|
+
limit: +limit,
|
|
1045
|
+
percent: Math.min(percent, 1),
|
|
1046
|
+
min: min > 0 ? min : 0,
|
|
1047
|
+
max: max > 0 ? max : Infinity
|
|
1048
|
+
};
|
|
912
1049
|
}
|
|
913
1050
|
}
|
|
914
|
-
else if (
|
|
915
|
-
|
|
1051
|
+
else if (CACHE_SOURCE[key]) {
|
|
1052
|
+
CACHE_SOURCE[key].config = null;
|
|
916
1053
|
}
|
|
917
1054
|
}
|
|
918
1055
|
}
|
|
@@ -959,96 +1096,63 @@ class ClientDb extends Client {
|
|
|
959
1096
|
}
|
|
960
1097
|
static findResult(source, credential, queryString, timeout, sessionKey, renewCache) {
|
|
961
1098
|
const userKey = credential ? this.extractUUID(credential) || (0, types_1.hashKey)(this.asString(credential)) : undefined;
|
|
962
|
-
if (
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
let stored;
|
|
969
|
-
if (!(userCache && (stored = userCache[queryString]))) {
|
|
970
|
-
return;
|
|
971
|
-
}
|
|
972
|
-
const [expires, result] = stored;
|
|
973
|
-
if (result) {
|
|
974
|
-
const current = Date.now();
|
|
975
|
-
let valid = false;
|
|
976
|
-
if (renewCache) {
|
|
977
|
-
stored[0] = expireTime(timeout);
|
|
978
|
-
valid = true;
|
|
979
|
-
}
|
|
980
|
-
else if (current < expires) {
|
|
981
|
-
valid = true;
|
|
982
|
-
}
|
|
983
|
-
if (valid) {
|
|
984
|
-
stored[2] = current;
|
|
985
|
-
incrementSourceCount(source, stored, userCache, queryString);
|
|
986
|
-
if (Array.isArray(result)) {
|
|
987
|
-
return result;
|
|
988
|
-
}
|
|
989
|
-
try {
|
|
990
|
-
return JSON.parse(fs.readFileSync(result, 'utf8'));
|
|
991
|
-
}
|
|
992
|
-
catch {
|
|
993
|
-
}
|
|
1099
|
+
if (userKey) {
|
|
1100
|
+
queryString = (0, types_1.hashKey)(queryString);
|
|
1101
|
+
if (timeout > 0) {
|
|
1102
|
+
const stored = CACHE_USER[source]?.[userKey]?.[queryString];
|
|
1103
|
+
if (stored) {
|
|
1104
|
+
return stored.get(renewCache ? timeout : 0);
|
|
994
1105
|
}
|
|
995
|
-
clearSourceResult(stored);
|
|
996
1106
|
}
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
else if (sessionKey) {
|
|
1001
|
-
return CACHE_SESSION[source]?.[userKey + sessionKey]?.[queryString];
|
|
1107
|
+
else if (sessionKey) {
|
|
1108
|
+
return this.findSession(source, userKey + sessionKey, queryString);
|
|
1109
|
+
}
|
|
1002
1110
|
}
|
|
1003
1111
|
}
|
|
1004
|
-
static storeResult(source, credential, queryString, result,
|
|
1005
|
-
if (!credential) {
|
|
1112
|
+
static storeResult(source, credential, queryString, result, cache, sessionKey, sessionExpires) {
|
|
1113
|
+
if (!credential || !Array.isArray(result)) {
|
|
1006
1114
|
return result;
|
|
1007
1115
|
}
|
|
1008
|
-
let
|
|
1116
|
+
let cacheDir;
|
|
1009
1117
|
if ((0, types_1.isObject)(sessionKey)) {
|
|
1010
1118
|
({ cacheDir, sessionKey, sessionExpires } = sessionKey);
|
|
1011
1119
|
}
|
|
1012
|
-
else if ((0, types_1.isObject)(
|
|
1013
|
-
({ cache, cacheDir, sessionKey, sessionExpires } =
|
|
1120
|
+
else if ((0, types_1.isObject)(cache) && 'cache' in cache) {
|
|
1121
|
+
({ cache, cacheDir, sessionKey, sessionExpires } = cache);
|
|
1014
1122
|
}
|
|
1015
1123
|
let timeout = 0, userKey, whenEmpty, partition = false;
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
}
|
|
1027
|
-
timeout = convertSeconds(cache);
|
|
1028
|
-
break;
|
|
1029
|
-
case 'object': {
|
|
1030
|
-
let seconds, dir;
|
|
1031
|
-
({ timeout: seconds, when_empty: whenEmpty, dir } = cache);
|
|
1032
|
-
if ((0, types_1.isString)(dir) && (!cacheDir || module_1.isDir(dir))) {
|
|
1033
|
-
cacheDir = dir;
|
|
1034
|
-
partition = true;
|
|
1035
|
-
}
|
|
1036
|
-
if (typeof seconds === 'number') {
|
|
1037
|
-
timeout = seconds;
|
|
1038
|
-
}
|
|
1039
|
-
else {
|
|
1040
|
-
cache.timeout = seconds ? convertSeconds(seconds) : 0;
|
|
1041
|
-
}
|
|
1042
|
-
break;
|
|
1124
|
+
switch (typeof cache) {
|
|
1125
|
+
case 'object': {
|
|
1126
|
+
let seconds, dir;
|
|
1127
|
+
({ timeout: seconds, when_empty: whenEmpty, dir } = cache);
|
|
1128
|
+
if (dir && (!cacheDir || module_1.isDir(dir))) {
|
|
1129
|
+
cacheDir = dir;
|
|
1130
|
+
partition = true;
|
|
1131
|
+
}
|
|
1132
|
+
if (typeof seconds === 'number') {
|
|
1133
|
+
timeout = seconds;
|
|
1043
1134
|
}
|
|
1135
|
+
else {
|
|
1136
|
+
cache.timeout = seconds ? timeout = convertSeconds(seconds) : 0;
|
|
1137
|
+
}
|
|
1138
|
+
break;
|
|
1044
1139
|
}
|
|
1140
|
+
case 'number':
|
|
1141
|
+
timeout = cache;
|
|
1142
|
+
break;
|
|
1143
|
+
case 'string':
|
|
1144
|
+
if (typeof sessionKey === 'number') {
|
|
1145
|
+
sessionExpires = sessionKey;
|
|
1146
|
+
sessionKey = cache;
|
|
1147
|
+
break;
|
|
1148
|
+
}
|
|
1149
|
+
timeout = convertSeconds(cache);
|
|
1150
|
+
break;
|
|
1045
1151
|
}
|
|
1046
1152
|
if ((result.length > 0 || whenEmpty) && (userKey = this.extractUUID(credential) || (0, types_1.hashKey)(this.asString(credential)))) {
|
|
1047
1153
|
queryString = (0, types_1.hashKey)(queryString);
|
|
1048
1154
|
if (timeout > 0) {
|
|
1049
|
-
const item =
|
|
1050
|
-
((CACHE_USER[source] ||= {})[userKey] ||= {})[queryString] = item;
|
|
1051
|
-
addSourceResult(source, item);
|
|
1155
|
+
const item = new DbCache(source, userKey, queryString, result, expireTime(timeout));
|
|
1052
1156
|
if (cacheDir) {
|
|
1053
1157
|
if (partition) {
|
|
1054
1158
|
if (STORE_RESULT_COUNT === this.STORE_RESULT_PARTITION_SIZE) {
|
|
@@ -1062,61 +1166,62 @@ class ClientDb extends Client {
|
|
|
1062
1166
|
const pathname = path.join(cacheDir, queryString);
|
|
1063
1167
|
fs.writeFile(pathname, JSON.stringify(result), err => {
|
|
1064
1168
|
if (!err) {
|
|
1065
|
-
item
|
|
1169
|
+
item.value = pathname;
|
|
1066
1170
|
}
|
|
1067
1171
|
});
|
|
1068
1172
|
}
|
|
1069
1173
|
}
|
|
1070
|
-
else if (typeof sessionKey === 'string' && sessionExpires && sessionExpires > 0) {
|
|
1071
|
-
|
|
1072
|
-
((CACHE_SESSION[source] ||= {})[dbKey] ||= {})[queryString] = result;
|
|
1073
|
-
setTimeout(() => delete CACHE_SESSION[dbKey], sessionExpires * 1000);
|
|
1174
|
+
else if (typeof sessionKey === 'string' && typeof sessionExpires === 'number' && sessionExpires > 0) {
|
|
1175
|
+
this.storeSession(source, userKey + sessionKey, queryString, result, sessionExpires);
|
|
1074
1176
|
}
|
|
1075
1177
|
}
|
|
1076
1178
|
return result;
|
|
1077
1179
|
}
|
|
1078
|
-
static
|
|
1079
|
-
|
|
1080
|
-
|
|
1180
|
+
static findSession(source, user, key) {
|
|
1181
|
+
return CACHE_SESSION[source]?.get(user, key);
|
|
1182
|
+
}
|
|
1183
|
+
static storeSession(source, user, key, result, expires = 600) {
|
|
1184
|
+
(CACHE_SESSION[source] ||= new DbSession(source)).set(user, key, result, expires);
|
|
1185
|
+
}
|
|
1186
|
+
static async purgeResult(prefix, lru) {
|
|
1187
|
+
const cache = lru ? CACHE_SOURCE : CACHE_USER;
|
|
1188
|
+
const items = [];
|
|
1081
1189
|
if (prefix) {
|
|
1082
1190
|
if (!prefix.includes('_')) {
|
|
1083
1191
|
prefix += '_';
|
|
1084
|
-
for (const key in
|
|
1192
|
+
for (const key in cache) {
|
|
1085
1193
|
if (key.startsWith(prefix)) {
|
|
1086
|
-
|
|
1194
|
+
items.push(cache[key]);
|
|
1087
1195
|
}
|
|
1088
1196
|
}
|
|
1089
1197
|
}
|
|
1090
|
-
else {
|
|
1091
|
-
|
|
1092
|
-
if (source) {
|
|
1093
|
-
providers.set(prefix, source);
|
|
1094
|
-
}
|
|
1198
|
+
else if (cache[prefix]) {
|
|
1199
|
+
items.push(cache[prefix]);
|
|
1095
1200
|
}
|
|
1096
1201
|
}
|
|
1097
1202
|
else {
|
|
1098
|
-
for (const key in
|
|
1099
|
-
|
|
1203
|
+
for (const key in cache) {
|
|
1204
|
+
items.push(cache[key]);
|
|
1100
1205
|
}
|
|
1101
1206
|
}
|
|
1102
1207
|
let result = 0;
|
|
1103
|
-
|
|
1104
|
-
for (const
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1208
|
+
if (lru) {
|
|
1209
|
+
for (const source of items) {
|
|
1210
|
+
result += source.refresh(typeof lru === 'number' ? lru : undefined);
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
else {
|
|
1214
|
+
const current = Date.now();
|
|
1215
|
+
for (const source of items) {
|
|
1216
|
+
for (const session in source) {
|
|
1217
|
+
const data = source[session];
|
|
1218
|
+
for (const query in data) {
|
|
1219
|
+
const item = data[query];
|
|
1220
|
+
if (item.expired(current)) {
|
|
1221
|
+
++result;
|
|
1114
1222
|
}
|
|
1115
1223
|
}
|
|
1116
1224
|
}
|
|
1117
|
-
if (Object.keys(queries).length === 0) {
|
|
1118
|
-
delete data[user];
|
|
1119
|
-
}
|
|
1120
1225
|
}
|
|
1121
1226
|
}
|
|
1122
1227
|
return result;
|
|
@@ -1202,14 +1307,14 @@ class ClientDb extends Client {
|
|
|
1202
1307
|
break;
|
|
1203
1308
|
case 'object':
|
|
1204
1309
|
if (options !== null) {
|
|
1205
|
-
({ value, sessionKey,
|
|
1310
|
+
({ value, sessionKey, exclusiveOf, renewCache } = options);
|
|
1206
1311
|
if (Array.isArray(exclusiveOf)) {
|
|
1207
1312
|
const ignoreCache = exclusiveOf[2];
|
|
1208
1313
|
if (ignoreCache === 1) {
|
|
1209
1314
|
return;
|
|
1210
1315
|
}
|
|
1211
1316
|
renewCache ||= ignoreCache === 0;
|
|
1212
|
-
queryString += '_' + exclusiveOf.toString();
|
|
1317
|
+
queryString += '_' + exclusiveOf.slice(0, 2).toString();
|
|
1213
1318
|
}
|
|
1214
1319
|
}
|
|
1215
1320
|
break;
|
|
@@ -1221,8 +1326,14 @@ class ClientDb extends Client {
|
|
|
1221
1326
|
value = cache;
|
|
1222
1327
|
}
|
|
1223
1328
|
}
|
|
1224
|
-
const result = ClientDb.findResult(this.
|
|
1225
|
-
if (
|
|
1329
|
+
const result = ClientDb.findResult(this.getSourceName(source), uuidKey || credential, queryString, value === 0 ? 0 : ClientDb.getTimeout(value || this.settingsOf(source, 'cache')), sessionKey, renewCache);
|
|
1330
|
+
if (result) {
|
|
1331
|
+
if (exclusiveOf && isInvalidRange(result, exclusiveOf)) {
|
|
1332
|
+
if (exclusiveOf[2] === 2) {
|
|
1333
|
+
DbLRU.purge(this.getSourceName(source), result);
|
|
1334
|
+
}
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1226
1337
|
return result;
|
|
1227
1338
|
}
|
|
1228
1339
|
}
|
|
@@ -1234,30 +1345,37 @@ class ClientDb extends Client {
|
|
|
1234
1345
|
return result;
|
|
1235
1346
|
}
|
|
1236
1347
|
const uuidKey = ClientDb.extractUUID(credential);
|
|
1237
|
-
let
|
|
1238
|
-
if (
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1348
|
+
let value, exclusiveOf;
|
|
1349
|
+
if ((0, types_1.isObject)(sessionKey)) {
|
|
1350
|
+
({ value, sessionKey, exclusiveOf } = sessionKey);
|
|
1351
|
+
}
|
|
1352
|
+
if (Array.isArray(exclusiveOf)) {
|
|
1353
|
+
if (isInvalidRange(result, exclusiveOf)) {
|
|
1354
|
+
return result;
|
|
1242
1355
|
}
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1356
|
+
queryString += '_' + exclusiveOf.slice(0, 2).toString();
|
|
1357
|
+
}
|
|
1358
|
+
if (uuidKey) {
|
|
1359
|
+
const cache = this.settingsKey(uuidKey, 'cache');
|
|
1360
|
+
if (cache !== undefined) {
|
|
1361
|
+
value = cache;
|
|
1248
1362
|
}
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1363
|
+
}
|
|
1364
|
+
const cacheDir = this.cacheDir;
|
|
1365
|
+
value ??= this.settingsOf(source, 'cache');
|
|
1366
|
+
let options;
|
|
1367
|
+
if (this.hasPermission('memory')) {
|
|
1368
|
+
if (cacheDir || sessionKey) {
|
|
1369
|
+
options = { cacheDir, sessionKey, sessionExpires: this.cacheExpires / 1000 };
|
|
1254
1370
|
}
|
|
1255
|
-
options = { cache: value === 0 ? 0 : value || this.settingsOf(source, 'cache'), cacheDir: this.cacheDir, sessionKey, sessionExpires: this.cacheExpires / 1000 };
|
|
1256
1371
|
}
|
|
1257
|
-
else {
|
|
1258
|
-
options = { cacheDir
|
|
1372
|
+
else if (cacheDir) {
|
|
1373
|
+
options = { cacheDir };
|
|
1374
|
+
}
|
|
1375
|
+
else if (!(0, types_1.isObject)(value) || !(0, types_1.isString)(value.dir)) {
|
|
1376
|
+
return result;
|
|
1259
1377
|
}
|
|
1260
|
-
return ClientDb.storeResult(this.
|
|
1378
|
+
return value || options ? ClientDb.storeResult(this.getSourceName(source), uuidKey || credential, queryString, result, value, options) : result;
|
|
1261
1379
|
}
|
|
1262
1380
|
getCacheResult(source, credential, queryString, cacheValue, ignoreCache) {
|
|
1263
1381
|
if (ignoreCache !== 1) {
|
|
@@ -1302,6 +1420,9 @@ class ClientDb extends Client {
|
|
|
1302
1420
|
return getSettingsValue(data, name, component);
|
|
1303
1421
|
}
|
|
1304
1422
|
}
|
|
1423
|
+
getSourceName(value) {
|
|
1424
|
+
return this.moduleName + '_' + value;
|
|
1425
|
+
}
|
|
1305
1426
|
get pending() {
|
|
1306
1427
|
return this.database.filter(item => {
|
|
1307
1428
|
const state = item.transactionState || 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e-mc/core",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.6",
|
|
4
4
|
"description": "Core modules for E-mc.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"license": "BSD-3-Clause",
|
|
20
20
|
"homepage": "https://github.com/anpham6/e-mc#readme",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@e-mc/module": "0.13.
|
|
23
|
-
"@e-mc/types": "0.13.
|
|
22
|
+
"@e-mc/module": "0.13.6",
|
|
23
|
+
"@e-mc/types": "0.13.6",
|
|
24
24
|
"ipaddr.js": "^2.3.0",
|
|
25
25
|
"picomatch": "^4.0.3"
|
|
26
26
|
}
|