kuzzle 2.14.14 → 2.15.2
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/adminController.js +5 -0
- package/lib/api/controllers/documentController.js +1 -5
- package/lib/cluster/idCardHandler.d.ts +140 -0
- package/lib/cluster/idCardHandler.js +219 -172
- package/lib/cluster/node.js +19 -8
- package/lib/cluster/protobuf/sync.proto +4 -0
- package/lib/cluster/subscriber.js +10 -1
- package/lib/cluster/workers/IDCardRenewer.js +13 -7
- package/lib/config/httpRoutes.js +1 -0
- package/lib/core/cache/cacheEngine.js +9 -0
- package/lib/core/realtime/hotelClerk.js +6 -6
- package/lib/core/realtime/notifier.js +16 -18
- package/lib/core/storage/clientAdapter.js +11 -5
- package/lib/core/storage/indexCache.d.ts +55 -0
- package/lib/core/storage/indexCache.js +97 -130
- package/lib/kuzzle/kuzzle.js +2 -2
- package/lib/service/storage/elasticsearch.js +14 -9
- package/package-lock.json +175 -134
- package/package.json +13 -13
|
@@ -88,6 +88,7 @@ class ClusterSubscriber {
|
|
|
88
88
|
NewRealtimeRoom: this.handleNewRealtimeRoom,
|
|
89
89
|
NodeEvicted: this.handleNodeEviction,
|
|
90
90
|
NodeShutdown: this.handleNodeShutdown,
|
|
91
|
+
RefreshIndexCache: this.handleRefreshIndexCache,
|
|
91
92
|
RefreshValidators: this.handleRefreshValidators,
|
|
92
93
|
RemoveAuthStrategy: this.handleAuthStrategyRemoval,
|
|
93
94
|
RemoveCollection: this.handleCollectionRemoval,
|
|
@@ -210,7 +211,7 @@ class ClusterSubscriber {
|
|
|
210
211
|
|
|
211
212
|
const message = decoder.toObject(decoder.decode(data));
|
|
212
213
|
|
|
213
|
-
if (!await this.validateMessage(message)) {
|
|
214
|
+
if (! await this.validateMessage(message)) {
|
|
214
215
|
return;
|
|
215
216
|
}
|
|
216
217
|
|
|
@@ -497,6 +498,14 @@ class ClusterSubscriber {
|
|
|
497
498
|
await global.kuzzle.validation.curateSpecification();
|
|
498
499
|
}
|
|
499
500
|
|
|
501
|
+
/**
|
|
502
|
+
* Handles manual refresh of the index cache
|
|
503
|
+
*/
|
|
504
|
+
async handleRefreshIndexCache () {
|
|
505
|
+
debug('Index cache manually refresh received from node %s', this.remoteNodeId);
|
|
506
|
+
await global.kuzzle.ask('core:storage:public:cache:refresh', { from: 'cluster' });
|
|
507
|
+
}
|
|
508
|
+
|
|
500
509
|
/**
|
|
501
510
|
* Invalidates a profile to force reloading it from the storage space
|
|
502
511
|
*
|
|
@@ -15,14 +15,15 @@ class IDCardRenewer {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
async init (config) {
|
|
18
|
-
if (!this.disposed) {
|
|
19
|
-
return; // Already
|
|
18
|
+
if (! this.disposed) {
|
|
19
|
+
return; // Already initialized
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
this.disposed = false;
|
|
23
23
|
this.nodeIdKey = config.nodeIdKey;
|
|
24
24
|
this.refreshDelay = config.refreshDelay || 2000;
|
|
25
|
-
|
|
25
|
+
this.refreshMultiplier = config.refreshMultiplier;
|
|
26
|
+
|
|
26
27
|
/**
|
|
27
28
|
* Since we do not have access to the Kuzzle Context we can't use kuzzle.ask('core:cache:internal:*',...),
|
|
28
29
|
* so we need to have an instance of Redis similar to the one used in the Cache Engine
|
|
@@ -48,6 +49,9 @@ class IDCardRenewer {
|
|
|
48
49
|
this.renewIDCard.bind(this),
|
|
49
50
|
this.refreshDelay);
|
|
50
51
|
}
|
|
52
|
+
|
|
53
|
+
// Notify that the worker is running and updating the ID Card
|
|
54
|
+
this.parentPort.postMessage({ initialized: true });
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
async initRedis (config, name) {
|
|
@@ -63,7 +67,7 @@ class IDCardRenewer {
|
|
|
63
67
|
try {
|
|
64
68
|
const refreshed = await this.redis.commands.pexpire(
|
|
65
69
|
this.nodeIdKey,
|
|
66
|
-
this.refreshDelay *
|
|
70
|
+
this.refreshDelay * this.refreshMultiplier);
|
|
67
71
|
// Unable to refresh the key in time before it expires
|
|
68
72
|
// => this node is too slow, we need to remove it from the cluster
|
|
69
73
|
if (refreshed === 0) {
|
|
@@ -99,7 +103,8 @@ class IDCardRenewer {
|
|
|
99
103
|
|
|
100
104
|
if (!isMainThread) {
|
|
101
105
|
const idCardRenewer = new IDCardRenewer();
|
|
102
|
-
|
|
106
|
+
|
|
107
|
+
parentPort.on('message', async message => {
|
|
103
108
|
if (message.action === 'start') {
|
|
104
109
|
// Simulate basic global Kuzzle Context
|
|
105
110
|
global.kuzzle = { ...message.kuzzle };
|
|
@@ -111,11 +116,12 @@ if (!isMainThread) {
|
|
|
111
116
|
};
|
|
112
117
|
// Should never throw
|
|
113
118
|
await idCardRenewer.init(message);
|
|
114
|
-
}
|
|
119
|
+
}
|
|
120
|
+
else if (message.action === 'dispose') {
|
|
115
121
|
// Should never throw
|
|
116
122
|
await idCardRenewer.dispose();
|
|
117
123
|
}
|
|
118
|
-
});
|
|
124
|
+
});
|
|
119
125
|
}
|
|
120
126
|
|
|
121
127
|
module.exports = { IDCardRenewer };
|
package/lib/config/httpRoutes.js
CHANGED
|
@@ -46,6 +46,7 @@ const routes = [
|
|
|
46
46
|
{ verb: 'get', path: '/validations/_scroll/:scrollId', controller: 'collection', action: 'scrollSpecifications' },
|
|
47
47
|
{ verb: 'get', path: '/:index/_list', controller: 'collection', action: 'list' },
|
|
48
48
|
|
|
49
|
+
{ verb: 'post', path: '/admin/_refreshIndexCache', controller: 'admin', action: 'refreshIndexCache' },
|
|
49
50
|
{ verb: 'post', path: '/admin/_resetCache', controller: 'admin', action: 'resetCache' },
|
|
50
51
|
{ verb: 'post', path: '/admin/_resetSecurity', controller: 'admin', action: 'resetSecurity' },
|
|
51
52
|
{ verb: 'post', path: '/admin/_resetDatabase', controller: 'admin', action: 'resetDatabase' },
|
|
@@ -180,6 +180,15 @@ class CacheEngine {
|
|
|
180
180
|
global.kuzzle.onAsk(
|
|
181
181
|
'core:cache:internal:store',
|
|
182
182
|
(key, value, opts) => this.internal.store(key, value, opts));
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Executes an arbitrary NATIVE cache command directly
|
|
186
|
+
* @param {string} command
|
|
187
|
+
* @param {Array} args -- command arguments
|
|
188
|
+
*/
|
|
189
|
+
global.kuzzle.onAsk(
|
|
190
|
+
'core:cache:internal:execute',
|
|
191
|
+
(command, ...args) => this.internal.exec(command, ...args));
|
|
183
192
|
}
|
|
184
193
|
|
|
185
194
|
registerPublicEvents () {
|
|
@@ -381,7 +381,7 @@ class HotelClerk {
|
|
|
381
381
|
}, requestContext);
|
|
382
382
|
await this.module.notifier.notifyUser(roomId, request, 'out', { count: room.size });
|
|
383
383
|
// Do not send an unsubscription notification if the room has been destroyed
|
|
384
|
-
//
|
|
384
|
+
// because the other nodes already had destroyed it in the full state
|
|
385
385
|
if (notify
|
|
386
386
|
&& this.rooms.has(roomId)
|
|
387
387
|
&& room.channels.size > 0) {
|
|
@@ -417,6 +417,11 @@ class HotelClerk {
|
|
|
417
417
|
async removeRoom(roomId) {
|
|
418
418
|
this.roomsCount--;
|
|
419
419
|
this.rooms.delete(roomId);
|
|
420
|
+
// We have to ask the cluster to dispatch the room removal event.
|
|
421
|
+
// The cluster will also remove the room from Koncorde if no other node
|
|
422
|
+
// uses it.
|
|
423
|
+
// (this node may have no subscribers on it, but other nodes might)
|
|
424
|
+
await global.kuzzle.ask('cluster:realtime:room:remove', roomId);
|
|
420
425
|
// @deprecated -- to be removed in the next major version
|
|
421
426
|
try {
|
|
422
427
|
await global.kuzzle.pipe('room:remove', roomId);
|
|
@@ -424,11 +429,6 @@ class HotelClerk {
|
|
|
424
429
|
catch (e) {
|
|
425
430
|
return;
|
|
426
431
|
}
|
|
427
|
-
// We have to ask the cluster to dispatch the room removal event.
|
|
428
|
-
// The cluster will also remove the room from Koncorde if no other node
|
|
429
|
-
// uses it.
|
|
430
|
-
// (this node may have no subscribers on it, but other nodes might)
|
|
431
|
-
await global.kuzzle.ask('cluster:realtime:room:remove', roomId);
|
|
432
432
|
}
|
|
433
433
|
/**
|
|
434
434
|
* Subscribes a connection to an existing room.
|
|
@@ -249,9 +249,7 @@ class NotifierController {
|
|
|
249
249
|
if (cache !== null) {
|
|
250
250
|
const stopListening = difference(JSON.parse(cache), rooms);
|
|
251
251
|
|
|
252
|
-
await this.notifyDocument(stopListening, request, 'out', 'replace',
|
|
253
|
-
_id: document._id,
|
|
254
|
-
});
|
|
252
|
+
await this.notifyDocument(stopListening, request, 'out', 'replace', document);
|
|
255
253
|
}
|
|
256
254
|
|
|
257
255
|
return rooms;
|
|
@@ -281,25 +279,29 @@ class NotifierController {
|
|
|
281
279
|
: [];
|
|
282
280
|
|
|
283
281
|
const result = await Bluebird.map(documents, (doc, index) => {
|
|
284
|
-
switch(action) {
|
|
282
|
+
switch (action) {
|
|
285
283
|
case actionEnum.CREATE:
|
|
286
284
|
return this.notifyDocumentCreate(request, doc);
|
|
285
|
+
|
|
287
286
|
case actionEnum.DELETE:
|
|
288
287
|
return this.notifyDocumentDelete(request, doc);
|
|
288
|
+
|
|
289
289
|
case actionEnum.REPLACE:
|
|
290
290
|
return this.notifyDocumentReplace(request, doc, cache[index]);
|
|
291
|
+
|
|
291
292
|
case actionEnum.UPDATE:
|
|
292
293
|
return this.notifyDocumentUpdate(request, doc, cache[index]);
|
|
294
|
+
|
|
293
295
|
case actionEnum.UPSERT:
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
return doc.created
|
|
297
|
+
? this.notifyDocumentCreate(request, doc)
|
|
298
|
+
: this.notifyDocumentUpdate(request, doc, cache[index]);
|
|
299
|
+
|
|
298
300
|
case actionEnum.WRITE:
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
301
|
+
return doc.created
|
|
302
|
+
? this.notifyDocumentCreate(request, doc)
|
|
303
|
+
: this.notifyDocumentReplace(request, doc, cache[index]);
|
|
304
|
+
|
|
303
305
|
default:
|
|
304
306
|
throw kerror.get('core', 'fatal', 'assertion_failed', `unknown notify action "${doc.action}"`);
|
|
305
307
|
}
|
|
@@ -342,9 +344,7 @@ class NotifierController {
|
|
|
342
344
|
if (cache !== null) {
|
|
343
345
|
const stopListening = difference(JSON.parse(cache), rooms);
|
|
344
346
|
|
|
345
|
-
await this.notifyDocument(stopListening, request, 'out', 'update',
|
|
346
|
-
_id: document._id,
|
|
347
|
-
});
|
|
347
|
+
await this.notifyDocument(stopListening, request, 'out', 'update', document);
|
|
348
348
|
}
|
|
349
349
|
|
|
350
350
|
return rooms;
|
|
@@ -361,9 +361,7 @@ class NotifierController {
|
|
|
361
361
|
const rooms = this._test(request, document._source, document._id);
|
|
362
362
|
|
|
363
363
|
if (rooms.length > 0) {
|
|
364
|
-
await this.notifyDocument(rooms, request, 'out', 'delete',
|
|
365
|
-
_id: document._id,
|
|
366
|
-
});
|
|
364
|
+
await this.notifyDocument(rooms, request, 'out', 'delete', document);
|
|
367
365
|
}
|
|
368
366
|
|
|
369
367
|
return [];
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
'use strict';
|
|
23
23
|
|
|
24
24
|
const Elasticsearch = require('../../service/storage/elasticsearch');
|
|
25
|
-
const IndexCache = require('./indexCache');
|
|
25
|
+
const { IndexCache } = require('./indexCache');
|
|
26
26
|
const { isPlainObject } = require('../../util/safeObject');
|
|
27
27
|
const kerror = require('../../kerror');
|
|
28
28
|
const { Mutex } = require('../../util/mutex');
|
|
@@ -42,7 +42,7 @@ class ClientAdapter {
|
|
|
42
42
|
global.kuzzle.config.services.storageEngine,
|
|
43
43
|
scope);
|
|
44
44
|
this.scope = scope;
|
|
45
|
-
this.cache = new IndexCache(
|
|
45
|
+
this.cache = new IndexCache();
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
async init () {
|
|
@@ -57,6 +57,13 @@ class ClientAdapter {
|
|
|
57
57
|
|
|
58
58
|
// Global store events registration
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Manually refresh the index cache (e.g. after alias creation)
|
|
62
|
+
*/
|
|
63
|
+
global.kuzzle.onAsk(
|
|
64
|
+
`core:storage:${this.scope}:cache:refresh`,
|
|
65
|
+
() => this.populateCache());
|
|
66
|
+
|
|
60
67
|
/**
|
|
61
68
|
* Return information about the instantiated ES service
|
|
62
69
|
* @returns {Promise.<Object>}
|
|
@@ -77,7 +84,6 @@ class ClientAdapter {
|
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
async createIndex (index, { indexCacheOnly=false, propagate=true } = {}) {
|
|
80
|
-
|
|
81
87
|
if (this.cache.hasIndex(index)) {
|
|
82
88
|
throw servicesError.get('index_already_exists', this.scope, index);
|
|
83
89
|
}
|
|
@@ -264,7 +270,7 @@ class ClientAdapter {
|
|
|
264
270
|
`core:storage:${this.scope}:collection:update`,
|
|
265
271
|
(index, collection, changes) => {
|
|
266
272
|
this.cache.assertCollectionExists(index, collection);
|
|
267
|
-
this.client.updateCollection(index, collection, changes);
|
|
273
|
+
return this.client.updateCollection(index, collection, changes);
|
|
268
274
|
});
|
|
269
275
|
}
|
|
270
276
|
|
|
@@ -856,7 +862,7 @@ class ClientAdapter {
|
|
|
856
862
|
* @returns {Promise}
|
|
857
863
|
*/
|
|
858
864
|
async loadMappings (
|
|
859
|
-
fixtures = {},
|
|
865
|
+
fixtures = {},
|
|
860
866
|
options = {
|
|
861
867
|
indexCacheOnly: false,
|
|
862
868
|
propagate: true,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export declare class IndexCache {
|
|
2
|
+
/**
|
|
3
|
+
* Index map: each entry holds a set of collection names
|
|
4
|
+
*
|
|
5
|
+
* Map<index, Set<collection>>
|
|
6
|
+
*/
|
|
7
|
+
private indexes;
|
|
8
|
+
constructor();
|
|
9
|
+
/**
|
|
10
|
+
* Cache a new index
|
|
11
|
+
*
|
|
12
|
+
* @return true if an index was added, false if there is no modification
|
|
13
|
+
*/
|
|
14
|
+
addIndex(index: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Cache a new collection
|
|
17
|
+
*/
|
|
18
|
+
addCollection(index: string, collection: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* Check an index existence
|
|
21
|
+
*/
|
|
22
|
+
hasIndex(index: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Check a collection existence
|
|
25
|
+
*/
|
|
26
|
+
hasCollection(index: string, collection: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Return the list of cached indexes
|
|
29
|
+
*/
|
|
30
|
+
listIndexes(): string[];
|
|
31
|
+
/**
|
|
32
|
+
* Return the list of an index collections
|
|
33
|
+
*
|
|
34
|
+
* @throws If the provided index does not exist
|
|
35
|
+
*/
|
|
36
|
+
listCollections(index: string): string[];
|
|
37
|
+
/**
|
|
38
|
+
* Remove an index from the cache
|
|
39
|
+
*/
|
|
40
|
+
removeIndex(index: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Remove a collection from the cache
|
|
43
|
+
*/
|
|
44
|
+
removeCollection(index: string, collection: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Assert that the provided index exists
|
|
47
|
+
*
|
|
48
|
+
* @throws If the index does not exist
|
|
49
|
+
*/
|
|
50
|
+
assertIndexExists(index: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Assert that the provided index and collection exist
|
|
53
|
+
*/
|
|
54
|
+
assertCollectionExists(index: string, collection: string): void;
|
|
55
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/*
|
|
2
3
|
* Kuzzle, a backend software, self-hostable and ready to use
|
|
3
4
|
* to power modern apps
|
|
@@ -18,142 +19,108 @@
|
|
|
18
19
|
* See the License for the specific language governing permissions and
|
|
19
20
|
* limitations under the License.
|
|
20
21
|
*/
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
23
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.IndexCache = void 0;
|
|
27
|
+
const kerror_1 = __importDefault(require("../../kerror"));
|
|
28
|
+
const storageError = kerror_1.default.wrap('services', 'storage');
|
|
26
29
|
class IndexCache {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
constructor() {
|
|
31
|
+
/**
|
|
32
|
+
* Index map: each entry holds a set of collection names
|
|
33
|
+
*
|
|
34
|
+
* Map<index, Set<collection>>
|
|
35
|
+
*/
|
|
36
|
+
this.indexes = new Map();
|
|
37
|
+
this.indexes = new Map();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Cache a new index
|
|
41
|
+
*
|
|
42
|
+
* @return true if an index was added, false if there is no modification
|
|
43
|
+
*/
|
|
44
|
+
addIndex(index) {
|
|
45
|
+
if (this.indexes.has(index)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
this.indexes.set(index, new Set());
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Cache a new collection
|
|
53
|
+
*/
|
|
54
|
+
addCollection(index, collection) {
|
|
55
|
+
this.addIndex(index);
|
|
56
|
+
const collections = this.indexes.get(index);
|
|
57
|
+
collections.add(collection);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Check an index existence
|
|
61
|
+
*/
|
|
62
|
+
hasIndex(index) {
|
|
63
|
+
return this.indexes.has(index);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Check a collection existence
|
|
67
|
+
*/
|
|
68
|
+
hasCollection(index, collection) {
|
|
69
|
+
const collections = this.indexes.get(index);
|
|
70
|
+
if (!collections) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
return collections.has(collection);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Return the list of cached indexes
|
|
77
|
+
*/
|
|
78
|
+
listIndexes() {
|
|
79
|
+
return Array.from(this.indexes.keys());
|
|
80
|
+
}
|
|
33
81
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
82
|
+
* Return the list of an index collections
|
|
83
|
+
*
|
|
84
|
+
* @throws If the provided index does not exist
|
|
36
85
|
*/
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Cache a new index
|
|
42
|
-
* @param {string} index
|
|
43
|
-
* @return {boolean} true if an index was added, false if there is no
|
|
44
|
-
* modification
|
|
45
|
-
*/
|
|
46
|
-
addIndex (index) {
|
|
47
|
-
if (this.indexes.has(index)) {
|
|
48
|
-
return false;
|
|
86
|
+
listCollections(index) {
|
|
87
|
+
this.assertIndexExists(index);
|
|
88
|
+
return Array.from(this.indexes.get(index));
|
|
49
89
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Cache a new collection
|
|
58
|
-
* @param {string} index
|
|
59
|
-
* @param {string} collection
|
|
60
|
-
*/
|
|
61
|
-
addCollection (index, collection) {
|
|
62
|
-
this.addIndex(index);
|
|
63
|
-
const collections = this.indexes.get(index);
|
|
64
|
-
|
|
65
|
-
collections.add(collection);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Check an index existence
|
|
70
|
-
* @param {string} index
|
|
71
|
-
* @returns {boolean}
|
|
72
|
-
*/
|
|
73
|
-
hasIndex (index) {
|
|
74
|
-
return this.indexes.has(index);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Check a collection existence
|
|
79
|
-
* @param {string} index
|
|
80
|
-
* @param {string} collection
|
|
81
|
-
* @returns {boolean}
|
|
82
|
-
*/
|
|
83
|
-
hasCollection (index, collection) {
|
|
84
|
-
const collections = this.indexes.get(index);
|
|
85
|
-
|
|
86
|
-
if (!collections) {
|
|
87
|
-
return false;
|
|
90
|
+
/**
|
|
91
|
+
* Remove an index from the cache
|
|
92
|
+
*/
|
|
93
|
+
removeIndex(index) {
|
|
94
|
+
this.indexes.delete(index);
|
|
88
95
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
listIndexes () {
|
|
98
|
-
return Array.from(this.indexes.keys());
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Return the list of an index' collections
|
|
103
|
-
* @param {string} index
|
|
104
|
-
* @returns {string[]}
|
|
105
|
-
* @throws If the provided index does not exist
|
|
106
|
-
*/
|
|
107
|
-
listCollections (index) {
|
|
108
|
-
this.assertIndexExists(index);
|
|
109
|
-
|
|
110
|
-
return Array.from(this.indexes.get(index));
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Remove an index from the cache
|
|
115
|
-
* @param {string} index
|
|
116
|
-
*/
|
|
117
|
-
removeIndex (index) {
|
|
118
|
-
this.indexes.delete(index);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Remove a collection from the cache
|
|
123
|
-
* @param {string} index
|
|
124
|
-
* @param {string} collection
|
|
125
|
-
*/
|
|
126
|
-
removeCollection (index, collection) {
|
|
127
|
-
const collections = this.indexes.get(index);
|
|
128
|
-
|
|
129
|
-
if (collections) {
|
|
130
|
-
collections.delete(collection);
|
|
96
|
+
/**
|
|
97
|
+
* Remove a collection from the cache
|
|
98
|
+
*/
|
|
99
|
+
removeCollection(index, collection) {
|
|
100
|
+
const collections = this.indexes.get(index);
|
|
101
|
+
if (collections) {
|
|
102
|
+
collections.delete(collection);
|
|
103
|
+
}
|
|
131
104
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
throw kerror.get('unknown_index', index);
|
|
105
|
+
/**
|
|
106
|
+
* Assert that the provided index exists
|
|
107
|
+
*
|
|
108
|
+
* @throws If the index does not exist
|
|
109
|
+
*/
|
|
110
|
+
assertIndexExists(index) {
|
|
111
|
+
if (!this.indexes.has(index)) {
|
|
112
|
+
throw storageError.get('unknown_index', index);
|
|
113
|
+
}
|
|
142
114
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
this.assertIndexExists(index);
|
|
152
|
-
|
|
153
|
-
if (!this.indexes.get(index).has(collection)) {
|
|
154
|
-
throw kerror.get('unknown_collection', index, collection);
|
|
115
|
+
/**
|
|
116
|
+
* Assert that the provided index and collection exist
|
|
117
|
+
*/
|
|
118
|
+
assertCollectionExists(index, collection) {
|
|
119
|
+
this.assertIndexExists(index);
|
|
120
|
+
if (!this.indexes.get(index).has(collection)) {
|
|
121
|
+
throw storageError.get('unknown_collection', index, collection);
|
|
122
|
+
}
|
|
155
123
|
}
|
|
156
|
-
}
|
|
157
124
|
}
|
|
158
|
-
|
|
159
|
-
|
|
125
|
+
exports.IndexCache = IndexCache;
|
|
126
|
+
//# sourceMappingURL=indexCache.js.map
|
package/lib/kuzzle/kuzzle.js
CHANGED
|
@@ -28,7 +28,7 @@ const murmurhash_native_1 = require("murmurhash-native");
|
|
|
28
28
|
const json_stable_stringify_1 = __importDefault(require("json-stable-stringify"));
|
|
29
29
|
const koncorde_1 = require("koncorde");
|
|
30
30
|
const bluebird_1 = __importDefault(require("bluebird"));
|
|
31
|
-
const
|
|
31
|
+
const node_segfault_handler_1 = __importDefault(require("node-segfault-handler"));
|
|
32
32
|
const lodash_1 = __importDefault(require("lodash"));
|
|
33
33
|
const kuzzleStateEnum_1 = __importDefault(require("./kuzzleStateEnum"));
|
|
34
34
|
const kuzzleEventEmitter_1 = __importDefault(require("./event/kuzzleEventEmitter"));
|
|
@@ -444,7 +444,7 @@ class Kuzzle extends kuzzleEventEmitter_1.default {
|
|
|
444
444
|
this.shutdown();
|
|
445
445
|
});
|
|
446
446
|
}
|
|
447
|
-
|
|
447
|
+
node_segfault_handler_1.default.registerHandler();
|
|
448
448
|
}
|
|
449
449
|
async dumpAndExit(suffix) {
|
|
450
450
|
if (this.config.dump.enabled) {
|
|
@@ -128,12 +128,11 @@ class ElasticSearch extends Service {
|
|
|
128
128
|
'_source_includes'
|
|
129
129
|
];
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
];
|
|
136
|
-
|
|
131
|
+
/**
|
|
132
|
+
* Only allow stored-scripts in queries
|
|
133
|
+
*/
|
|
134
|
+
this.scriptKeys = ['script', '_script'];
|
|
135
|
+
this.scriptAllowedArgs = ['id', 'params'];
|
|
137
136
|
|
|
138
137
|
this.maxScrollDuration = this._loadMsConfig('maxScrollDuration');
|
|
139
138
|
|
|
@@ -2979,14 +2978,20 @@ class ElasticSearch extends Service {
|
|
|
2979
2978
|
}
|
|
2980
2979
|
|
|
2981
2980
|
/**
|
|
2982
|
-
* Throw if
|
|
2981
|
+
* Throw if a script is used in the query.
|
|
2982
|
+
*
|
|
2983
|
+
* Only Stored Scripts are accepted
|
|
2983
2984
|
*
|
|
2984
2985
|
* @param {Object} object
|
|
2985
2986
|
*/
|
|
2986
|
-
_scriptCheck(object) {
|
|
2987
|
+
_scriptCheck (object) {
|
|
2987
2988
|
for (const [key, value] of Object.entries(object)) {
|
|
2988
2989
|
if (this.scriptKeys.includes(key)) {
|
|
2989
|
-
|
|
2990
|
+
for (const scriptArg of Object.keys(value)) {
|
|
2991
|
+
if (! this.scriptAllowedArgs.includes(scriptArg)) {
|
|
2992
|
+
throw kerror.get('invalid_query_keyword', `${key}.${scriptArg}`);
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2990
2995
|
}
|
|
2991
2996
|
// Every object must be checked here, even the ones nested into an array
|
|
2992
2997
|
else if (typeof value === 'object' && value !== null) {
|