kuzzle 2.60.0-beta.1 → 2.60.0-beta.3
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/dist/bin/copy-binaries.js +17 -7
- package/dist/bin/start-kuzzle-server +19 -8
- package/dist/index.d.ts +2 -1
- package/dist/index.js +6 -2
- package/dist/lib/api/controllers/adminController.d.ts +9 -3
- package/dist/lib/api/controllers/adminController.js +42 -26
- package/dist/lib/api/controllers/authController.d.ts +15 -5
- package/dist/lib/api/controllers/authController.js +35 -20
- package/dist/lib/api/controllers/baseController.js +17 -7
- package/dist/lib/api/controllers/bulkController.js +17 -7
- package/dist/lib/api/controllers/collectionController.js +17 -7
- package/dist/lib/api/controllers/debugController.js +17 -7
- package/dist/lib/api/controllers/documentController.js +17 -7
- package/dist/lib/api/controllers/indexController.d.ts +1 -1
- package/dist/lib/api/controllers/memoryStorageController.js +17 -7
- package/dist/lib/api/controllers/securityController.d.ts +30 -28
- package/dist/lib/api/controllers/securityController.js +18 -8
- package/dist/lib/api/controllers/serverController.d.ts +0 -1
- package/dist/lib/api/controllers/serverController.js +17 -7
- package/dist/lib/api/documentExtractor.js +17 -7
- package/dist/lib/api/funnel.js +19 -9
- package/dist/lib/api/httpRoutes.d.ts +2 -1
- package/dist/lib/api/openapi/OpenApiManager.d.ts +2 -1
- package/dist/lib/api/openapi/openApiGenerator.js +1 -2
- package/dist/lib/api/request/kuzzleRequest.d.ts +9 -2
- package/dist/lib/api/request/kuzzleRequest.js +21 -7
- package/dist/lib/api/request/requestContext.d.ts +7 -2
- package/dist/lib/api/request/requestContext.js +17 -7
- package/dist/lib/api/request/requestInput.d.ts +1 -1
- package/dist/lib/api/request/requestInput.js +17 -7
- package/dist/lib/api/request/requestResponse.d.ts +2 -2
- package/dist/lib/api/request/requestResponse.js +21 -10
- package/dist/lib/cluster/command.d.ts +0 -2
- package/dist/lib/cluster/command.js +17 -7
- package/dist/lib/cluster/idCardHandler.d.ts +7 -2
- package/dist/lib/cluster/idCardHandler.js +24 -3
- package/dist/lib/cluster/node.d.ts +15 -3
- package/dist/lib/cluster/node.js +112 -40
- package/dist/lib/cluster/protobuf/command.proto +23 -22
- package/dist/lib/cluster/protobuf/sync.proto +91 -85
- package/dist/lib/cluster/publisher.js +17 -7
- package/dist/lib/cluster/state.js +17 -7
- package/dist/lib/cluster/subscriber.d.ts +0 -2
- package/dist/lib/cluster/subscriber.js +17 -7
- package/dist/lib/cluster/workers/IDCardRenewer.d.ts +6 -1
- package/dist/lib/cluster/workers/IDCardRenewer.js +14 -8
- package/dist/lib/config/index.js +20 -14
- package/dist/lib/core/auth/formatProcessing.d.ts +1 -1
- package/dist/lib/core/auth/formatProcessing.js +3 -3
- package/dist/lib/core/auth/passportResponse.d.ts +0 -1
- package/dist/lib/core/auth/passportWrapper.js +24 -8
- package/dist/lib/core/backend/backend.js +17 -7
- package/dist/lib/core/backend/backendConfig.d.ts +1 -1
- package/dist/lib/core/backend/backendConfig.js +17 -7
- package/dist/lib/core/backend/backendController.js +17 -7
- package/dist/lib/core/backend/backendErrors.js +17 -7
- package/dist/lib/core/backend/backendHook.js +17 -7
- package/dist/lib/core/backend/backendImport.js +17 -7
- package/dist/lib/core/backend/backendPipe.d.ts +4 -1
- package/dist/lib/core/backend/backendPipe.js +17 -7
- package/dist/lib/core/backend/backendPlugin.js +17 -7
- package/dist/lib/core/backend/backendStorage.js +8 -8
- package/dist/lib/core/backend/backendSubscription.js +17 -7
- package/dist/lib/core/backend/backendVault.js +17 -7
- package/dist/lib/core/backend/internalLogger.d.ts +7 -7
- package/dist/lib/core/debug/kuzzleDebugger.js +17 -7
- package/dist/lib/core/network/accessLogger.d.ts +0 -1
- package/dist/lib/core/network/accessLogger.js +17 -7
- package/dist/lib/core/network/clientConnection.js +17 -7
- package/dist/lib/core/network/context.d.ts +0 -1
- package/dist/lib/core/network/entryPoint.js +17 -7
- package/dist/lib/core/network/httpRouter/routePart.js +17 -7
- package/dist/lib/core/network/protocols/httpMessage.d.ts +0 -2
- package/dist/lib/core/network/protocols/httpwsProtocol.d.ts +0 -3
- package/dist/lib/core/network/protocols/httpwsProtocol.js +17 -7
- package/dist/lib/core/network/protocols/mqttProtocol.d.ts +1 -2
- package/dist/lib/core/network/protocols/mqttProtocol.js +31 -10
- package/dist/lib/core/network/router.js +17 -7
- package/dist/lib/core/plugin/plugin.js +17 -7
- package/dist/lib/core/plugin/pluginContext.d.ts +20 -9
- package/dist/lib/core/plugin/pluginContext.js +39 -24
- package/dist/lib/core/plugin/pluginsManager.js +17 -7
- package/dist/lib/core/realtime/channel.js +17 -7
- package/dist/lib/core/realtime/hotelClerk.d.ts +3 -2
- package/dist/lib/core/realtime/hotelClerk.js +17 -7
- package/dist/lib/core/realtime/notifier.js +17 -7
- package/dist/lib/core/security/profileRepository.js +17 -7
- package/dist/lib/core/security/roleRepository.js +17 -7
- package/dist/lib/core/security/securityLoader.js +17 -7
- package/dist/lib/core/security/tokenRepository.js +18 -8
- package/dist/lib/core/security/userRepository.js +17 -7
- package/dist/lib/core/shared/ObjectRepository.js +20 -7
- package/dist/lib/core/shared/abstractManifest.js +17 -7
- package/dist/lib/core/shared/sdk/embeddedSdk.js +20 -8
- package/dist/lib/core/shared/sdk/funnelProtocol.js +17 -7
- package/dist/lib/core/shared/store.d.ts +11 -1
- package/dist/lib/core/shared/store.js +26 -30
- package/dist/lib/core/statistics/statistics.d.ts +0 -1
- package/dist/lib/core/statistics/statistics.js +17 -7
- package/dist/lib/core/storage/clientAdapter.d.ts +4 -6
- package/dist/lib/core/storage/clientAdapter.js +24 -18
- package/dist/lib/core/storage/indexCache.js +17 -7
- package/dist/lib/core/validation/specification.js +1 -2
- package/dist/lib/core/validation/types/date.js +17 -7
- package/dist/lib/core/validation/types/enum.js +17 -7
- package/dist/lib/core/validation/types/geoShape.js +17 -7
- package/dist/lib/core/validation/types/geoShapeUtils.js +6 -7
- package/dist/lib/core/validation/validation.js +17 -7
- package/dist/lib/core/validation/validationUtils.js +24 -15
- package/dist/lib/kerror/codes/8-cluster.json +23 -0
- package/dist/lib/kerror/codes/index.js +20 -10
- package/dist/lib/kerror/errors/kuzzleError.js +18 -8
- package/dist/lib/kerror/index.js +31 -18
- package/dist/lib/kuzzle/Logger.js +4 -3
- package/dist/lib/kuzzle/dumpGenerator.js +17 -7
- package/dist/lib/kuzzle/event/KuzzleEventEmitter.d.ts +3 -3
- package/dist/lib/kuzzle/event/KuzzleEventEmitter.js +17 -7
- package/dist/lib/kuzzle/event/pipeRunner.js +17 -7
- package/dist/lib/kuzzle/exitOnFailure.d.ts +13 -0
- package/dist/lib/kuzzle/exitOnFailure.js +60 -0
- package/dist/lib/kuzzle/internalIndexHandler.js +37 -32
- package/dist/lib/kuzzle/kuzzle.d.ts +20 -8
- package/dist/lib/kuzzle/kuzzle.js +148 -130
- package/dist/lib/model/security/profile.js +17 -7
- package/dist/lib/model/security/role.js +17 -7
- package/dist/lib/model/security/user.js +17 -7
- package/dist/lib/model/storage/apiKey.d.ts +1 -1
- package/dist/lib/model/storage/apiKey.js +17 -7
- package/dist/lib/service/cache/redis.js +40 -9
- package/dist/lib/service/service.js +17 -7
- package/dist/lib/service/storage/7/elasticsearch.d.ts +36 -25
- package/dist/lib/service/storage/7/elasticsearch.js +73 -55
- package/dist/lib/service/storage/8/elasticsearch.d.ts +47 -36
- package/dist/lib/service/storage/8/elasticsearch.js +73 -55
- package/dist/lib/service/storage/Elasticsearch.d.ts +10 -4
- package/dist/lib/types/HttpStream.d.ts +0 -1
- package/dist/lib/types/Plugin.js +17 -7
- package/dist/lib/types/config/SecurityConfiguration.d.ts +0 -2
- package/dist/lib/types/config/storageEngine/StorageEngineElasticsearchConfiguration.d.ts +5 -0
- package/dist/lib/types/controllers/GetCurrentUserResponse.d.ts +5 -0
- package/dist/lib/types/controllers/GetCurrentUserResponse.js +3 -0
- package/dist/lib/types/controllers/ResetSecurityResult.d.ts +5 -0
- package/dist/lib/types/controllers/ResetSecurityResult.js +3 -0
- package/dist/lib/types/controllers/adminController.type.d.ts +7 -5
- package/dist/lib/types/controllers/authController.type.d.ts +7 -5
- package/dist/lib/types/core/auth/Serialized.d.ts +14 -0
- package/dist/lib/types/core/auth/Serialized.js +3 -0
- package/dist/lib/types/core/auth/formatProcessing.type.d.ts +5 -11
- package/dist/lib/types/events/EventProtocol.d.ts +0 -2
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/index.js +1 -0
- package/dist/lib/types/storage/8/Elasticsearch.d.ts +4 -3
- package/dist/lib/util/array.d.ts +1 -1
- package/dist/lib/util/array.js +7 -6
- package/dist/lib/util/assertType.js +5 -6
- package/dist/lib/util/async.js +1 -2
- package/dist/lib/util/asyncStore.d.ts +0 -1
- package/dist/lib/util/bufferedPassThrough.d.ts +0 -3
- package/dist/lib/util/crypto.js +1 -2
- package/dist/lib/util/debug.d.ts +0 -1
- package/dist/lib/util/debug.js +17 -7
- package/dist/lib/util/distributedLock.d.ts +27 -4
- package/dist/lib/util/distributedLock.js +69 -16
- package/dist/lib/util/dump-collection.d.ts +2 -2
- package/dist/lib/util/dump-collection.js +22 -13
- package/dist/lib/util/esRequest.js +1 -2
- package/dist/lib/util/extractFields.d.ts +16 -7
- package/dist/lib/util/extractFields.js +1 -10
- package/dist/lib/util/koncordeCompat.js +22 -13
- package/dist/lib/util/mutex.d.ts +4 -4
- package/dist/lib/util/mutex.js +21 -11
- package/dist/lib/util/name-generator.js +2 -2
- package/dist/lib/util/requestAssertions.js +27 -18
- package/dist/lib/util/safeObject.js +3 -4
- package/dist/lib/util/stackTrace.js +2 -3
- package/dist/lib/util/thrown.js +1 -2
- package/dist/lib/util/time.js +1 -2
- package/dist/package.json +22 -15
- package/package.json +22 -15
|
@@ -17,6 +17,12 @@ import { Logger } from "./Logger";
|
|
|
17
17
|
declare class Kuzzle extends KuzzleEventEmitter {
|
|
18
18
|
config: IKuzzleConfiguration;
|
|
19
19
|
private _state;
|
|
20
|
+
/** The running shutdown, which later `shutdown()` calls wait for (#3017) */
|
|
21
|
+
private shutdownPromise;
|
|
22
|
+
/** The highest exit code asked for by the `shutdown()` calls so far */
|
|
23
|
+
private shutdownExitCode;
|
|
24
|
+
/** Ends a failure's shutdown that does not finish in time */
|
|
25
|
+
private shutdownWatchdog;
|
|
20
26
|
log: Logger;
|
|
21
27
|
/** Read by `PluginsManager` to locate the plugins directories. */
|
|
22
28
|
rootPath: string;
|
|
@@ -95,8 +101,12 @@ declare class Kuzzle extends KuzzleEventEmitter {
|
|
|
95
101
|
* @param {Object} - Additional options (import, installations, plugins, secretsFile, support, vaultKey)
|
|
96
102
|
*
|
|
97
103
|
* @this {Kuzzle}
|
|
104
|
+
*
|
|
105
|
+
* The public signature takes `unknown`, which every call that compiled with
|
|
106
|
+
* v2.56.0's `any` still satisfies. `Backend.start()` is the one caller, and
|
|
107
|
+
* it hands the application wrapper the implementation reads.
|
|
98
108
|
*/
|
|
99
|
-
start(application:
|
|
109
|
+
start(application: unknown, options?: StartOptions): Promise<void>;
|
|
100
110
|
/**
|
|
101
111
|
* Generates the node ID.
|
|
102
112
|
*
|
|
@@ -113,6 +123,7 @@ declare class Kuzzle extends KuzzleEventEmitter {
|
|
|
113
123
|
* @returns {Promise}
|
|
114
124
|
*/
|
|
115
125
|
shutdown(exitCode?: number): Promise<void>;
|
|
126
|
+
private runShutdown;
|
|
116
127
|
/**
|
|
117
128
|
* Execute multiple handlers only once on any given environment
|
|
118
129
|
*
|
|
@@ -121,18 +132,19 @@ declare class Kuzzle extends KuzzleEventEmitter {
|
|
|
121
132
|
* @returns {Promise<void>}
|
|
122
133
|
*/
|
|
123
134
|
install(installations?: InstallationConfig[]): Promise<void>;
|
|
124
|
-
ask(event: string, ...args: [payload?:
|
|
125
|
-
emit(event: string, ...args:
|
|
126
|
-
pipe(event: string, ...args:
|
|
135
|
+
ask(event: string, ...args: [payload?: unknown, ...rest: unknown[]]): Promise<any>;
|
|
136
|
+
emit(event: string, ...args: unknown[]): boolean;
|
|
137
|
+
pipe(event: string, ...args: unknown[]): Promise<any>;
|
|
127
138
|
private importUserMappings;
|
|
128
139
|
private importMappings;
|
|
129
140
|
private importFixtures;
|
|
130
141
|
private importPermissions;
|
|
142
|
+
private isConfigsEmpty;
|
|
131
143
|
/**
|
|
132
|
-
*
|
|
144
|
+
* Records the hash of the payload just imported (or found already imported)
|
|
145
|
+
* in both Redis and `%kuzzle.imports`, so that the next node or the next
|
|
146
|
+
* start can tell the import is done for this very payload
|
|
133
147
|
*/
|
|
134
|
-
private _waitForImportToFinish;
|
|
135
|
-
private isConfigsEmpty;
|
|
136
148
|
private persistHashedImport;
|
|
137
149
|
/**
|
|
138
150
|
* Load into the app several imports
|
|
@@ -144,7 +156,7 @@ declare class Kuzzle extends KuzzleEventEmitter {
|
|
|
144
156
|
*/
|
|
145
157
|
loadInitialState(toImport?: ImportConfig, toSupport?: SupportConfig): Promise<void>;
|
|
146
158
|
dump(suffix: string): Promise<string>;
|
|
147
|
-
hash(input:
|
|
159
|
+
hash(input: unknown): number;
|
|
148
160
|
get state(): kuzzleStateEnum;
|
|
149
161
|
set state(value: kuzzleStateEnum);
|
|
150
162
|
/**
|
|
@@ -35,13 +35,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
35
35
|
}) : function(o, v) {
|
|
36
36
|
o["default"] = v;
|
|
37
37
|
});
|
|
38
|
-
var __importStar = (this && this.__importStar) || function (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
38
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
39
|
+
var ownKeys = function(o) {
|
|
40
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
41
|
+
var ar = [];
|
|
42
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
43
|
+
return ar;
|
|
44
|
+
};
|
|
45
|
+
return ownKeys(o);
|
|
46
|
+
};
|
|
47
|
+
return function (mod) {
|
|
48
|
+
if (mod && mod.__esModule) return mod;
|
|
49
|
+
var result = {};
|
|
50
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
51
|
+
__setModuleDefault(result, mod);
|
|
52
|
+
return result;
|
|
53
|
+
};
|
|
54
|
+
})();
|
|
45
55
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
56
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
57
|
};
|
|
@@ -73,6 +83,7 @@ const validation_1 = __importDefault(require("../core/validation/validation"));
|
|
|
73
83
|
const kerror = __importStar(require("../kerror"));
|
|
74
84
|
const asyncStore_1 = __importDefault(require("../util/asyncStore"));
|
|
75
85
|
const crypto_1 = require("../util/crypto");
|
|
86
|
+
const distributedLock_1 = require("../util/distributedLock");
|
|
76
87
|
const mutex_1 = require("../util/mutex");
|
|
77
88
|
const dumpGenerator_1 = __importDefault(require("./dumpGenerator"));
|
|
78
89
|
const KuzzleEventEmitter_1 = __importDefault(require("./event/KuzzleEventEmitter"));
|
|
@@ -82,6 +93,12 @@ const Logger_1 = require("./Logger");
|
|
|
82
93
|
const vault_1 = __importDefault(require("./vault"));
|
|
83
94
|
const name_generator_1 = require("../util/name-generator");
|
|
84
95
|
let _kuzzle = null;
|
|
96
|
+
/**
|
|
97
|
+
* How long a shutdown caused by a failure may run before the process exits
|
|
98
|
+
* anyway: a `kuzzle:shutdown` pipe or a lock release that never settles must
|
|
99
|
+
* not keep a failed node alive, which a bare `process.exit(1)` never did
|
|
100
|
+
*/
|
|
101
|
+
const FAILURE_SHUTDOWN_TIMEOUT = 30000;
|
|
85
102
|
Reflect.defineProperty(global, "kuzzle", {
|
|
86
103
|
configurable: true,
|
|
87
104
|
enumerable: false,
|
|
@@ -102,6 +119,12 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
102
119
|
constructor(config) {
|
|
103
120
|
super(config.plugins.common.maxConcurrentPipes, config.plugins.common.pipesBufferSize);
|
|
104
121
|
this._state = kuzzleStateEnum_1.default.STARTING;
|
|
122
|
+
/** The running shutdown, which later `shutdown()` calls wait for (#3017) */
|
|
123
|
+
this.shutdownPromise = null;
|
|
124
|
+
/** The highest exit code asked for by the `shutdown()` calls so far */
|
|
125
|
+
this.shutdownExitCode = 0;
|
|
126
|
+
/** Ends a failure's shutdown that does not finish in time */
|
|
127
|
+
this.shutdownWatchdog = null;
|
|
105
128
|
global.kuzzle = this;
|
|
106
129
|
this._state = kuzzleStateEnum_1.default.STARTING;
|
|
107
130
|
this.config = config;
|
|
@@ -138,15 +161,7 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
138
161
|
userMappings: this.importUserMappings.bind(this),
|
|
139
162
|
};
|
|
140
163
|
}
|
|
141
|
-
|
|
142
|
-
* Initializes all the needed components of Kuzzle.
|
|
143
|
-
*
|
|
144
|
-
* @param {Application} - Application Plugin instance
|
|
145
|
-
* @param {Object} - Additional options (import, installations, plugins, secretsFile, support, vaultKey)
|
|
146
|
-
*
|
|
147
|
-
* @this {Kuzzle}
|
|
148
|
-
*/
|
|
149
|
-
async start(application, options = { import: {} }) {
|
|
164
|
+
async start(application, options) {
|
|
150
165
|
this.registerSignalHandlers();
|
|
151
166
|
try {
|
|
152
167
|
this.log.info(`[ℹ] Starting Kuzzle ${this.version} ...`);
|
|
@@ -164,7 +179,7 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
164
179
|
await new security_1.default().init();
|
|
165
180
|
// This will init the cluster module if enabled
|
|
166
181
|
await this.initKuzzleNode();
|
|
167
|
-
this.vault = vault_1.default.load(options
|
|
182
|
+
this.vault = vault_1.default.load(options?.vaultKey, options?.secretsFile, this.config.vault?.newAlgorithm);
|
|
168
183
|
this.validation.init();
|
|
169
184
|
await this.tokenManager.init();
|
|
170
185
|
await this.funnel.init();
|
|
@@ -175,15 +190,15 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
175
190
|
await this.entryPoint.init();
|
|
176
191
|
await this.debugger.init();
|
|
177
192
|
this.pluginsManager.application = application;
|
|
178
|
-
const pluginImports = await this.pluginsManager.init(options
|
|
179
|
-
const imports = lodash_1.default.merge({}, pluginImports, options
|
|
193
|
+
const pluginImports = await this.pluginsManager.init(options?.plugins);
|
|
194
|
+
const imports = lodash_1.default.merge({}, pluginImports, options?.import);
|
|
180
195
|
// Authentification plugins must be loaded before users import to avoid
|
|
181
196
|
// credentials related error which would prevent Kuzzle from starting
|
|
182
|
-
await this.loadInitialState(imports, options
|
|
197
|
+
await this.loadInitialState(imports, options?.support);
|
|
183
198
|
await this.ask("core:security:verify");
|
|
184
199
|
this.router.init();
|
|
185
200
|
this.log.info("[✔] Core components loaded");
|
|
186
|
-
await this.install(options
|
|
201
|
+
await this.install(options?.installations);
|
|
187
202
|
// `application` is the very wrapper handed to the plugins manager six
|
|
188
203
|
// lines up, so reading the name back off the manager was a round trip
|
|
189
204
|
// through a getter that can answer `undefined`.
|
|
@@ -201,6 +216,16 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
201
216
|
}
|
|
202
217
|
catch (error) {
|
|
203
218
|
this.log.error(`[X] Cannot start Kuzzle ${this.version}: ${error instanceof Error ? error.message : (0, node_util_1.inspect)(error)}`);
|
|
219
|
+
// A failed start cannot be retried (a second Kuzzle instance cannot be
|
|
220
|
+
// built), and what it did start keeps the process alive: in production,
|
|
221
|
+
// a node with no listener and an ID card still renewed (#3020). Not
|
|
222
|
+
// awaited, so the caller still gets the error before the process exits.
|
|
223
|
+
this.shutdown(1).catch((shutdownError) => {
|
|
224
|
+
this.log.error(`Unable to shut down after a failed start: ${shutdownError instanceof Error
|
|
225
|
+
? shutdownError.message
|
|
226
|
+
: (0, node_util_1.inspect)(shutdownError)}`);
|
|
227
|
+
process.exit(1);
|
|
228
|
+
});
|
|
204
229
|
throw error;
|
|
205
230
|
}
|
|
206
231
|
}
|
|
@@ -228,6 +253,22 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
228
253
|
* @returns {Promise}
|
|
229
254
|
*/
|
|
230
255
|
async shutdown(exitCode = 0) {
|
|
256
|
+
// Several sources can ask for it at once (a signal, a cluster eviction,
|
|
257
|
+
// the `exit` handler that `process.exit` below fires): they share the one
|
|
258
|
+
// shutdown, and a failure reported by any of them keeps the exit non-zero
|
|
259
|
+
this.shutdownExitCode = Math.max(this.shutdownExitCode, exitCode);
|
|
260
|
+
// Not for a requested shutdown: it waits for the requests still running,
|
|
261
|
+
// however long they take
|
|
262
|
+
if (exitCode !== 0) {
|
|
263
|
+
this.shutdownWatchdog ?? (this.shutdownWatchdog = setTimeout(() => {
|
|
264
|
+
this.log.error(`[shutdown] Not finished after ${FAILURE_SHUTDOWN_TIMEOUT}ms: exiting now`);
|
|
265
|
+
process.exit(this.shutdownExitCode);
|
|
266
|
+
}, FAILURE_SHUTDOWN_TIMEOUT));
|
|
267
|
+
}
|
|
268
|
+
this.shutdownPromise ?? (this.shutdownPromise = this.runShutdown());
|
|
269
|
+
return this.shutdownPromise;
|
|
270
|
+
}
|
|
271
|
+
async runShutdown() {
|
|
231
272
|
this._state = kuzzleStateEnum_1.default.SHUTTING_DOWN;
|
|
232
273
|
this.log.info("Initiating shutdown...");
|
|
233
274
|
// Ask the network layer to stop accepting new request
|
|
@@ -241,7 +282,10 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
241
282
|
}
|
|
242
283
|
// The other nodes may be waiting on a lock this one holds: a node leaving
|
|
243
284
|
// mid-startup is often in the middle of one (F-13).
|
|
244
|
-
await
|
|
285
|
+
await Promise.all([
|
|
286
|
+
(0, distributedLock_1.releaseAllLocksBeforeExit)(),
|
|
287
|
+
mutex_1.Mutex.releaseAllBeforeExit(), // NOSONAR: frees locks taken through the deprecated API
|
|
288
|
+
]);
|
|
245
289
|
this.log.info("Halted.");
|
|
246
290
|
// flush both application and Kuzzle core loggers before leaving (Could happen even if some core/application components are not initialized)
|
|
247
291
|
await this?.log?.flush?.();
|
|
@@ -251,7 +295,10 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
251
295
|
// `pluginsManager?.application?.log?.flush?.()` was a silent no-op and the
|
|
252
296
|
// application's buffered logs were dropped on shutdown (TD-51).
|
|
253
297
|
await this?.pluginsManager?.application?.instance?.log?.flush?.();
|
|
254
|
-
|
|
298
|
+
if (this.shutdownWatchdog !== null) {
|
|
299
|
+
clearTimeout(this.shutdownWatchdog);
|
|
300
|
+
}
|
|
301
|
+
process.exit(this.shutdownExitCode);
|
|
255
302
|
}
|
|
256
303
|
/**
|
|
257
304
|
* Execute multiple handlers only once on any given environment
|
|
@@ -266,9 +313,9 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
266
313
|
if (!installations?.length) {
|
|
267
314
|
return;
|
|
268
315
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
316
|
+
// No retry limit: another node is running the installations, and this
|
|
317
|
+
// one must not start before they are recorded
|
|
318
|
+
await (0, distributedLock_1.withLock)("backend:installations", async () => {
|
|
272
319
|
for (const installation of installations) {
|
|
273
320
|
const isAlreadyInstalled = await this.ask("core:storage:private:document:exist", "kuzzle", "installations", installation.id);
|
|
274
321
|
if (!isAlreadyInstalled) {
|
|
@@ -286,10 +333,7 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
286
333
|
this.log.info(`[✔] Install code "${installation.id}" successfully executed`);
|
|
287
334
|
}
|
|
288
335
|
}
|
|
289
|
-
}
|
|
290
|
-
finally {
|
|
291
|
-
await mutex.unlock();
|
|
292
|
-
}
|
|
336
|
+
}, { retryAttempts: Number.POSITIVE_INFINITY });
|
|
293
337
|
}
|
|
294
338
|
// For testing purpose
|
|
295
339
|
async ask(event, ...args) {
|
|
@@ -322,11 +366,8 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
322
366
|
}
|
|
323
367
|
else if (!lodash_1.default.isEmpty(toSupport.mappings)) {
|
|
324
368
|
await this.ask("core:storage:public:mappings:import", toSupport.mappings, {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
* we just want to load the mapping in our own index cache and not in the database.
|
|
328
|
-
*/
|
|
329
|
-
indexCacheOnly: status.initialized || !status.locked,
|
|
369
|
+
// Already imported (by this node or another one): only fill the cache
|
|
370
|
+
indexCacheOnly: status.initialized,
|
|
330
371
|
propagate: false, // Each node needs to do the import themselves
|
|
331
372
|
rawMappings: true,
|
|
332
373
|
refresh: true,
|
|
@@ -335,11 +376,8 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
335
376
|
}
|
|
336
377
|
else if (!lodash_1.default.isEmpty(toImport.mappings)) {
|
|
337
378
|
await this.ask("core:storage:public:mappings:import", toImport.mappings, {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
* we just want to load the mapping in our own index cache and not in the database.
|
|
341
|
-
*/
|
|
342
|
-
indexCacheOnly: status.initialized || !status.locked,
|
|
379
|
+
// Already imported (by this node or another one): only fill the cache
|
|
380
|
+
indexCacheOnly: status.initialized,
|
|
343
381
|
propagate: false, // Each node needs to do the import themselves
|
|
344
382
|
refresh: true,
|
|
345
383
|
});
|
|
@@ -392,19 +430,6 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
392
430
|
this.log.info("[✔] Permissions import successful");
|
|
393
431
|
}
|
|
394
432
|
}
|
|
395
|
-
/**
|
|
396
|
-
* Check if every import has been done, if one of them is not finished yet, wait for it
|
|
397
|
-
*/
|
|
398
|
-
async _waitForImportToFinish() {
|
|
399
|
-
const importTypes = Object.keys(this.importTypes);
|
|
400
|
-
for (const importType of importTypes) {
|
|
401
|
-
// If the import is done, we pop it from the queue to check the next one
|
|
402
|
-
if (await this.ask("core:cache:internal:get", `backend:init:import:${importType}`)) {
|
|
403
|
-
return;
|
|
404
|
-
}
|
|
405
|
-
await bluebird_1.default.delay(1000);
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
433
|
isConfigsEmpty(importConfig, supportConfig) {
|
|
409
434
|
if (lodash_1.default.isEmpty(importConfig.mappings) &&
|
|
410
435
|
lodash_1.default.isEmpty(importConfig.profiles) &&
|
|
@@ -418,10 +443,16 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
418
443
|
}
|
|
419
444
|
return false;
|
|
420
445
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
446
|
+
/**
|
|
447
|
+
* Records the hash of the payload just imported (or found already imported)
|
|
448
|
+
* in both Redis and `%kuzzle.imports`, so that the next node or the next
|
|
449
|
+
* start can tell the import is done for this very payload
|
|
450
|
+
*/
|
|
451
|
+
async persistHashedImport({ existingRedisHash, existingESHash, importPayloadHash, initialized, type, }) {
|
|
452
|
+
// Not initialized: the payload was just imported, and a hash left by a
|
|
453
|
+
// previous payload must be replaced, or every start would import it again
|
|
454
|
+
if (!initialized || !existingESHash) {
|
|
455
|
+
this.log.info(`Recording the ${type} import in %kuzzle.imports...`);
|
|
425
456
|
// `createOrReplace`, not `create`: this document has a fixed id, so a
|
|
426
457
|
// conflict on it means another node initialized the same import — an
|
|
427
458
|
// outcome to converge on, not an error to die on. `create` made that
|
|
@@ -429,24 +460,9 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
429
460
|
await this.ask("core:storage:private:document:createOrReplace", "kuzzle", "imports", `backend:init:import:${type}`, {
|
|
430
461
|
hash: importPayloadHash,
|
|
431
462
|
});
|
|
432
|
-
await this.ask("core:cache:internal:store", `backend:init:import:${type}`, importPayloadHash);
|
|
433
|
-
}
|
|
434
|
-
else if (existingRedisHash && !existingESHash) {
|
|
435
|
-
// If the import is initialized in the redis cache but not in the ES
|
|
436
|
-
// We initialize it in the ES
|
|
437
|
-
this.log.info(`${type} import is not initialized in %kuzzle.imports, initializing...`);
|
|
438
|
-
const redisCache = await this.ask("core:cache:internal:get", `backend:init:import:${type}`);
|
|
439
|
-
// Same reasoning as above: a fixed id, so a conflict is convergence.
|
|
440
|
-
await this.ask("core:storage:private:document:createOrReplace", "kuzzle", "imports", `backend:init:import:${type}`, {
|
|
441
|
-
hash: redisCache,
|
|
442
|
-
});
|
|
443
463
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
// We initialize it in the redis cache
|
|
447
|
-
this.log.info(`${type} import is not initialized in the redis cache, initializing...`);
|
|
448
|
-
const esDocument = await this.ask("core:storage:private:document:get", "kuzzle", "imports", `backend:init:import:${type}`);
|
|
449
|
-
await this.ask("core:cache:internal:store", `backend:init:import:${type}`, esDocument._source.hash);
|
|
464
|
+
if (!initialized || !existingRedisHash) {
|
|
465
|
+
await this.ask("core:cache:internal:store", `backend:init:import:${type}`, importPayloadHash);
|
|
450
466
|
}
|
|
451
467
|
}
|
|
452
468
|
/**
|
|
@@ -461,42 +477,37 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
461
477
|
if (this.isConfigsEmpty(toImport, toSupport)) {
|
|
462
478
|
return;
|
|
463
479
|
}
|
|
464
|
-
const
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
// swapping one site would remove the exclusion it exists for. Deferred
|
|
496
|
-
// to #2894, like the remaining call sites.
|
|
497
|
-
const lockOptions = { timeout: 0, ttl: 60000 };
|
|
498
|
-
const mutex = new mutex_1.Mutex(`backend:import:${type}`, lockOptions); // NOSONAR
|
|
499
|
-
const locked = await mutex.lock();
|
|
480
|
+
const importTypes = Object.entries(this.importTypes);
|
|
481
|
+
// Imports the types from `index` on. Each type's lock is taken around the
|
|
482
|
+
// remaining types, so that every lock taken is held until all the imports
|
|
483
|
+
// are done: a node waiting for the first lock starts only once the node
|
|
484
|
+
// ahead of it has imported everything.
|
|
485
|
+
const importFrom = async (index) => {
|
|
486
|
+
const next = importTypes[index];
|
|
487
|
+
if (!next) {
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
const [type, importMethod] = next;
|
|
491
|
+
const importPayload = {};
|
|
492
|
+
switch (type) {
|
|
493
|
+
case "fixtures":
|
|
494
|
+
lodash_1.default.set(importPayload, "toSupport.fixtures", toSupport.fixtures);
|
|
495
|
+
break;
|
|
496
|
+
case "mappings":
|
|
497
|
+
lodash_1.default.set(importPayload, "toSupport.mappings", toSupport.mappings);
|
|
498
|
+
lodash_1.default.set(importPayload, "toImport.mappings", toImport.mappings);
|
|
499
|
+
break;
|
|
500
|
+
case "permissions":
|
|
501
|
+
lodash_1.default.set(importPayload, "toSupport.securities", toSupport.securities);
|
|
502
|
+
lodash_1.default.set(importPayload, "toImport.profiles", toImport.profiles);
|
|
503
|
+
lodash_1.default.set(importPayload, "toImport.roles", toImport.roles);
|
|
504
|
+
lodash_1.default.set(importPayload, "toImport.users", toImport.users);
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
// `?? ""`: `json-stable-stringify` answers undefined for a value it
|
|
508
|
+
// cannot serialise, and the payload is built right above.
|
|
509
|
+
const importPayloadHash = (0, crypto_1.sha256)((0, json_stable_stringify_1.default)(importPayload) ?? "");
|
|
510
|
+
const importType = async () => {
|
|
500
511
|
// Read the bookkeeping *after* the lock, never before: a read taken
|
|
501
512
|
// before acquiring it is not protected by it, and the holder that
|
|
502
513
|
// acted on a stale "not initialized" used to create a document the
|
|
@@ -515,26 +526,31 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
515
526
|
initialized = esDocument._source.hash === importPayloadHash;
|
|
516
527
|
}
|
|
517
528
|
await importMethod({ toImport, toSupport }, {
|
|
518
|
-
firstCall: !initialized
|
|
519
|
-
initialized
|
|
520
|
-
locked,
|
|
529
|
+
firstCall: !initialized,
|
|
530
|
+
initialized,
|
|
521
531
|
});
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
this
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
532
|
+
await this.persistHashedImport({
|
|
533
|
+
existingESHash,
|
|
534
|
+
existingRedisHash,
|
|
535
|
+
importPayloadHash,
|
|
536
|
+
initialized,
|
|
537
|
+
type,
|
|
538
|
+
});
|
|
539
|
+
await importFrom(index + 1);
|
|
540
|
+
};
|
|
541
|
+
// No retry limit: the node holding it is running this import, and this
|
|
542
|
+
// one must not start before it is done. Once it gets the lock, it finds
|
|
543
|
+
// the import done for this payload and only fills its cache; if the
|
|
544
|
+
// node ahead died mid-import, it runs the import itself. The lock is
|
|
545
|
+
// refreshed while held; a lost lock fails the startup with
|
|
546
|
+
// `MutexLockLostError` (the bookkeeping write stays idempotent, TD-69).
|
|
547
|
+
await (0, distributedLock_1.withLock)(`backend:import:${type}`, importType, {
|
|
548
|
+
retryAttempts: Number.POSITIVE_INFINITY,
|
|
549
|
+
ttl: 60000,
|
|
550
|
+
});
|
|
551
|
+
};
|
|
552
|
+
await importFrom(0);
|
|
553
|
+
this.log.info("[✔] Import successful");
|
|
538
554
|
}
|
|
539
555
|
dump(suffix) {
|
|
540
556
|
return this.dumpGenerator.dump(suffix);
|
|
@@ -633,7 +649,9 @@ class Kuzzle extends KuzzleEventEmitter_1.default {
|
|
|
633
649
|
// nothing to do with that error
|
|
634
650
|
}
|
|
635
651
|
}
|
|
636
|
-
|
|
652
|
+
// Only abnormal terminations get here: exit non-zero, so that an
|
|
653
|
+
// `on-failure` restart policy brings the node back (#3020)
|
|
654
|
+
await this.shutdown(1);
|
|
637
655
|
}
|
|
638
656
|
}
|
|
639
657
|
exports.Kuzzle = Kuzzle;
|
|
@@ -35,13 +35,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
35
35
|
}) : function(o, v) {
|
|
36
36
|
o["default"] = v;
|
|
37
37
|
});
|
|
38
|
-
var __importStar = (this && this.__importStar) || function (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
38
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
39
|
+
var ownKeys = function(o) {
|
|
40
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
41
|
+
var ar = [];
|
|
42
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
43
|
+
return ar;
|
|
44
|
+
};
|
|
45
|
+
return ownKeys(o);
|
|
46
|
+
};
|
|
47
|
+
return function (mod) {
|
|
48
|
+
if (mod && mod.__esModule) return mod;
|
|
49
|
+
var result = {};
|
|
50
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
51
|
+
__setModuleDefault(result, mod);
|
|
52
|
+
return result;
|
|
53
|
+
};
|
|
54
|
+
})();
|
|
45
55
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
56
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
57
|
};
|
|
@@ -35,13 +35,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
35
35
|
}) : function(o, v) {
|
|
36
36
|
o["default"] = v;
|
|
37
37
|
});
|
|
38
|
-
var __importStar = (this && this.__importStar) || function (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
38
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
39
|
+
var ownKeys = function(o) {
|
|
40
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
41
|
+
var ar = [];
|
|
42
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
43
|
+
return ar;
|
|
44
|
+
};
|
|
45
|
+
return ownKeys(o);
|
|
46
|
+
};
|
|
47
|
+
return function (mod) {
|
|
48
|
+
if (mod && mod.__esModule) return mod;
|
|
49
|
+
var result = {};
|
|
50
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
51
|
+
__setModuleDefault(result, mod);
|
|
52
|
+
return result;
|
|
53
|
+
};
|
|
54
|
+
})();
|
|
45
55
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
56
|
exports.Role = void 0;
|
|
47
57
|
const kerror = __importStar(require("../../kerror"));
|
|
@@ -35,13 +35,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
35
35
|
}) : function(o, v) {
|
|
36
36
|
o["default"] = v;
|
|
37
37
|
});
|
|
38
|
-
var __importStar = (this && this.__importStar) || function (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
38
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
39
|
+
var ownKeys = function(o) {
|
|
40
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
41
|
+
var ar = [];
|
|
42
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
43
|
+
return ar;
|
|
44
|
+
};
|
|
45
|
+
return ownKeys(o);
|
|
46
|
+
};
|
|
47
|
+
return function (mod) {
|
|
48
|
+
if (mod && mod.__esModule) return mod;
|
|
49
|
+
var result = {};
|
|
50
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
51
|
+
__setModuleDefault(result, mod);
|
|
52
|
+
return result;
|
|
53
|
+
};
|
|
54
|
+
})();
|
|
45
55
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
56
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
57
|
};
|
|
@@ -35,13 +35,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
35
35
|
}) : function(o, v) {
|
|
36
36
|
o["default"] = v;
|
|
37
37
|
});
|
|
38
|
-
var __importStar = (this && this.__importStar) || function (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
38
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
39
|
+
var ownKeys = function(o) {
|
|
40
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
41
|
+
var ar = [];
|
|
42
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
43
|
+
return ar;
|
|
44
|
+
};
|
|
45
|
+
return ownKeys(o);
|
|
46
|
+
};
|
|
47
|
+
return function (mod) {
|
|
48
|
+
if (mod && mod.__esModule) return mod;
|
|
49
|
+
var result = {};
|
|
50
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
51
|
+
__setModuleDefault(result, mod);
|
|
52
|
+
return result;
|
|
53
|
+
};
|
|
54
|
+
})();
|
|
45
55
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
56
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
57
|
};
|