@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.
Files changed (3) hide show
  1. package/README.md +13 -10
  2. package/index.js +308 -187
  3. 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.5/lib/index.d.ts)
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
- purgeResult(prefix?: string): Promise<number>;
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.5/lib/squared.d.ts
323
- - https://www.unpkg.com/@e-mc/types@0.13.5/lib/core.d.ts
324
- - https://www.unpkg.com/@e-mc/types@0.13.5/lib/db.d.ts
325
- - https://www.unpkg.com/@e-mc/types@0.13.5/lib/dom.d.ts
326
- - https://www.unpkg.com/@e-mc/types@0.13.5/lib/logger.d.ts
327
- - https://www.unpkg.com/@e-mc/types@0.13.5/lib/node.d.ts
328
- - https://www.unpkg.com/@e-mc/types@0.13.5/lib/settings.d.ts
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: (0, types_1.supported)(19, 4) || (0, types_1.supported)(18, 14, true) ? os.availableParallelism() : os.cpus().length,
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
- (stored || (CACHE_SOURCE[key] = { items: [] })).config = { limit: +limit > 0 ? +limit : 0, percent: Math.min(percent, 1), min: min > 0 ? min : 0, max: max > 0 ? max : Infinity };
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 (stored) {
915
- delete stored.config;
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 (!userKey) {
963
- return;
964
- }
965
- queryString = (0, types_1.hashKey)(queryString);
966
- if (timeout > 0) {
967
- const userCache = CACHE_USER[source]?.[userKey];
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
- deleteSourceResult(source, stored);
998
- delete userCache[queryString];
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, options, sessionKey, sessionExpires) {
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 cache, cacheDir;
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)(options) && 'cache' in options) {
1013
- ({ cache, cacheDir, sessionKey, sessionExpires } = options);
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
- if (cache) {
1017
- switch (typeof cache) {
1018
- case 'number':
1019
- timeout = cache;
1020
- break;
1021
- case 'string':
1022
- if (typeof sessionKey === 'number') {
1023
- sessionExpires = sessionKey;
1024
- sessionKey = cache;
1025
- break;
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 = [expireTime(timeout), result, Date.now(), 0];
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[1] = pathname;
1169
+ item.value = pathname;
1066
1170
  }
1067
1171
  });
1068
1172
  }
1069
1173
  }
1070
- else if (typeof sessionKey === 'string' && sessionExpires && sessionExpires > 0) {
1071
- const dbKey = userKey + sessionKey;
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 async purgeResult(prefix) {
1079
- const current = Date.now();
1080
- const providers = new Map();
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 CACHE_USER) {
1192
+ for (const key in cache) {
1085
1193
  if (key.startsWith(prefix)) {
1086
- providers.set(key, CACHE_USER[key]);
1194
+ items.push(cache[key]);
1087
1195
  }
1088
1196
  }
1089
1197
  }
1090
- else {
1091
- const source = CACHE_USER[prefix];
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 CACHE_USER) {
1099
- providers.set(key, CACHE_USER[key]);
1203
+ for (const key in cache) {
1204
+ items.push(cache[key]);
1100
1205
  }
1101
1206
  }
1102
1207
  let result = 0;
1103
- for (const [source, data] of providers) {
1104
- for (const user in data) {
1105
- const queries = data[user];
1106
- for (const query in queries) {
1107
- const item = queries[query];
1108
- if (current >= item[0]) {
1109
- ++result;
1110
- delete queries[query];
1111
- deleteSourceResult(source, item);
1112
- if (typeof item[1] === 'string') {
1113
- fs.unlink(item[1], () => { });
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, renewCache, exclusiveOf } = options);
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.moduleName + '_' + source, uuidKey || credential, queryString, value === 0 ? 0 : ClientDb.getTimeout(value || this.settingsOf(source, 'cache')), sessionKey, renewCache);
1225
- if (!exclusiveOf || !isInvalidRange(result, exclusiveOf)) {
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 options;
1238
- if (this.hasPermission('memory')) {
1239
- let value, exclusiveOf;
1240
- if ((0, types_1.isObject)(sessionKey)) {
1241
- ({ value, sessionKey, exclusiveOf } = sessionKey);
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
- if (Array.isArray(exclusiveOf)) {
1244
- if (isInvalidRange(result, exclusiveOf)) {
1245
- return result;
1246
- }
1247
- queryString += '_' + exclusiveOf.toString();
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
- if (uuidKey) {
1250
- const cache = this.settingsKey(uuidKey, 'cache');
1251
- if (cache !== undefined) {
1252
- value = cache;
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: this.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.moduleName + '_' + source, uuidKey || credential, queryString, result, options);
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.5",
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.5",
23
- "@e-mc/types": "0.13.5",
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
  }