kuzzle 2.20.3 → 2.21.1
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/lib/api/controllers/debugController.d.ts +2 -27
- package/lib/api/controllers/debugController.js +20 -175
- package/lib/api/controllers/documentController.js +122 -10
- package/lib/api/funnel.js +16 -2
- package/lib/api/request/kuzzleRequest.d.ts +8 -0
- package/lib/api/request/kuzzleRequest.js +12 -0
- package/lib/cluster/idCardHandler.js +19 -6
- package/lib/cluster/node.js +27 -1
- package/lib/cluster/protobuf/sync.proto +5 -0
- package/lib/cluster/publisher.js +10 -0
- package/lib/cluster/subscriber.js +15 -0
- package/lib/cluster/workers/IDCardRenewer.js +27 -26
- package/lib/core/debug/kuzzleDebugger.d.ts +46 -0
- package/lib/core/debug/kuzzleDebugger.js +266 -0
- package/lib/core/network/clientConnection.js +6 -1
- package/lib/core/network/protocols/httpwsProtocol.js +18 -3
- package/lib/kuzzle/dumpGenerator.js +1 -1
- package/lib/kuzzle/kuzzle.js +3 -0
- package/lib/service/storage/elasticsearch.js +44 -30
- package/lib/types/events/EventGenericDocument.d.ts +21 -1
- package/package.json +1 -1
- package/lib/types/DebugModule.d.ts +0 -24
- package/lib/types/DebugModule.js +0 -39
|
@@ -4,23 +4,10 @@ import { NativeController } from "./baseController";
|
|
|
4
4
|
* @class DebugController
|
|
5
5
|
*/
|
|
6
6
|
export declare class DebugController extends NativeController {
|
|
7
|
-
|
|
8
|
-
private debuggerStatus;
|
|
9
|
-
/**
|
|
10
|
-
* Map<eventName, Set<connectionId>>
|
|
11
|
-
*/
|
|
12
|
-
private events;
|
|
13
|
-
/**
|
|
14
|
-
* Map of functions from the DebugModules
|
|
15
|
-
*/
|
|
16
|
-
private kuzzlePostMethods;
|
|
7
|
+
constructor();
|
|
17
8
|
/**
|
|
18
|
-
*
|
|
19
|
-
* Used to add new methods and events to the protocol
|
|
9
|
+
* Return the node version of the current Kuzzle instance
|
|
20
10
|
*/
|
|
21
|
-
private modules;
|
|
22
|
-
constructor();
|
|
23
|
-
init(): Promise<void>;
|
|
24
11
|
nodeVersion(): Promise<string>;
|
|
25
12
|
/**
|
|
26
13
|
* Connect the debugger
|
|
@@ -44,16 +31,4 @@ export declare class DebugController extends NativeController {
|
|
|
44
31
|
* Remove the websocket connection from the events' listeners
|
|
45
32
|
*/
|
|
46
33
|
removeListener(request: KuzzleRequest): Promise<void>;
|
|
47
|
-
/**
|
|
48
|
-
* Execute a method using the Chrome Debug Protocol
|
|
49
|
-
* @param method Chrome Debug Protocol method to execute
|
|
50
|
-
* @param params
|
|
51
|
-
* @returns
|
|
52
|
-
*/
|
|
53
|
-
private inspectorPost;
|
|
54
|
-
/**
|
|
55
|
-
* Sends a direct notification to a websocket connection without having to listen to a specific room
|
|
56
|
-
*/
|
|
57
|
-
private notifyConnection;
|
|
58
|
-
private notifyGlobalListeners;
|
|
59
34
|
}
|
|
@@ -48,10 +48,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
48
48
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
49
|
exports.DebugController = void 0;
|
|
50
50
|
const baseController_1 = require("./baseController");
|
|
51
|
-
const inspector_1 = __importDefault(require("inspector"));
|
|
52
51
|
const kerror = __importStar(require("../../kerror"));
|
|
53
52
|
const get_1 = __importDefault(require("lodash/get"));
|
|
54
|
-
const DEBUGGER_EVENT = "kuzzle-debugger-event";
|
|
55
53
|
/**
|
|
56
54
|
* @class DebugController
|
|
57
55
|
*/
|
|
@@ -65,53 +63,10 @@ class DebugController extends baseController_1.NativeController {
|
|
|
65
63
|
"addListener",
|
|
66
64
|
"removeListener",
|
|
67
65
|
]);
|
|
68
|
-
this.debuggerStatus = false;
|
|
69
|
-
/**
|
|
70
|
-
* Map<eventName, Set<connectionId>>
|
|
71
|
-
*/
|
|
72
|
-
this.events = new Map();
|
|
73
|
-
/**
|
|
74
|
-
* Map of functions from the DebugModules
|
|
75
|
-
*/
|
|
76
|
-
this.kuzzlePostMethods = new Map();
|
|
77
|
-
/**
|
|
78
|
-
* List of DebugModule for DebugController
|
|
79
|
-
* Used to add new methods and events to the protocol
|
|
80
|
-
*/
|
|
81
|
-
this.modules = [];
|
|
82
|
-
}
|
|
83
|
-
async init() {
|
|
84
|
-
super.init();
|
|
85
|
-
this.inspector = new inspector_1.default.Session();
|
|
86
|
-
// Remove connection id from the list of listeners for each event
|
|
87
|
-
global.kuzzle.on("connection:remove", (connectionId) => {
|
|
88
|
-
if (!this.debuggerStatus) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
for (const listener of this.events.values()) {
|
|
92
|
-
listener.delete(connectionId);
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
this.inspector.on("inspectorNotification", async (payload) => {
|
|
96
|
-
if (!this.debuggerStatus) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
await this.notifyGlobalListeners(payload.method, payload);
|
|
100
|
-
const listeners = this.events.get(payload.method);
|
|
101
|
-
if (!listeners) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const promises = [];
|
|
105
|
-
for (const connectionId of listeners) {
|
|
106
|
-
promises.push(this.notifyConnection(connectionId, DEBUGGER_EVENT, {
|
|
107
|
-
event: payload.method,
|
|
108
|
-
result: payload,
|
|
109
|
-
}));
|
|
110
|
-
}
|
|
111
|
-
// No need to catch, notify is already try-catched
|
|
112
|
-
await Promise.all(promises);
|
|
113
|
-
});
|
|
114
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Return the node version of the current Kuzzle instance
|
|
69
|
+
*/
|
|
115
70
|
async nodeVersion() {
|
|
116
71
|
return process.version;
|
|
117
72
|
}
|
|
@@ -119,168 +74,58 @@ class DebugController extends baseController_1.NativeController {
|
|
|
119
74
|
* Connect the debugger
|
|
120
75
|
*/
|
|
121
76
|
async enable() {
|
|
122
|
-
if (
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
this.inspector.connect();
|
|
126
|
-
this.debuggerStatus = true;
|
|
127
|
-
for (const module of this.modules) {
|
|
128
|
-
await module.init(this.inspector);
|
|
129
|
-
for (const methodName of module.methods) {
|
|
130
|
-
if (!module[methodName]) {
|
|
131
|
-
throw new Error(`Missing implementation of method "${methodName}" inside DebugModule "${module.name}"`);
|
|
132
|
-
}
|
|
133
|
-
this.kuzzlePostMethods.set(`Kuzzle.${module.name}.${methodName}`, module[methodName].bind(module));
|
|
134
|
-
}
|
|
135
|
-
for (const eventName of module.events) {
|
|
136
|
-
module.on(eventName, async (payload) => {
|
|
137
|
-
if (!this.debuggerStatus) {
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
const event = `Kuzzle.${module.name}.${eventName}`;
|
|
141
|
-
await this.notifyGlobalListeners(event, payload);
|
|
142
|
-
const listeners = this.events.get(event);
|
|
143
|
-
if (!listeners) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
const promises = [];
|
|
147
|
-
for (const connectionId of listeners) {
|
|
148
|
-
promises.push(this.notifyConnection(connectionId, DEBUGGER_EVENT, {
|
|
149
|
-
event,
|
|
150
|
-
result: payload,
|
|
151
|
-
}));
|
|
152
|
-
}
|
|
153
|
-
// No need to catch, notify is already try-catched
|
|
154
|
-
await Promise.all(promises);
|
|
155
|
-
});
|
|
156
|
-
}
|
|
77
|
+
if (!(0, get_1.default)(global.kuzzle.config, "security.debug.native_debug_protocol")) {
|
|
78
|
+
throw kerror.get("core", "debugger", "native_debug_protocol_usage_denied");
|
|
157
79
|
}
|
|
80
|
+
await global.kuzzle.ask("core:debugger:enable");
|
|
158
81
|
}
|
|
159
82
|
/**
|
|
160
83
|
* Disconnect the debugger and clears all the events listeners
|
|
161
84
|
*/
|
|
162
85
|
async disable() {
|
|
163
|
-
if (!
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
for (const module of this.modules) {
|
|
167
|
-
for (const eventName of module.events) {
|
|
168
|
-
module.removeAllListeners(eventName);
|
|
169
|
-
}
|
|
170
|
-
await module.cleanup();
|
|
86
|
+
if (!(0, get_1.default)(global.kuzzle.config, "security.debug.native_debug_protocol")) {
|
|
87
|
+
throw kerror.get("core", "debugger", "native_debug_protocol_usage_denied");
|
|
171
88
|
}
|
|
172
|
-
|
|
173
|
-
this.debuggerStatus = false;
|
|
174
|
-
this.events.clear();
|
|
175
|
-
this.kuzzlePostMethods.clear();
|
|
89
|
+
await global.kuzzle.ask("core:debugger:disable");
|
|
176
90
|
}
|
|
177
91
|
/**
|
|
178
92
|
* Trigger action from debugger directly following the Chrome Debug Protocol
|
|
179
93
|
* See: https://chromedevtools.github.io/devtools-protocol/v8/
|
|
180
94
|
*/
|
|
181
95
|
async post(request) {
|
|
182
|
-
if (!this.debuggerStatus) {
|
|
183
|
-
throw kerror.get("core", "debugger", "not_enabled");
|
|
184
|
-
}
|
|
185
|
-
const method = request.getBodyString("method");
|
|
186
|
-
const params = request.getBodyObject("params", {});
|
|
187
|
-
if (method.startsWith("Kuzzle.")) {
|
|
188
|
-
const debugModuleMethod = this.kuzzlePostMethods.get(method);
|
|
189
|
-
if (debugModuleMethod) {
|
|
190
|
-
return debugModuleMethod(params);
|
|
191
|
-
}
|
|
192
|
-
throw kerror.get("core", "debugger", "method_not_found", method);
|
|
193
|
-
}
|
|
194
96
|
if (!(0, get_1.default)(global.kuzzle.config, "security.debug.native_debug_protocol")) {
|
|
195
97
|
throw kerror.get("core", "debugger", "native_debug_protocol_usage_denied");
|
|
196
98
|
}
|
|
197
|
-
|
|
99
|
+
const method = request.getBodyString("method");
|
|
100
|
+
const params = request.getBodyObject("params", {});
|
|
101
|
+
return global.kuzzle.ask("core:debugger:post", method, params);
|
|
198
102
|
}
|
|
199
103
|
/**
|
|
200
104
|
* Make the websocket connection listen and receive events from Chrome Debug Protocol
|
|
201
105
|
* See events from: https://chromedevtools.github.io/devtools-protocol/v8/
|
|
202
106
|
*/
|
|
203
107
|
async addListener(request) {
|
|
108
|
+
if (!(0, get_1.default)(global.kuzzle.config, "security.debug.native_debug_protocol")) {
|
|
109
|
+
throw kerror.get("core", "debugger", "native_debug_protocol_usage_denied");
|
|
110
|
+
}
|
|
204
111
|
if (request.context.connection.protocol !== "websocket") {
|
|
205
112
|
throw kerror.get("api", "assert", "unsupported_protocol", request.context.connection.protocol, "debug:addListener");
|
|
206
113
|
}
|
|
207
|
-
if (!this.debuggerStatus) {
|
|
208
|
-
throw kerror.get("core", "debugger", "not_enabled");
|
|
209
|
-
}
|
|
210
114
|
const event = request.getBodyString("event");
|
|
211
|
-
|
|
212
|
-
if (!listeners) {
|
|
213
|
-
listeners = new Set();
|
|
214
|
-
this.events.set(event, listeners);
|
|
215
|
-
}
|
|
216
|
-
listeners.add(request.context.connection.id);
|
|
115
|
+
await global.kuzzle.ask("core:debugger:addListener", event, request.context.connection.id);
|
|
217
116
|
}
|
|
218
117
|
/**
|
|
219
118
|
* Remove the websocket connection from the events' listeners
|
|
220
119
|
*/
|
|
221
120
|
async removeListener(request) {
|
|
121
|
+
if (!(0, get_1.default)(global.kuzzle.config, "security.debug.native_debug_protocol")) {
|
|
122
|
+
throw kerror.get("core", "debugger", "native_debug_protocol_usage_denied");
|
|
123
|
+
}
|
|
222
124
|
if (request.context.connection.protocol !== "websocket") {
|
|
223
125
|
throw kerror.get("api", "assert", "unsupported_protocol", request.context.connection.protocol, "debug:removeListener");
|
|
224
126
|
}
|
|
225
|
-
if (!this.debuggerStatus) {
|
|
226
|
-
throw kerror.get("core", "debugger", "not_enabled");
|
|
227
|
-
}
|
|
228
127
|
const event = request.getBodyString("event");
|
|
229
|
-
|
|
230
|
-
if (listeners) {
|
|
231
|
-
listeners.delete(request.context.connection.id);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Execute a method using the Chrome Debug Protocol
|
|
236
|
-
* @param method Chrome Debug Protocol method to execute
|
|
237
|
-
* @param params
|
|
238
|
-
* @returns
|
|
239
|
-
*/
|
|
240
|
-
async inspectorPost(method, params) {
|
|
241
|
-
if (!this.debuggerStatus) {
|
|
242
|
-
throw kerror.get("core", "debugger", "not_enabled");
|
|
243
|
-
}
|
|
244
|
-
let resolve;
|
|
245
|
-
const promise = new Promise((res) => {
|
|
246
|
-
resolve = res;
|
|
247
|
-
});
|
|
248
|
-
this.inspector.post(method, params, (err, res) => {
|
|
249
|
-
if (err) {
|
|
250
|
-
resolve({
|
|
251
|
-
error: JSON.stringify(Object.getOwnPropertyDescriptors(err)),
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
resolve(res);
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
|
-
return promise;
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Sends a direct notification to a websocket connection without having to listen to a specific room
|
|
262
|
-
*/
|
|
263
|
-
async notifyConnection(connectionId, event, payload) {
|
|
264
|
-
global.kuzzle.entryPoint._notify({
|
|
265
|
-
channels: [event],
|
|
266
|
-
connectionId,
|
|
267
|
-
payload,
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
async notifyGlobalListeners(event, payload) {
|
|
271
|
-
const listeners = this.events.get("*");
|
|
272
|
-
if (!listeners) {
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
const promises = [];
|
|
276
|
-
for (const connectionId of listeners) {
|
|
277
|
-
promises.push(this.notifyConnection(connectionId, DEBUGGER_EVENT, {
|
|
278
|
-
event,
|
|
279
|
-
result: payload,
|
|
280
|
-
}));
|
|
281
|
-
}
|
|
282
|
-
// No need to catch, notify is already try-catched
|
|
283
|
-
await Promise.all(promises);
|
|
128
|
+
await global.kuzzle.ask("core:debugger:removeListener", event, request.context.connection.id);
|
|
284
129
|
}
|
|
285
130
|
}
|
|
286
131
|
exports.DebugController = DebugController;
|
|
@@ -390,12 +390,34 @@ class DocumentController extends NativeController {
|
|
|
390
390
|
|
|
391
391
|
const validated = await global.kuzzle.validation.validate(request, false);
|
|
392
392
|
|
|
393
|
+
// Add metadata
|
|
394
|
+
const pipeMetadataResult = await this.pipe(
|
|
395
|
+
"generic:document:injectMetadata",
|
|
396
|
+
{
|
|
397
|
+
metadata: {
|
|
398
|
+
author: userId,
|
|
399
|
+
createdAt: Date.now(),
|
|
400
|
+
updatedAt: null,
|
|
401
|
+
updater: null,
|
|
402
|
+
},
|
|
403
|
+
request,
|
|
404
|
+
}
|
|
405
|
+
);
|
|
406
|
+
|
|
393
407
|
const created = await this.ask(
|
|
394
408
|
"core:storage:public:document:create",
|
|
395
409
|
index,
|
|
396
410
|
collection,
|
|
397
|
-
|
|
398
|
-
|
|
411
|
+
{
|
|
412
|
+
...validated.getBody(),
|
|
413
|
+
_kuzzle_info: pipeMetadataResult.metadata,
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
id,
|
|
417
|
+
injectKuzzleMeta: false,
|
|
418
|
+
refresh,
|
|
419
|
+
userId,
|
|
420
|
+
}
|
|
399
421
|
);
|
|
400
422
|
|
|
401
423
|
if (!silent) {
|
|
@@ -440,13 +462,34 @@ class DocumentController extends NativeController {
|
|
|
440
462
|
false
|
|
441
463
|
);
|
|
442
464
|
|
|
465
|
+
// Add metadata
|
|
466
|
+
const pipeMetadataResult = await this.pipe(
|
|
467
|
+
"generic:document:injectMetadata",
|
|
468
|
+
{
|
|
469
|
+
metadata: {
|
|
470
|
+
author: userId,
|
|
471
|
+
createdAt: Date.now(),
|
|
472
|
+
updatedAt: Date.now(),
|
|
473
|
+
updater: userId,
|
|
474
|
+
},
|
|
475
|
+
request,
|
|
476
|
+
}
|
|
477
|
+
);
|
|
478
|
+
|
|
443
479
|
const response = await this.ask(
|
|
444
480
|
"core:storage:public:document:createOrReplace",
|
|
445
481
|
index,
|
|
446
482
|
collection,
|
|
447
483
|
id,
|
|
448
|
-
|
|
449
|
-
|
|
484
|
+
{
|
|
485
|
+
...content,
|
|
486
|
+
_kuzzle_info: pipeMetadataResult.metadata,
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
injectKuzzleMeta: false,
|
|
490
|
+
refresh,
|
|
491
|
+
userId,
|
|
492
|
+
}
|
|
450
493
|
);
|
|
451
494
|
|
|
452
495
|
if (!silent) {
|
|
@@ -493,13 +536,33 @@ class DocumentController extends NativeController {
|
|
|
493
536
|
false
|
|
494
537
|
);
|
|
495
538
|
|
|
539
|
+
// Add metadata
|
|
540
|
+
const pipeMetadataResult = await this.pipe(
|
|
541
|
+
"generic:document:injectMetadata",
|
|
542
|
+
{
|
|
543
|
+
metadata: {
|
|
544
|
+
updatedAt: Date.now(),
|
|
545
|
+
updater: userId,
|
|
546
|
+
},
|
|
547
|
+
request,
|
|
548
|
+
}
|
|
549
|
+
);
|
|
550
|
+
|
|
496
551
|
const updatedDocument = await this.ask(
|
|
497
552
|
"core:storage:public:document:update",
|
|
498
553
|
index,
|
|
499
554
|
collection,
|
|
500
555
|
id,
|
|
501
|
-
|
|
502
|
-
|
|
556
|
+
{
|
|
557
|
+
...content,
|
|
558
|
+
_kuzzle_info: pipeMetadataResult.metadata,
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
injectKuzzleMeta: false,
|
|
562
|
+
refresh,
|
|
563
|
+
retryOnConflict,
|
|
564
|
+
userId,
|
|
565
|
+
}
|
|
503
566
|
);
|
|
504
567
|
|
|
505
568
|
const _updatedFields = extractFields(content, {
|
|
@@ -548,13 +611,41 @@ class DocumentController extends NativeController {
|
|
|
548
611
|
const source = request.getBoolean("source");
|
|
549
612
|
const { index, collection } = request.getIndexAndCollection();
|
|
550
613
|
|
|
614
|
+
// Add metadata
|
|
615
|
+
const pipeMetadataResult = await this.pipe(
|
|
616
|
+
"generic:document:injectMetadata",
|
|
617
|
+
{
|
|
618
|
+
defaultMetadata: {
|
|
619
|
+
author: userId,
|
|
620
|
+
createdAt: Date.now(),
|
|
621
|
+
},
|
|
622
|
+
metadata: {
|
|
623
|
+
updatedAt: Date.now(),
|
|
624
|
+
updater: userId,
|
|
625
|
+
},
|
|
626
|
+
request,
|
|
627
|
+
}
|
|
628
|
+
);
|
|
629
|
+
|
|
551
630
|
const updatedDocument = await this.ask(
|
|
552
631
|
"core:storage:public:document:upsert",
|
|
553
632
|
index,
|
|
554
633
|
collection,
|
|
555
634
|
id,
|
|
556
|
-
|
|
557
|
-
|
|
635
|
+
{
|
|
636
|
+
...content,
|
|
637
|
+
_kuzzle_info: pipeMetadataResult.metadata,
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
defaultValues: {
|
|
641
|
+
...defaultValues,
|
|
642
|
+
_kuzzle_info: pipeMetadataResult.defaultMetadata,
|
|
643
|
+
},
|
|
644
|
+
injectKuzzleMeta: false,
|
|
645
|
+
refresh,
|
|
646
|
+
retryOnConflict,
|
|
647
|
+
userId,
|
|
648
|
+
}
|
|
558
649
|
);
|
|
559
650
|
|
|
560
651
|
if (!silent && updatedDocument.created) {
|
|
@@ -633,13 +724,34 @@ class DocumentController extends NativeController {
|
|
|
633
724
|
false
|
|
634
725
|
);
|
|
635
726
|
|
|
727
|
+
// Add metadata
|
|
728
|
+
const pipeMetadataResult = await this.pipe(
|
|
729
|
+
"generic:document:injectMetadata",
|
|
730
|
+
{
|
|
731
|
+
metadata: {
|
|
732
|
+
author: userId,
|
|
733
|
+
createdAt: Date.now(),
|
|
734
|
+
updatedAt: Date.now(),
|
|
735
|
+
updater: userId,
|
|
736
|
+
},
|
|
737
|
+
request,
|
|
738
|
+
}
|
|
739
|
+
);
|
|
740
|
+
|
|
636
741
|
const response = await this.ask(
|
|
637
742
|
"core:storage:public:document:replace",
|
|
638
743
|
index,
|
|
639
744
|
collection,
|
|
640
745
|
id,
|
|
641
|
-
|
|
642
|
-
|
|
746
|
+
{
|
|
747
|
+
...content,
|
|
748
|
+
_kuzzle_info: pipeMetadataResult.metadata,
|
|
749
|
+
},
|
|
750
|
+
{
|
|
751
|
+
injectKuzzleMeta: false,
|
|
752
|
+
refresh,
|
|
753
|
+
userId,
|
|
754
|
+
}
|
|
643
755
|
);
|
|
644
756
|
|
|
645
757
|
if (!silent) {
|
package/lib/api/funnel.js
CHANGED
|
@@ -51,6 +51,7 @@ const debug = require("../util/debug")("kuzzle:funnel");
|
|
|
51
51
|
const processError = kerror.wrap("api", "process");
|
|
52
52
|
const { has } = require("../util/safeObject");
|
|
53
53
|
const { HttpStream } = require("../types");
|
|
54
|
+
const get = require("lodash/get");
|
|
54
55
|
|
|
55
56
|
// Actions of the auth controller that does not necessite to verify the token
|
|
56
57
|
// when cookie auth is active
|
|
@@ -179,6 +180,12 @@ class Funnel {
|
|
|
179
180
|
throw processError.get("not_enough_nodes");
|
|
180
181
|
}
|
|
181
182
|
|
|
183
|
+
const isRequestFromDebugSession = get(
|
|
184
|
+
request,
|
|
185
|
+
"context.connection.misc.internal.debugSession",
|
|
186
|
+
false
|
|
187
|
+
);
|
|
188
|
+
|
|
182
189
|
if (this.overloaded) {
|
|
183
190
|
const now = Date.now();
|
|
184
191
|
|
|
@@ -226,7 +233,8 @@ class Funnel {
|
|
|
226
233
|
*/
|
|
227
234
|
if (
|
|
228
235
|
this.pendingRequestsQueue.length >=
|
|
229
|
-
|
|
236
|
+
global.kuzzle.config.limits.requestsBufferSize &&
|
|
237
|
+
!isRequestFromDebugSession
|
|
230
238
|
) {
|
|
231
239
|
const error = processError.get("overloaded");
|
|
232
240
|
global.kuzzle.emit("log:error", error);
|
|
@@ -239,7 +247,13 @@ class Funnel {
|
|
|
239
247
|
request.internalId,
|
|
240
248
|
new PendingRequest(request, fn, context)
|
|
241
249
|
);
|
|
242
|
-
|
|
250
|
+
|
|
251
|
+
if (isRequestFromDebugSession) {
|
|
252
|
+
// Push at the front to prioritize debug requests
|
|
253
|
+
this.pendingRequestsQueue.unshift(request.internalId);
|
|
254
|
+
} else {
|
|
255
|
+
this.pendingRequestsQueue.push(request.internalId);
|
|
256
|
+
}
|
|
243
257
|
|
|
244
258
|
if (!this.overloaded) {
|
|
245
259
|
this.overloaded = true;
|
|
@@ -135,6 +135,14 @@ export declare class KuzzleRequest {
|
|
|
135
135
|
status: number;
|
|
136
136
|
timestamp: number;
|
|
137
137
|
};
|
|
138
|
+
/**
|
|
139
|
+
* Return the requested controller
|
|
140
|
+
*/
|
|
141
|
+
getController(): string;
|
|
142
|
+
/**
|
|
143
|
+
* Returns the requested controller's action
|
|
144
|
+
*/
|
|
145
|
+
getAction(): string;
|
|
138
146
|
/**
|
|
139
147
|
* Returns the `lang` param of the request.
|
|
140
148
|
*
|
|
@@ -324,6 +324,18 @@ class KuzzleRequest {
|
|
|
324
324
|
timestamp: this.timestamp,
|
|
325
325
|
};
|
|
326
326
|
}
|
|
327
|
+
/**
|
|
328
|
+
* Return the requested controller
|
|
329
|
+
*/
|
|
330
|
+
getController() {
|
|
331
|
+
return this[_input].controller;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Returns the requested controller's action
|
|
335
|
+
*/
|
|
336
|
+
getAction() {
|
|
337
|
+
return this[_input].action;
|
|
338
|
+
}
|
|
327
339
|
/**
|
|
328
340
|
* Returns the `lang` param of the request.
|
|
329
341
|
*
|
|
@@ -25,7 +25,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.ClusterIdCardHandler = exports.IdCard = void 0;
|
|
27
27
|
const name_generator_1 = require("../util/name-generator");
|
|
28
|
-
const
|
|
28
|
+
const child_process_1 = require("child_process");
|
|
29
29
|
const bluebird_1 = __importDefault(require("bluebird"));
|
|
30
30
|
require("../types");
|
|
31
31
|
const REDIS_PREFIX = "{cluster/node}/";
|
|
@@ -110,14 +110,16 @@ class ClusterIdCardHandler {
|
|
|
110
110
|
} while (!reserved);
|
|
111
111
|
await this.addIdCardToIndex();
|
|
112
112
|
this.refreshWorker = this.constructWorker(`${__dirname}/workers/IDCardRenewer.js`);
|
|
113
|
-
this.refreshWorker.unref();
|
|
114
113
|
this.refreshWorker.on("message", async (message) => {
|
|
115
114
|
if (message.error) {
|
|
116
115
|
await this.node.evictSelf(message.error);
|
|
117
116
|
}
|
|
118
117
|
});
|
|
118
|
+
this.refreshWorker.on("close", () => {
|
|
119
|
+
this.disposed = true;
|
|
120
|
+
});
|
|
119
121
|
// Transfer informations to the worker
|
|
120
|
-
this.refreshWorker.
|
|
122
|
+
this.refreshWorker.send({
|
|
121
123
|
action: "start",
|
|
122
124
|
kuzzle: {
|
|
123
125
|
config: global.kuzzle.config,
|
|
@@ -138,7 +140,7 @@ class ClusterIdCardHandler {
|
|
|
138
140
|
* Helper method to mock worker instantiation in unit tests
|
|
139
141
|
*/
|
|
140
142
|
constructWorker(path) {
|
|
141
|
-
return
|
|
143
|
+
return (0, child_process_1.fork)(path);
|
|
142
144
|
}
|
|
143
145
|
/**
|
|
144
146
|
* Start refreshing the ID Card before the worker starts to ensure the ID Card
|
|
@@ -163,9 +165,20 @@ class ClusterIdCardHandler {
|
|
|
163
165
|
});
|
|
164
166
|
}
|
|
165
167
|
async dispose() {
|
|
168
|
+
if (this.disposed) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
166
171
|
this.disposed = true;
|
|
167
|
-
if (this.refreshWorker
|
|
168
|
-
this.refreshWorker.
|
|
172
|
+
if (this.refreshWorker &&
|
|
173
|
+
this.refreshWorker.connected &&
|
|
174
|
+
!this.refreshWorker.killed &&
|
|
175
|
+
this.refreshWorker.channel) {
|
|
176
|
+
try {
|
|
177
|
+
this.refreshWorker.send({ action: "dispose" });
|
|
178
|
+
}
|
|
179
|
+
catch (e) {
|
|
180
|
+
// It could happens that the worker has been killed before the dispose causing send to fail
|
|
181
|
+
}
|
|
169
182
|
}
|
|
170
183
|
}
|
|
171
184
|
/**
|
package/lib/cluster/node.js
CHANGED
|
@@ -249,6 +249,24 @@ class ClusterNode {
|
|
|
249
249
|
this.command.dispose();
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Notify other nodes to not evict this node
|
|
254
|
+
*
|
|
255
|
+
* @param {bool} evictionPrevented
|
|
256
|
+
*/
|
|
257
|
+
preventEviction(evictionPrevented) {
|
|
258
|
+
this.publisher.sendNodePreventEviction(evictionPrevented);
|
|
259
|
+
// This node is subscribed to the other node and might not receive their heartbeat while debugging
|
|
260
|
+
// so this node should not have the responsability of evicting others when his own eviction is prevented
|
|
261
|
+
// when debugging.
|
|
262
|
+
// Otherwise when recovering from a debug session, all the other nodes will be evicted.
|
|
263
|
+
for (const subscriber of this.remoteNodes.values()) {
|
|
264
|
+
subscriber.handleNodePreventEviction({
|
|
265
|
+
evictionPrevented,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
252
270
|
/**
|
|
253
271
|
* Adds a new remote node, and subscribes to it.
|
|
254
272
|
* @param {string} id - remote node ID
|
|
@@ -678,6 +696,10 @@ class ClusterNode {
|
|
|
678
696
|
* Registers ask events
|
|
679
697
|
*/
|
|
680
698
|
registerAskEvents() {
|
|
699
|
+
global.kuzzle.onAsk("cluster:node:preventEviction", (state) => {
|
|
700
|
+
this.preventEviction(state);
|
|
701
|
+
});
|
|
702
|
+
|
|
681
703
|
/**
|
|
682
704
|
* Removes a room from the full state, and only for this node.
|
|
683
705
|
* Removes the room from Koncorde if, and only if, no other node uses it.
|
|
@@ -816,7 +838,11 @@ class ClusterNode {
|
|
|
816
838
|
this.onAuthStrategyRemoved(name, pluginName)
|
|
817
839
|
);
|
|
818
840
|
|
|
819
|
-
global.kuzzle.on("admin:afterDump", (
|
|
841
|
+
global.kuzzle.on("admin:afterDump", (request) => {
|
|
842
|
+
const suffix = request.getString("suffix", "manual-api-action");
|
|
843
|
+
|
|
844
|
+
return this.onDumpRequest(suffix);
|
|
845
|
+
});
|
|
820
846
|
|
|
821
847
|
global.kuzzle.on("admin:afterResetSecurity", () => this.onSecurityReset());
|
|
822
848
|
|