@e-mc/core 0.13.6 → 0.13.7
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 -11
- package/index.js +394 -275
- 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.7/lib/index.d.ts)
|
|
13
13
|
|
|
14
14
|
```typescript
|
|
15
15
|
import type { DataSource, LogStatus, WorkerAction } from "./squared";
|
|
@@ -74,6 +74,7 @@ interface HostConstructor extends ModuleConstructor {
|
|
|
74
74
|
getThreadCount(full: true): ThreadCountStat;
|
|
75
75
|
getThreadCount(username: string, iv?: BinaryLike): ThreadCountStat;
|
|
76
76
|
getThreadCount(username?: string | boolean, iv?: BinaryLike): number;
|
|
77
|
+
parseIp(value: unknown, kind?: "ipv4" | "ipv6"): string;
|
|
77
78
|
getPermissionFromSettings(freeze?: boolean): IPermission;
|
|
78
79
|
readonly prototype: IHost;
|
|
79
80
|
new(config?: HostInitConfig): IHost;
|
|
@@ -102,11 +103,11 @@ interface IClientDb extends IClient<IHost, ClientModule<ClientDbSettings>> {
|
|
|
102
103
|
hasCache(source: string, sessionKey?: string): boolean;
|
|
103
104
|
hasCoerce(source: string, component: keyof DbCoerceSettings, uuidKey: string | undefined): boolean;
|
|
104
105
|
hasCoerce(source: string, component: keyof DbCoerceSettings, credential?: unknown): boolean;
|
|
106
|
+
getQueryResult(source: string, credential: unknown, queryString: string, options: CacheOptions): QueryResult | undefined;
|
|
105
107
|
getQueryResult(source: string, credential: unknown, queryString: string, renewCache: boolean): QueryResult | undefined;
|
|
106
108
|
getQueryResult(source: string, credential: unknown, queryString: string, sessionKey?: string, renewCache?: boolean): QueryResult | undefined;
|
|
107
|
-
|
|
109
|
+
setQueryResult(source: string, credential: unknown, queryString: string, result: unknown, options: CacheOptions): QueryResult;
|
|
108
110
|
setQueryResult(source: string, credential: unknown, queryString: string, result: unknown, sessionKey?: string): QueryResult;
|
|
109
|
-
setQueryResult(source: string, credential: unknown, queryString: string, result: unknown, options?: CacheOptions): QueryResult;
|
|
110
111
|
getCacheResult(source: string, credential: unknown, queryString: string, cacheValue: CacheOptions, ignoreCache?: unknown): QueryResult | undefined;
|
|
111
112
|
applyState(items: DataSource | DataSource[], value: number, as?: boolean): void;
|
|
112
113
|
commit(items?: DataSource[]): Promise<boolean>;
|
|
@@ -130,7 +131,8 @@ interface ClientDbConstructor extends ClientConstructor<IHost, ClientModule> {
|
|
|
130
131
|
loadSettings(settings: Pick<Settings, "process" | "memory">, password?: string): boolean;
|
|
131
132
|
getTimeout(value: number | string | TimeoutAction | undefined): number;
|
|
132
133
|
convertTime(value: number | string): number;
|
|
133
|
-
findResult(source: string, credential: unknown, queryString: string, timeout: number,
|
|
134
|
+
findResult(source: string, credential: unknown, queryString: string, timeout: number, renewCache: boolean): QueryResult | undefined;
|
|
135
|
+
findResult(source: string, credential: unknown, queryString: string, timeout: number, sessionKey?: string, renewCache?: boolean): QueryResult | undefined;
|
|
134
136
|
storeResult(source: string, credential: unknown, queryString: string, result: QueryResult, options: StoreResultOptions): QueryResult;
|
|
135
137
|
/** @deprecated */
|
|
136
138
|
storeResult(source: string, credential: unknown, queryString: string, result: QueryResult, sessionKey: string, sessionExpires: number): QueryResult;
|
|
@@ -322,13 +324,13 @@ NOTE: **@e-mc/core** is mostly a collection of abstract base classes which canno
|
|
|
322
324
|
|
|
323
325
|
## References
|
|
324
326
|
|
|
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.
|
|
329
|
-
- https://www.unpkg.com/@e-mc/types@0.13.
|
|
330
|
-
- https://www.unpkg.com/@e-mc/types@0.13.
|
|
331
|
-
- https://www.unpkg.com/@e-mc/types@0.13.
|
|
327
|
+
- https://www.unpkg.com/@e-mc/types@0.13.7/lib/squared.d.ts
|
|
328
|
+
- https://www.unpkg.com/@e-mc/types@0.13.7/lib/core.d.ts
|
|
329
|
+
- https://www.unpkg.com/@e-mc/types@0.13.7/lib/db.d.ts
|
|
330
|
+
- https://www.unpkg.com/@e-mc/types@0.13.7/lib/dom.d.ts
|
|
331
|
+
- https://www.unpkg.com/@e-mc/types@0.13.7/lib/logger.d.ts
|
|
332
|
+
- https://www.unpkg.com/@e-mc/types@0.13.7/lib/node.d.ts
|
|
333
|
+
- https://www.unpkg.com/@e-mc/types@0.13.7/lib/settings.d.ts
|
|
332
334
|
|
|
333
335
|
* https://www.npmjs.com/package/@types/node
|
|
334
336
|
|
package/index.js
CHANGED
|
@@ -19,15 +19,8 @@ const CACHE_SOURCE = Object.create(null);
|
|
|
19
19
|
const CACHE_SESSION = Object.create(null);
|
|
20
20
|
const ABORT_LISTENER = new WeakMap();
|
|
21
21
|
const HOST = {
|
|
22
|
-
DONE: new Map(),
|
|
23
|
-
QUEUE: [],
|
|
24
22
|
QUEUE_LIMIT: Infinity,
|
|
25
23
|
QUEUE_EXPIRES: 86400000,
|
|
26
|
-
PID: 1,
|
|
27
|
-
CLOSED: 0,
|
|
28
|
-
QUEUED: 0,
|
|
29
|
-
REJECTED: 0,
|
|
30
|
-
KILLED: 0,
|
|
31
24
|
CIPHER: null,
|
|
32
25
|
ADMIN_USERS: [],
|
|
33
26
|
ADMIN_PRIVATE: false,
|
|
@@ -35,11 +28,7 @@ const HOST = {
|
|
|
35
28
|
THREAD_EXPIRES: 86400000,
|
|
36
29
|
PRIORITY_MIN: 0,
|
|
37
30
|
PRIORITY_MAX: 100,
|
|
38
|
-
PRIORITY_BYPASS: undefined
|
|
39
|
-
LOG_PROGRESS: null,
|
|
40
|
-
LOG_DELAYED: [],
|
|
41
|
-
LOG_PROGRESS_QUEUE: new WeakSet(),
|
|
42
|
-
LOG_PROGRESS_PAUSED: new Set()
|
|
31
|
+
PRIORITY_BYPASS: undefined
|
|
43
32
|
};
|
|
44
33
|
const WORKER_GROUP = {
|
|
45
34
|
MAX: module_1.availableParallelism(),
|
|
@@ -49,119 +38,23 @@ const WORKER_GROUP = {
|
|
|
49
38
|
const WORKER_CHANNEL = {
|
|
50
39
|
MIN: 0,
|
|
51
40
|
MAX: Math.max(WORKER_GROUP.MAX / 2, 2),
|
|
52
|
-
TIMEOUT:
|
|
41
|
+
TIMEOUT: 5 * 60000,
|
|
53
42
|
VERBOSE: true
|
|
54
43
|
};
|
|
44
|
+
const GC = {
|
|
45
|
+
EXPIRES: 600,
|
|
46
|
+
EXPIRES_LIMIT: 2592000,
|
|
47
|
+
EXPIRES_DEFAULT: false,
|
|
48
|
+
INTERVAL: 60000
|
|
49
|
+
};
|
|
55
50
|
let STORE_RESULT_COUNT = 0;
|
|
56
51
|
let PICOMATCH_OPTIONS = { nocase: module_1.PLATFORM_WIN32 };
|
|
57
52
|
let MINIMATCH_OPTIONS = {};
|
|
58
53
|
let MINIMATCH;
|
|
59
54
|
let PERMISSION;
|
|
60
|
-
function closeHostThread(host) {
|
|
61
|
-
HOST.DONE.delete(host);
|
|
62
|
-
resumeHostLog(host);
|
|
63
|
-
++HOST.CLOSED;
|
|
64
|
-
const current = Date.now();
|
|
65
|
-
for (let i = 0; i < HOST.QUEUE.length; ++i) {
|
|
66
|
-
const item = HOST.QUEUE[i];
|
|
67
|
-
const { instance, startTime } = item;
|
|
68
|
-
if (startTime + HOST.QUEUE_EXPIRES <= current) {
|
|
69
|
-
cancelHostThread(instance, 'expired: ' + (0, types_1.formatTime)(startTime, true));
|
|
70
|
-
HOST.QUEUE.splice(i--, 1);
|
|
71
|
-
resumeHostQueue(item, true);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
if (HOST.QUEUE.length > 0 && HOST.DONE.size < HOST.THREAD_LIMIT) {
|
|
75
|
-
const queue = HOST.QUEUE.shift();
|
|
76
|
-
HOST.DONE.set(queue.instance, HOST.PID++);
|
|
77
|
-
resumeHostQueue(queue);
|
|
78
|
-
HOST.QUEUE.forEach((item, index) => {
|
|
79
|
-
notifyHostQueue(item.instance, index, item.priority, true);
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
function cancelHostThread(host, hint, rejected) {
|
|
84
|
-
host.writeFail(["Transaction was cancelled", host.username], (0, types_1.errorValue)("Thread was killed", hint), { type: 2, fatal: true });
|
|
85
|
-
host.abort();
|
|
86
|
-
resetHostLog(host);
|
|
87
|
-
if (rejected) {
|
|
88
|
-
++HOST.REJECTED;
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
++HOST.KILLED;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
function resetHostLog(host) {
|
|
95
|
-
if (HOST.LOG_PROGRESS === host) {
|
|
96
|
-
HOST.LOG_PROGRESS = null;
|
|
97
|
-
HOST.LOG_DELAYED.length = 0;
|
|
98
|
-
}
|
|
99
|
-
HOST.LOG_PROGRESS_QUEUE.delete(host);
|
|
100
|
-
HOST.LOG_PROGRESS_PAUSED.delete(host);
|
|
101
|
-
}
|
|
102
|
-
function resumeHostLog(host) {
|
|
103
|
-
resetHostLog(host);
|
|
104
|
-
if (!HOST.LOG_PROGRESS) {
|
|
105
|
-
for (const item of HOST.LOG_PROGRESS_PAUSED) {
|
|
106
|
-
item.resumeLog('progress');
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
function notifyHostQueue(host, position, priority, broadcast) {
|
|
111
|
-
if (!broadcast || host.broadcastId) {
|
|
112
|
-
host.formatMessage(2, 'QUEUE', ["Thread limit exceeded" + ` (position #${position + 1})`, host.username], 'Priority: ' + priority, { type: 2, ...module_1.LOG_STYLE_WARN });
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
function addHostQueue(item) {
|
|
116
|
-
HOST.QUEUE.push(item);
|
|
117
|
-
HOST.QUEUE.sort((a, b) => {
|
|
118
|
-
const au = a.instance.username;
|
|
119
|
-
const bu = b.instance.username;
|
|
120
|
-
if (au && !bu) {
|
|
121
|
-
return -1;
|
|
122
|
-
}
|
|
123
|
-
if (!au && bu) {
|
|
124
|
-
return 1;
|
|
125
|
-
}
|
|
126
|
-
return a.priority - b.priority;
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
function resumeHostQueue(item, aborted) {
|
|
130
|
-
if (!item.joined) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
const { instance, args = [], startTime } = item;
|
|
134
|
-
if (!aborted) {
|
|
135
|
-
if (HOST.LOG_PROGRESS) {
|
|
136
|
-
instance.pauseLog('progress');
|
|
137
|
-
}
|
|
138
|
-
else if (HOST.LOG_PROGRESS_QUEUE.has(instance)) {
|
|
139
|
-
HOST.LOG_PROGRESS = instance;
|
|
140
|
-
instance.resumeLog('progress');
|
|
141
|
-
for (const host of HOST.DONE.keys()) {
|
|
142
|
-
if (host !== instance) {
|
|
143
|
-
host.pauseLog('progress');
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
HOST.LOG_PROGRESS_QUEUE.delete(instance);
|
|
148
|
-
instance.writeTimeElapsed('JOIN', ['Thread restarting...', HOST.THREAD_LIMIT > 1 ? 'Availability: ' + HOST.DONE.size + ' / ' + HOST.THREAD_LIMIT : ''], startTime, { type: 2, ...module_1.LOG_STYLE_WARN });
|
|
149
|
-
}
|
|
150
|
-
queueMicrotask(() => {
|
|
151
|
-
try {
|
|
152
|
-
instance.resumeThread({ args, startTime, aborted });
|
|
153
|
-
}
|
|
154
|
-
catch {
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
55
|
function encryptText(data, iv) {
|
|
159
56
|
return HOST.CIPHER && (0, types_1.isString)(data) && (0, types_1.encryptUTF8)(HOST.CIPHER.algorithm, HOST.CIPHER.key, iv, data) || '';
|
|
160
57
|
}
|
|
161
|
-
function getSettingsValue(options, name, component) {
|
|
162
|
-
const result = options[name];
|
|
163
|
-
return component ? (0, types_1.isObject)(result) ? result[component] : undefined : result;
|
|
164
|
-
}
|
|
165
58
|
function isInvalidRange(result, range) {
|
|
166
59
|
const [lower, upper = 0] = range;
|
|
167
60
|
return Array.isArray(result) && (result.length <= lower || upper > 0 && result.length > upper);
|
|
@@ -173,30 +66,8 @@ function asPosix(value) {
|
|
|
173
66
|
}
|
|
174
67
|
return path.normalize(value);
|
|
175
68
|
}
|
|
176
|
-
function parseIp(value, kind) {
|
|
177
|
-
if (value) {
|
|
178
|
-
try {
|
|
179
|
-
let ip = ipaddr.parse(value);
|
|
180
|
-
if (ip.kind() === 'ipv4') {
|
|
181
|
-
if (kind === 6) {
|
|
182
|
-
ip = ip.toIPv4MappedAddress();
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
else if (kind === 4) {
|
|
186
|
-
if (!ip.isIPv4MappedAddress()) {
|
|
187
|
-
return '';
|
|
188
|
-
}
|
|
189
|
-
ip = ip.toIPv4Address();
|
|
190
|
-
}
|
|
191
|
-
return ip.toNormalizedString();
|
|
192
|
-
}
|
|
193
|
-
catch {
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return '';
|
|
197
|
-
}
|
|
198
69
|
const readable = (value) => (0, types_1.isString)(value) || (0, types_1.isArray)(value);
|
|
199
|
-
const expireTime = (value) => Date.now() + value * 1000;
|
|
70
|
+
const expireTime = (value) => Date.now() + Math.min(Math.trunc(value * 1000), GC.EXPIRES_LIMIT);
|
|
200
71
|
const convertSeconds = (value) => typeof value === 'string' && Math.ceil((0, types_1.parseTime)(value) / 1000) || 0;
|
|
201
72
|
class DbLRU {
|
|
202
73
|
static get(source) {
|
|
@@ -215,28 +86,38 @@ class DbLRU {
|
|
|
215
86
|
}
|
|
216
87
|
return false;
|
|
217
88
|
}
|
|
218
|
-
items = [];
|
|
219
89
|
config = null;
|
|
90
|
+
items = [];
|
|
220
91
|
refresh(percent) {
|
|
221
92
|
const { items, config } = this;
|
|
222
93
|
let result = 0;
|
|
223
94
|
if (config && items.length >= config.limit || percent) {
|
|
224
95
|
percent = Math.min(1, percent ?? config.percent);
|
|
96
|
+
const length = items.length;
|
|
225
97
|
if (percent === 1) {
|
|
226
|
-
|
|
227
|
-
for (let i = 0; i < result; ++i) {
|
|
98
|
+
for (let i = 0; i < length; ++i) {
|
|
228
99
|
items[i].delete(false);
|
|
229
100
|
}
|
|
101
|
+
result = length;
|
|
230
102
|
items.length = 0;
|
|
231
103
|
}
|
|
232
104
|
else {
|
|
105
|
+
const data = items.slice(0);
|
|
233
106
|
const min = config?.min || 0;
|
|
234
|
-
|
|
235
|
-
|
|
107
|
+
let lfu = config?.type === 'lfu';
|
|
108
|
+
if (lfu) {
|
|
109
|
+
data.sort((a, b) => (a.accessCount - b.accessCount) || (a.lastAccessed - b.lastAccessed));
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
data.sort((a, b) => a.lastAccessed - b.lastAccessed);
|
|
113
|
+
lfu = min === 0;
|
|
114
|
+
}
|
|
115
|
+
for (let i = 0, j = Math.floor(length * Math.min(percent, 1)); i < length && j > 0; ++i) {
|
|
236
116
|
const item = data[i];
|
|
237
|
-
if (
|
|
117
|
+
if (lfu || item.accessCount < min) {
|
|
238
118
|
item.delete(true);
|
|
239
119
|
++result;
|
|
120
|
+
--j;
|
|
240
121
|
}
|
|
241
122
|
}
|
|
242
123
|
}
|
|
@@ -249,10 +130,10 @@ class DbCache {
|
|
|
249
130
|
user;
|
|
250
131
|
query;
|
|
251
132
|
value;
|
|
252
|
-
expires;
|
|
253
133
|
accessCount = 0;
|
|
254
134
|
lastAccessed = Date.now();
|
|
255
135
|
disposed = false;
|
|
136
|
+
expires;
|
|
256
137
|
userData;
|
|
257
138
|
queryData;
|
|
258
139
|
sourceList;
|
|
@@ -261,13 +142,18 @@ class DbCache {
|
|
|
261
142
|
this.user = user;
|
|
262
143
|
this.query = query;
|
|
263
144
|
this.value = value;
|
|
264
|
-
this.
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
145
|
+
this.userData = CACHE_USER[source] ||= new Map();
|
|
146
|
+
let data = this.userData.get(user);
|
|
147
|
+
if (!data) {
|
|
148
|
+
data = {};
|
|
149
|
+
this.userData.set(user, data);
|
|
150
|
+
}
|
|
151
|
+
data[query] = this;
|
|
152
|
+
this.queryData = data;
|
|
268
153
|
this.sourceList = DbLRU.get(source);
|
|
269
154
|
this.sourceList.refresh();
|
|
270
155
|
this.sourceList.items.push(this);
|
|
156
|
+
this.expires = expireTime(expires);
|
|
271
157
|
}
|
|
272
158
|
get(seconds) {
|
|
273
159
|
const current = Date.now();
|
|
@@ -329,7 +215,7 @@ class DbCache {
|
|
|
329
215
|
}
|
|
330
216
|
}
|
|
331
217
|
if (!found) {
|
|
332
|
-
|
|
218
|
+
this.userData.delete(this.user);
|
|
333
219
|
}
|
|
334
220
|
if (typeof value === 'string') {
|
|
335
221
|
try {
|
|
@@ -349,41 +235,254 @@ class DbCache {
|
|
|
349
235
|
}
|
|
350
236
|
class DbSession {
|
|
351
237
|
source;
|
|
352
|
-
|
|
238
|
+
timeout;
|
|
239
|
+
sourceData = new Map();
|
|
353
240
|
constructor(source) {
|
|
354
241
|
this.source = source;
|
|
355
|
-
|
|
356
|
-
this.
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
clearInterval(timer);
|
|
360
|
-
}
|
|
361
|
-
}, 60000);
|
|
242
|
+
this.timeout = setInterval(() => {
|
|
243
|
+
this.cleanup();
|
|
244
|
+
this.refresh();
|
|
245
|
+
}, GC.INTERVAL);
|
|
362
246
|
}
|
|
363
247
|
set(user, key, result, seconds) {
|
|
364
|
-
let data = this.sourceData
|
|
248
|
+
let data = this.sourceData.get(user);
|
|
365
249
|
if (!data) {
|
|
366
|
-
data = [Object.create(null),
|
|
367
|
-
this.sourceData
|
|
250
|
+
data = [Object.create(null), expireTime(seconds)];
|
|
251
|
+
this.sourceData.set(user, data);
|
|
368
252
|
}
|
|
369
253
|
data[0][key] = result;
|
|
370
254
|
}
|
|
371
255
|
get(user, key) {
|
|
372
|
-
return this.sourceData
|
|
256
|
+
return this.sourceData.get(user)?.[0][key];
|
|
373
257
|
}
|
|
374
|
-
|
|
258
|
+
refresh() {
|
|
259
|
+
if (this.done) {
|
|
260
|
+
CACHE_SESSION[this.source] = undefined;
|
|
261
|
+
if (this.timeout) {
|
|
262
|
+
clearInterval(this.timeout);
|
|
263
|
+
this.timeout = null;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
cleanup() {
|
|
375
268
|
const current = Date.now();
|
|
376
|
-
for (const user of this.
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
269
|
+
for (const [user, item] of this.sourceData) {
|
|
270
|
+
if (item[1] >= current) {
|
|
271
|
+
this.sourceData.delete(user);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
destroy() {
|
|
276
|
+
this.sourceData.clear();
|
|
277
|
+
this.refresh();
|
|
278
|
+
}
|
|
279
|
+
get done() {
|
|
280
|
+
return this.sourceData.size === 0;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
class HostQueue {
|
|
284
|
+
thread;
|
|
285
|
+
host;
|
|
286
|
+
priority;
|
|
287
|
+
joined = false;
|
|
288
|
+
args = [];
|
|
289
|
+
startTime = Date.now();
|
|
290
|
+
constructor(thread, host, priority) {
|
|
291
|
+
this.thread = thread;
|
|
292
|
+
this.host = host;
|
|
293
|
+
this.priority = priority;
|
|
294
|
+
}
|
|
295
|
+
join(args) {
|
|
296
|
+
if (!this.joined) {
|
|
297
|
+
if (Array.isArray(args)) {
|
|
298
|
+
this.args = args;
|
|
299
|
+
}
|
|
300
|
+
this.joined = true;
|
|
301
|
+
this.thread.queued++;
|
|
302
|
+
return true;
|
|
303
|
+
}
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
resume(aborted) {
|
|
307
|
+
if (!this.joined) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const { thread, host, args, startTime } = this;
|
|
311
|
+
if (!aborted) {
|
|
312
|
+
if (thread.progress) {
|
|
313
|
+
host.pauseLog('progress');
|
|
314
|
+
}
|
|
315
|
+
else if (thread.foreground.has(host)) {
|
|
316
|
+
thread.progress = host;
|
|
317
|
+
host.resumeLog('progress');
|
|
318
|
+
for (const pended of thread.items.keys()) {
|
|
319
|
+
if (pended !== host) {
|
|
320
|
+
host.pauseLog('progress');
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
host.writeTimeElapsed('JOIN', ['Thread restarting...', HOST.THREAD_LIMIT > 1 ? `Availability: ${thread.size} / ${HOST.THREAD_LIMIT}` : ''], startTime, { type: 2, ...module_1.LOG_STYLE_WARN });
|
|
325
|
+
}
|
|
326
|
+
thread.foreground.delete(host);
|
|
327
|
+
if (typeof host.resumeThread === 'function') {
|
|
328
|
+
queueMicrotask(() => host.resumeThread({ args, startTime, aborted }));
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
notify(broadcast, position = this.position) {
|
|
332
|
+
const host = this.host;
|
|
333
|
+
if (!broadcast || host.broadcastId) {
|
|
334
|
+
host.formatMessage(2, 'QUEUE', ["Thread limit exceeded" + ` (position #${position + 1})`, host.username], 'Priority: ' + this.priority, { type: 2, ...module_1.LOG_STYLE_WARN });
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
get position() {
|
|
338
|
+
return this.thread.position(this.host);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
class HostThread {
|
|
342
|
+
pid = 1;
|
|
343
|
+
queued = 0;
|
|
344
|
+
closed = 0;
|
|
345
|
+
rejected = 0;
|
|
346
|
+
killed = 0;
|
|
347
|
+
progress = null;
|
|
348
|
+
items = new Map();
|
|
349
|
+
queue = [];
|
|
350
|
+
paused = new Set();
|
|
351
|
+
foreground = new WeakSet();
|
|
352
|
+
messages = [];
|
|
353
|
+
*[Symbol.iterator]() {
|
|
354
|
+
for (const item of this.items) {
|
|
355
|
+
yield item;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
add(host, progress) {
|
|
359
|
+
this.items.set(host, this.pid++);
|
|
360
|
+
if (this.progress) {
|
|
361
|
+
host.pauseLog('progress');
|
|
362
|
+
if (progress) {
|
|
363
|
+
this.foreground.add(host);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
else if (progress) {
|
|
367
|
+
this.progress = host;
|
|
368
|
+
host['_logDelayed'] = [];
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
pause(host) {
|
|
372
|
+
this.paused.add(host);
|
|
373
|
+
}
|
|
374
|
+
cancel(host, hint, rejected = false) {
|
|
375
|
+
host.writeFail(["Transaction was cancelled", host.username], (0, types_1.errorValue)("Thread was killed", hint), { type: 2, fatal: true });
|
|
376
|
+
host.abort();
|
|
377
|
+
this.resetLog(host);
|
|
378
|
+
if (rejected) {
|
|
379
|
+
this.rejected++;
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
this.killed++;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
close(host) {
|
|
386
|
+
this.items.delete(host);
|
|
387
|
+
this.resumeLog(host);
|
|
388
|
+
this.closed++;
|
|
389
|
+
const current = Date.now();
|
|
390
|
+
const queue = this.queue;
|
|
391
|
+
for (let i = 0; i < queue.length; ++i) {
|
|
392
|
+
const item = queue[i];
|
|
393
|
+
if (current >= item.startTime + HOST.QUEUE_EXPIRES) {
|
|
394
|
+
this.cancel(item.host, 'expired: ' + (0, types_1.formatTime)(item.startTime, true));
|
|
395
|
+
item.resume(true);
|
|
396
|
+
queue.splice(i--, 1);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (queue.length > 0 && this.size < HOST.THREAD_LIMIT) {
|
|
400
|
+
for (let i = 0; i < queue.length; ++i) {
|
|
401
|
+
const item = queue[i];
|
|
402
|
+
if (item.joined) {
|
|
403
|
+
this.add(item.host);
|
|
404
|
+
item.resume(false);
|
|
405
|
+
queue.splice(i, 1);
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
queue.forEach((item, index) => item.notify(true, index));
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
kill() {
|
|
413
|
+
const result = new Map();
|
|
414
|
+
const current = Date.now();
|
|
415
|
+
for (const [host, pid] of this.items) {
|
|
416
|
+
if (host.done) {
|
|
417
|
+
this.close(host);
|
|
380
418
|
}
|
|
419
|
+
else if (host.startTime + HOST.THREAD_EXPIRES >= current) {
|
|
420
|
+
host.writeFail(["Transaction was cancelled", host.username], (0, types_1.errorValue)("Timeout was exceeded", (0, types_1.formatTime)(HOST.THREAD_EXPIRES)), { fatal: true });
|
|
421
|
+
host.abort();
|
|
422
|
+
this.close(host);
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
result.set(host, pid);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
return result;
|
|
429
|
+
}
|
|
430
|
+
resumeLog(host) {
|
|
431
|
+
this.resetLog(host);
|
|
432
|
+
if (!this.progress) {
|
|
433
|
+
for (const item of this.paused) {
|
|
434
|
+
item.resumeLog('progress');
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
resetLog(host) {
|
|
439
|
+
if (this.progress === host) {
|
|
440
|
+
this.progress = null;
|
|
441
|
+
this.messages.length = 0;
|
|
381
442
|
}
|
|
443
|
+
this.foreground.delete(host);
|
|
444
|
+
this.paused.delete(host);
|
|
382
445
|
}
|
|
383
|
-
|
|
384
|
-
|
|
446
|
+
schedule(host, priority) {
|
|
447
|
+
const item = new HostQueue(this, host, priority);
|
|
448
|
+
this.queue.push(item);
|
|
449
|
+
this.queue.sort((a, b) => {
|
|
450
|
+
const au = a.host.username;
|
|
451
|
+
const bu = b.host.username;
|
|
452
|
+
if (au && !bu) {
|
|
453
|
+
return -1;
|
|
454
|
+
}
|
|
455
|
+
if (!au && bu) {
|
|
456
|
+
return 1;
|
|
457
|
+
}
|
|
458
|
+
return a.priority - b.priority;
|
|
459
|
+
});
|
|
460
|
+
item.notify(false);
|
|
461
|
+
}
|
|
462
|
+
join(host, options = {}) {
|
|
463
|
+
const index = this.position(host);
|
|
464
|
+
if (index !== -1) {
|
|
465
|
+
const queue = this.queue[index];
|
|
466
|
+
if (options.reject) {
|
|
467
|
+
this.queue.splice(index, 1);
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
queue.join(options.args);
|
|
471
|
+
return true;
|
|
472
|
+
}
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
position(host) {
|
|
476
|
+
return this.queue.findIndex(item => item.host === host);
|
|
477
|
+
}
|
|
478
|
+
get pending() {
|
|
479
|
+
return this.queue.length;
|
|
480
|
+
}
|
|
481
|
+
get size() {
|
|
482
|
+
return this.items.size;
|
|
385
483
|
}
|
|
386
484
|
}
|
|
485
|
+
const HOST_MAIN = new HostThread();
|
|
387
486
|
class Host extends module_1 {
|
|
388
487
|
static [kHost] = true;
|
|
389
488
|
static async purgeMemory(percent = 1, limit = 0, parent) {
|
|
@@ -539,10 +638,10 @@ class Host extends module_1 {
|
|
|
539
638
|
}
|
|
540
639
|
let result = 0;
|
|
541
640
|
if (HOST.ADMIN_USERS.includes(username) || iv && HOST.ADMIN_USERS.includes(encryptText(username, iv))) {
|
|
542
|
-
for (const [host, id] of
|
|
641
|
+
for (const [host, id] of HOST_MAIN) {
|
|
543
642
|
if (pid === true || id === pid || Array.isArray(pid) && pid.includes(id)) {
|
|
544
|
-
|
|
545
|
-
|
|
643
|
+
HOST_MAIN.cancel(host, `pid: ${id}`);
|
|
644
|
+
HOST_MAIN.close(host);
|
|
546
645
|
++result;
|
|
547
646
|
}
|
|
548
647
|
}
|
|
@@ -569,24 +668,10 @@ class Host extends module_1 {
|
|
|
569
668
|
if (HOST.ADMIN_PRIVATE && !username) {
|
|
570
669
|
return full ? { count: -1 } : -1;
|
|
571
670
|
}
|
|
572
|
-
const
|
|
573
|
-
const items = [];
|
|
574
|
-
for (const [host, pid] of HOST.DONE) {
|
|
575
|
-
if (host.done) {
|
|
576
|
-
closeHostThread(host);
|
|
577
|
-
}
|
|
578
|
-
else if (host.startTime + HOST.THREAD_EXPIRES >= current) {
|
|
579
|
-
host.writeFail(["Transaction was cancelled", host.username], (0, types_1.errorValue)("Timeout was exceeded", (0, types_1.formatTime)(HOST.THREAD_EXPIRES)), { fatal: true });
|
|
580
|
-
host.abort();
|
|
581
|
-
closeHostThread(host);
|
|
582
|
-
}
|
|
583
|
-
else {
|
|
584
|
-
items.push([host, pid]);
|
|
585
|
-
}
|
|
586
|
-
}
|
|
671
|
+
const items = Array.from(HOST_MAIN.kill());
|
|
587
672
|
const count = items.length;
|
|
588
673
|
if (full) {
|
|
589
|
-
const result = { count, pending:
|
|
674
|
+
const result = { count, pending: HOST_MAIN.pending, opened: HOST_MAIN.size, closed: HOST_MAIN.closed, queued: HOST_MAIN.queued, rejected: HOST_MAIN.rejected, killed: HOST_MAIN.killed };
|
|
590
675
|
if (count) {
|
|
591
676
|
if (count > 1) {
|
|
592
677
|
items.sort((a, b) => a[0].startTime - b[0].startTime);
|
|
@@ -617,8 +702,34 @@ class Host extends module_1 {
|
|
|
617
702
|
}
|
|
618
703
|
return count;
|
|
619
704
|
}
|
|
705
|
+
static parseIp(value, kind) {
|
|
706
|
+
if ((0, types_1.isString)(value)) {
|
|
707
|
+
try {
|
|
708
|
+
let ip = ipaddr.parse(value);
|
|
709
|
+
if (kind) {
|
|
710
|
+
if (ip.kind() === 'ipv4') {
|
|
711
|
+
if (kind === 'ipv6') {
|
|
712
|
+
ip = ip.toIPv4MappedAddress();
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
else if (kind === 'ipv4') {
|
|
716
|
+
if (ip.isIPv4MappedAddress()) {
|
|
717
|
+
ip = ip.toIPv4Address();
|
|
718
|
+
}
|
|
719
|
+
else {
|
|
720
|
+
return '';
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
return ip.toNormalizedString();
|
|
725
|
+
}
|
|
726
|
+
catch {
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
return '';
|
|
730
|
+
}
|
|
620
731
|
static getLogDelayed() {
|
|
621
|
-
return
|
|
732
|
+
return HOST_MAIN.messages;
|
|
622
733
|
}
|
|
623
734
|
static getPermissionFromSettings(freeze = true) {
|
|
624
735
|
return freeze ? PERMISSION : Permission.clone(PERMISSION);
|
|
@@ -670,22 +781,17 @@ class Host extends module_1 {
|
|
|
670
781
|
this.ignoreLog(typeof log === 'boolean' ? !log : log);
|
|
671
782
|
}
|
|
672
783
|
this.#config = Object.freeze({ ...config });
|
|
673
|
-
if (
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
else if (showProgress) {
|
|
679
|
-
HOST.LOG_PROGRESS = this;
|
|
680
|
-
this._logDelayed = [];
|
|
681
|
-
}
|
|
784
|
+
if (HOST_MAIN.size >= HOST.THREAD_LIMIT) {
|
|
785
|
+
HOST_MAIN.kill();
|
|
786
|
+
}
|
|
787
|
+
if (HOST_MAIN.size < HOST.THREAD_LIMIT || this.username && typeof priority === 'number' && priority === HOST.PRIORITY_BYPASS) {
|
|
788
|
+
HOST_MAIN.add(this, showProgress);
|
|
682
789
|
}
|
|
683
|
-
else if (typeof priority === 'number' && priority >= HOST.PRIORITY_MIN && priority <= HOST.PRIORITY_MAX &&
|
|
684
|
-
|
|
685
|
-
notifyHostQueue(this, HOST.QUEUE.findIndex(item => item.instance === this), priority);
|
|
790
|
+
else if (typeof priority === 'number' && priority >= HOST.PRIORITY_MIN && priority <= HOST.PRIORITY_MAX && HOST_MAIN.pending < HOST.QUEUE_LIMIT && typeof this.resumeThread === 'function') {
|
|
791
|
+
HOST_MAIN.schedule(this, priority);
|
|
686
792
|
}
|
|
687
793
|
else {
|
|
688
|
-
|
|
794
|
+
HOST_MAIN.cancel(this, `limit: ${HOST.THREAD_LIMIT}`, true);
|
|
689
795
|
}
|
|
690
796
|
}
|
|
691
797
|
restart(...args) { }
|
|
@@ -793,7 +899,7 @@ class Host extends module_1 {
|
|
|
793
899
|
hasLog(type) {
|
|
794
900
|
switch (type) {
|
|
795
901
|
case 'progress':
|
|
796
|
-
return this ===
|
|
902
|
+
return this === HOST_MAIN.progress;
|
|
797
903
|
default:
|
|
798
904
|
return false;
|
|
799
905
|
}
|
|
@@ -801,12 +907,12 @@ class Host extends module_1 {
|
|
|
801
907
|
pauseLog(type) {
|
|
802
908
|
if (type === 'progress') {
|
|
803
909
|
this._logDelayed ||= [];
|
|
804
|
-
|
|
910
|
+
HOST_MAIN.pause(this);
|
|
805
911
|
}
|
|
806
912
|
this.#logState = 0;
|
|
807
913
|
}
|
|
808
914
|
resumeLog(type) {
|
|
809
|
-
if (!type || this.hasLog(type) || type === 'progress' && !
|
|
915
|
+
if (!type || this.hasLog(type) || type === 'progress' && !HOST_MAIN.progress) {
|
|
810
916
|
this.#logState = 1;
|
|
811
917
|
const log = this._logDelayed;
|
|
812
918
|
if (log?.length) {
|
|
@@ -827,12 +933,12 @@ class Host extends module_1 {
|
|
|
827
933
|
}
|
|
828
934
|
log.length = 0;
|
|
829
935
|
}
|
|
830
|
-
|
|
936
|
+
HOST_MAIN.resumeLog(this);
|
|
831
937
|
}
|
|
832
938
|
}
|
|
833
939
|
delayMessage(args) {
|
|
834
940
|
this._logDelayed?.push(args);
|
|
835
|
-
|
|
941
|
+
HOST_MAIN.messages.push(args);
|
|
836
942
|
}
|
|
837
943
|
retain(process) {
|
|
838
944
|
this.subProcesses.add(process);
|
|
@@ -862,27 +968,7 @@ class Host extends module_1 {
|
|
|
862
968
|
return null;
|
|
863
969
|
}
|
|
864
970
|
joinQueue(options) {
|
|
865
|
-
|
|
866
|
-
if (index !== -1) {
|
|
867
|
-
const queue = HOST.QUEUE[index];
|
|
868
|
-
let args, reject;
|
|
869
|
-
if (options) {
|
|
870
|
-
({ args, reject } = options);
|
|
871
|
-
}
|
|
872
|
-
if (reject) {
|
|
873
|
-
HOST.QUEUE.splice(index, 1);
|
|
874
|
-
return false;
|
|
875
|
-
}
|
|
876
|
-
if (Array.isArray(args)) {
|
|
877
|
-
queue.args = args;
|
|
878
|
-
}
|
|
879
|
-
if (!queue.joined) {
|
|
880
|
-
queue.joined = true;
|
|
881
|
-
++HOST.QUEUED;
|
|
882
|
-
}
|
|
883
|
-
return true;
|
|
884
|
-
}
|
|
885
|
-
return false;
|
|
971
|
+
return HOST_MAIN.join(this, options);
|
|
886
972
|
}
|
|
887
973
|
set host(value) { }
|
|
888
974
|
get host() {
|
|
@@ -895,22 +981,22 @@ class Host extends module_1 {
|
|
|
895
981
|
return this.#username;
|
|
896
982
|
}
|
|
897
983
|
get ipV4() {
|
|
898
|
-
return parseIp(this.config.remoteIp,
|
|
984
|
+
return Host.parseIp(this.config.remoteIp, 'ipv4');
|
|
899
985
|
}
|
|
900
986
|
get ipV6() {
|
|
901
|
-
return parseIp(this.config.remoteIp,
|
|
987
|
+
return Host.parseIp(this.config.remoteIp, 'ipv6');
|
|
902
988
|
}
|
|
903
989
|
set done(value) {
|
|
904
990
|
if (value) {
|
|
905
991
|
this.#done = true;
|
|
906
|
-
|
|
992
|
+
HOST_MAIN.close(this);
|
|
907
993
|
}
|
|
908
994
|
}
|
|
909
995
|
get done() {
|
|
910
996
|
return this.#done || this.aborted;
|
|
911
997
|
}
|
|
912
998
|
get queued() {
|
|
913
|
-
return
|
|
999
|
+
return HOST_MAIN.position(this) !== -1;
|
|
914
1000
|
}
|
|
915
1001
|
get logState() {
|
|
916
1002
|
return this.#logState;
|
|
@@ -974,7 +1060,7 @@ class Client extends module_1 {
|
|
|
974
1060
|
return result;
|
|
975
1061
|
}
|
|
976
1062
|
set cacheDir(value) {
|
|
977
|
-
if (path.isAbsolute(value) && module_1.isDir(value)) {
|
|
1063
|
+
if (path.isAbsolute(value) && module_1.isDir(value) && this.supportsProperty('cacheDir')) {
|
|
978
1064
|
this.#cacheDir = value;
|
|
979
1065
|
}
|
|
980
1066
|
}
|
|
@@ -1022,15 +1108,31 @@ class ClientDb extends Client {
|
|
|
1022
1108
|
return false;
|
|
1023
1109
|
}
|
|
1024
1110
|
const memory = settings.memory;
|
|
1025
|
-
|
|
1026
|
-
|
|
1111
|
+
for (const name in memory) {
|
|
1112
|
+
if (name === 'settings') {
|
|
1113
|
+
const gc = memory.settings?.gc;
|
|
1114
|
+
if (gc) {
|
|
1115
|
+
let { expires, interval, expires_limit } = gc;
|
|
1116
|
+
if (expires_limit !== undefined && (expires_limit = (0, types_1.parseExpires)(expires_limit) / 1000) >= 1) {
|
|
1117
|
+
GC.EXPIRES_LIMIT = expires_limit;
|
|
1118
|
+
}
|
|
1119
|
+
if (expires !== undefined && (expires = (0, types_1.parseExpires)(expires) / 1000) > 0) {
|
|
1120
|
+
GC.EXPIRES = Math.min(expires, GC.EXPIRES_LIMIT);
|
|
1121
|
+
GC.EXPIRES_DEFAULT = true;
|
|
1122
|
+
}
|
|
1123
|
+
if (interval !== undefined && (interval = (0, types_1.parseExpires)(interval)) > 0) {
|
|
1124
|
+
GC.INTERVAL = interval;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
else {
|
|
1027
1129
|
const client = memory[name];
|
|
1028
1130
|
if ((0, types_1.isPlainObject)(client)) {
|
|
1029
1131
|
for (const source in client) {
|
|
1030
1132
|
const item = client[source];
|
|
1031
|
-
if ((0, types_1.
|
|
1133
|
+
if ((0, types_1.isObject)(item) && 'enabled' in item) {
|
|
1032
1134
|
const key = name + '_' + source;
|
|
1033
|
-
const { enabled, limit = 0, min = 0, max = 0 } = item;
|
|
1135
|
+
const { enabled, limit = 0, min = 0, max = 0, type = 'lru' } = item;
|
|
1034
1136
|
if (enabled && +limit > 0) {
|
|
1035
1137
|
let percent = item.percent || 0;
|
|
1036
1138
|
if ((0, types_1.isString)(percent)) {
|
|
@@ -1041,6 +1143,7 @@ class ClientDb extends Client {
|
|
|
1041
1143
|
}
|
|
1042
1144
|
if (percent > 0) {
|
|
1043
1145
|
DbLRU.get(key).config = {
|
|
1146
|
+
type,
|
|
1044
1147
|
limit: +limit,
|
|
1045
1148
|
percent: Math.min(percent, 1),
|
|
1046
1149
|
min: min > 0 ? min : 0,
|
|
@@ -1062,7 +1165,7 @@ class ClientDb extends Client {
|
|
|
1062
1165
|
return parent ? super.purgeMemory(percent, limit, parent) : 0;
|
|
1063
1166
|
}
|
|
1064
1167
|
static getTimeout(value) {
|
|
1065
|
-
if (value
|
|
1168
|
+
if (value == null) {
|
|
1066
1169
|
return 0;
|
|
1067
1170
|
}
|
|
1068
1171
|
let result = 0;
|
|
@@ -1074,7 +1177,7 @@ class ClientDb extends Client {
|
|
|
1074
1177
|
result = convertSeconds(value);
|
|
1075
1178
|
break;
|
|
1076
1179
|
case 'object':
|
|
1077
|
-
if (
|
|
1180
|
+
if (typeof (result = value.timeout) === 'string') {
|
|
1078
1181
|
result = convertSeconds(value.timeout);
|
|
1079
1182
|
value.timeout = result;
|
|
1080
1183
|
}
|
|
@@ -1097,15 +1200,14 @@ class ClientDb extends Client {
|
|
|
1097
1200
|
static findResult(source, credential, queryString, timeout, sessionKey, renewCache) {
|
|
1098
1201
|
const userKey = credential ? this.extractUUID(credential) || (0, types_1.hashKey)(this.asString(credential)) : undefined;
|
|
1099
1202
|
if (userKey) {
|
|
1100
|
-
queryString = (0, types_1.hashKey)(queryString);
|
|
1101
1203
|
if (timeout > 0) {
|
|
1102
|
-
const stored = CACHE_USER[source]?.
|
|
1204
|
+
const stored = CACHE_USER[source]?.get(userKey)?.[(0, types_1.hashKey)(queryString)];
|
|
1103
1205
|
if (stored) {
|
|
1104
1206
|
return stored.get(renewCache ? timeout : 0);
|
|
1105
1207
|
}
|
|
1106
1208
|
}
|
|
1107
1209
|
else if (sessionKey) {
|
|
1108
|
-
return this.findSession(source, userKey + sessionKey, queryString);
|
|
1210
|
+
return this.findSession(source, userKey + sessionKey, (0, types_1.hashKey)(queryString));
|
|
1109
1211
|
}
|
|
1110
1212
|
}
|
|
1111
1213
|
}
|
|
@@ -1122,21 +1224,22 @@ class ClientDb extends Client {
|
|
|
1122
1224
|
}
|
|
1123
1225
|
let timeout = 0, userKey, whenEmpty, partition = false;
|
|
1124
1226
|
switch (typeof cache) {
|
|
1125
|
-
case 'object':
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
cacheDir
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1227
|
+
case 'object':
|
|
1228
|
+
if (cache) {
|
|
1229
|
+
let seconds, dir;
|
|
1230
|
+
({ timeout: seconds, when_empty: whenEmpty, dir } = cache);
|
|
1231
|
+
if (dir && (!cacheDir || module_1.isDir(dir))) {
|
|
1232
|
+
cacheDir = dir;
|
|
1233
|
+
partition = true;
|
|
1234
|
+
}
|
|
1235
|
+
if (typeof seconds === 'number') {
|
|
1236
|
+
timeout = seconds;
|
|
1237
|
+
}
|
|
1238
|
+
else {
|
|
1239
|
+
cache.timeout = seconds ? timeout = convertSeconds(seconds) : 0;
|
|
1240
|
+
}
|
|
1137
1241
|
}
|
|
1138
1242
|
break;
|
|
1139
|
-
}
|
|
1140
1243
|
case 'number':
|
|
1141
1244
|
timeout = cache;
|
|
1142
1245
|
break;
|
|
@@ -1150,9 +1253,9 @@ class ClientDb extends Client {
|
|
|
1150
1253
|
break;
|
|
1151
1254
|
}
|
|
1152
1255
|
if ((result.length > 0 || whenEmpty) && (userKey = this.extractUUID(credential) || (0, types_1.hashKey)(this.asString(credential)))) {
|
|
1153
|
-
queryString = (0, types_1.hashKey)(queryString);
|
|
1154
1256
|
if (timeout > 0) {
|
|
1155
|
-
|
|
1257
|
+
queryString = (0, types_1.hashKey)(queryString);
|
|
1258
|
+
const item = new DbCache(source, userKey, queryString, result, timeout);
|
|
1156
1259
|
if (cacheDir) {
|
|
1157
1260
|
if (partition) {
|
|
1158
1261
|
if (STORE_RESULT_COUNT === this.STORE_RESULT_PARTITION_SIZE) {
|
|
@@ -1171,8 +1274,8 @@ class ClientDb extends Client {
|
|
|
1171
1274
|
});
|
|
1172
1275
|
}
|
|
1173
1276
|
}
|
|
1174
|
-
else if (typeof sessionKey === 'string'
|
|
1175
|
-
this.storeSession(source, userKey + sessionKey, queryString, result, sessionExpires);
|
|
1277
|
+
else if (typeof sessionKey === 'string') {
|
|
1278
|
+
this.storeSession(source, userKey + sessionKey, (0, types_1.hashKey)(queryString), result, sessionExpires);
|
|
1176
1279
|
}
|
|
1177
1280
|
}
|
|
1178
1281
|
return result;
|
|
@@ -1180,8 +1283,10 @@ class ClientDb extends Client {
|
|
|
1180
1283
|
static findSession(source, user, key) {
|
|
1181
1284
|
return CACHE_SESSION[source]?.get(user, key);
|
|
1182
1285
|
}
|
|
1183
|
-
static storeSession(source, user, key, result, expires =
|
|
1184
|
-
(
|
|
1286
|
+
static storeSession(source, user, key, result, expires = 0) {
|
|
1287
|
+
if (expires > 0 || GC.EXPIRES_DEFAULT) {
|
|
1288
|
+
(CACHE_SESSION[source] ||= new DbSession(source)).set(user, key, result, expires > 0 ? expires : GC.EXPIRES);
|
|
1289
|
+
}
|
|
1185
1290
|
}
|
|
1186
1291
|
static async purgeResult(prefix, lru) {
|
|
1187
1292
|
const cache = lru ? CACHE_SOURCE : CACHE_USER;
|
|
@@ -1194,15 +1299,26 @@ class ClientDb extends Client {
|
|
|
1194
1299
|
items.push(cache[key]);
|
|
1195
1300
|
}
|
|
1196
1301
|
}
|
|
1302
|
+
for (const key in CACHE_SESSION) {
|
|
1303
|
+
if (key.startsWith(prefix)) {
|
|
1304
|
+
CACHE_SESSION[key]?.destroy();
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1197
1307
|
}
|
|
1198
|
-
else
|
|
1199
|
-
|
|
1308
|
+
else {
|
|
1309
|
+
if (cache[prefix]) {
|
|
1310
|
+
items.push(cache[prefix]);
|
|
1311
|
+
}
|
|
1312
|
+
CACHE_SESSION[prefix]?.destroy();
|
|
1200
1313
|
}
|
|
1201
1314
|
}
|
|
1202
1315
|
else {
|
|
1203
1316
|
for (const key in cache) {
|
|
1204
1317
|
items.push(cache[key]);
|
|
1205
1318
|
}
|
|
1319
|
+
for (const key in CACHE_SESSION) {
|
|
1320
|
+
CACHE_SESSION[key]?.destroy();
|
|
1321
|
+
}
|
|
1206
1322
|
}
|
|
1207
1323
|
let result = 0;
|
|
1208
1324
|
if (lru) {
|
|
@@ -1213,8 +1329,7 @@ class ClientDb extends Client {
|
|
|
1213
1329
|
else {
|
|
1214
1330
|
const current = Date.now();
|
|
1215
1331
|
for (const source of items) {
|
|
1216
|
-
for (const
|
|
1217
|
-
const data = source[session];
|
|
1332
|
+
for (const data of source.values()) {
|
|
1218
1333
|
for (const query in data) {
|
|
1219
1334
|
const item = data[query];
|
|
1220
1335
|
if (item.expired(current)) {
|
|
@@ -1253,13 +1368,8 @@ class ClientDb extends Client {
|
|
|
1253
1368
|
this.cacheDir = cache_dir;
|
|
1254
1369
|
}
|
|
1255
1370
|
if (expires !== undefined) {
|
|
1256
|
-
if (typeof expires === 'string') {
|
|
1257
|
-
|
|
1258
|
-
this.settings.session_expires = expires;
|
|
1259
|
-
}
|
|
1260
|
-
else {
|
|
1261
|
-
delete this.settings.cache_session;
|
|
1262
|
-
}
|
|
1371
|
+
if (typeof expires === 'string' && !isNaN(expires = (0, types_1.parseTime)(expires))) {
|
|
1372
|
+
this.settings.session_expires = expires;
|
|
1263
1373
|
}
|
|
1264
1374
|
if (expires >= 0) {
|
|
1265
1375
|
this.cacheExpires = expires;
|
|
@@ -1306,7 +1416,7 @@ class ClientDb extends Client {
|
|
|
1306
1416
|
sessionKey = options;
|
|
1307
1417
|
break;
|
|
1308
1418
|
case 'object':
|
|
1309
|
-
if (options
|
|
1419
|
+
if (options) {
|
|
1310
1420
|
({ value, sessionKey, exclusiveOf, renewCache } = options);
|
|
1311
1421
|
if (Array.isArray(exclusiveOf)) {
|
|
1312
1422
|
const ignoreCache = exclusiveOf[2];
|
|
@@ -1411,18 +1521,27 @@ class ClientDb extends Client {
|
|
|
1411
1521
|
settingsOf(source, name, component) {
|
|
1412
1522
|
const data = this.settings[source];
|
|
1413
1523
|
if ((0, types_1.isObject)(data)) {
|
|
1414
|
-
return
|
|
1524
|
+
return this.#settingsValue(data, name, component);
|
|
1415
1525
|
}
|
|
1416
1526
|
}
|
|
1417
1527
|
settingsKey(uuidKey, name, component) {
|
|
1418
1528
|
const data = this.settings.user_key?.[uuidKey];
|
|
1419
1529
|
if ((0, types_1.isObject)(data)) {
|
|
1420
|
-
return
|
|
1530
|
+
return this.#settingsValue(data, name, component);
|
|
1421
1531
|
}
|
|
1422
1532
|
}
|
|
1423
1533
|
getSourceName(value) {
|
|
1424
1534
|
return this.moduleName + '_' + value;
|
|
1425
1535
|
}
|
|
1536
|
+
#settingsValue(options, name, component) {
|
|
1537
|
+
const result = options[name];
|
|
1538
|
+
if (!component) {
|
|
1539
|
+
return result;
|
|
1540
|
+
}
|
|
1541
|
+
if ((0, types_1.isObject)(result)) {
|
|
1542
|
+
return result[component];
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1426
1545
|
get pending() {
|
|
1427
1546
|
return this.database.filter(item => {
|
|
1428
1547
|
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.7",
|
|
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.7",
|
|
23
|
+
"@e-mc/types": "0.13.7",
|
|
24
24
|
"ipaddr.js": "^2.3.0",
|
|
25
25
|
"picomatch": "^4.0.3"
|
|
26
26
|
}
|