@twin.org/engine-core 0.0.1-next.28 → 0.0.1-next.29
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/cjs/index.cjs +78 -51
- package/dist/esm/index.mjs +79 -52
- package/package.json +2 -2
package/dist/cjs/index.cjs
CHANGED
|
@@ -139,7 +139,7 @@ class EngineCore {
|
|
|
139
139
|
config: options.config,
|
|
140
140
|
defaultTypes: {},
|
|
141
141
|
componentInstances: [],
|
|
142
|
-
state: { bootstrappedComponents: [] },
|
|
142
|
+
state: { bootstrappedComponents: [], componentStates: {} },
|
|
143
143
|
stateDirty: false
|
|
144
144
|
};
|
|
145
145
|
this._stateStorage = options.stateStorage;
|
|
@@ -178,27 +178,44 @@ class EngineCore {
|
|
|
178
178
|
if (this._context.config.debug) {
|
|
179
179
|
this.logInfo(core.I18n.formatMessage("engineCore.debuggingEnabled"));
|
|
180
180
|
}
|
|
181
|
-
let canContinue
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
await this.initialiseTypeConfig(type, typeConfig, module, method);
|
|
185
|
-
}
|
|
186
|
-
canContinue = await this.bootstrap();
|
|
181
|
+
let canContinue;
|
|
182
|
+
try {
|
|
183
|
+
canContinue = await this.stateLoad();
|
|
187
184
|
if (canContinue) {
|
|
185
|
+
for (const { type, typeConfig, module, method } of this._typeInitialisers) {
|
|
186
|
+
await this.initialiseTypeConfig(type, typeConfig, module, method);
|
|
187
|
+
}
|
|
188
|
+
await this.bootstrap();
|
|
188
189
|
this.logInfo(core.I18n.formatMessage("engineCore.componentsStarting"));
|
|
189
190
|
for (const instance of this._context.componentInstances) {
|
|
190
191
|
if (core.Is.function(instance.component.start)) {
|
|
191
|
-
this.
|
|
192
|
-
|
|
192
|
+
const instanceName = this.getInstanceName(instance);
|
|
193
|
+
this.logInfo(core.I18n.formatMessage("engineCore.componentStarting", {
|
|
194
|
+
element: instance.instanceType
|
|
195
|
+
}));
|
|
196
|
+
const componentState = this._context.state.componentStates[instanceName] ?? {};
|
|
197
|
+
const lastState = core.ObjectHelper.clone(componentState);
|
|
198
|
+
await instance.component.start(this._context.state.nodeIdentity, this._loggerTypeName, componentState);
|
|
199
|
+
if (!core.ObjectHelper.equal(lastState, componentState)) {
|
|
200
|
+
this._context.state.componentStates[instanceName] = componentState;
|
|
201
|
+
this._context.stateDirty = true;
|
|
202
|
+
}
|
|
193
203
|
}
|
|
194
204
|
}
|
|
195
205
|
this.logInfo(core.I18n.formatMessage("engineCore.componentsComplete"));
|
|
196
206
|
}
|
|
197
|
-
}
|
|
198
|
-
if (canContinue) {
|
|
199
207
|
this.logInfo(core.I18n.formatMessage("engineCore.started"));
|
|
200
208
|
this._isStarted = true;
|
|
201
209
|
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
canContinue = false;
|
|
212
|
+
this.logError(core.BaseError.fromError(err));
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
if (!(await this.stateSave())) {
|
|
216
|
+
canContinue = false;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
202
219
|
return canContinue;
|
|
203
220
|
}
|
|
204
221
|
/**
|
|
@@ -210,9 +227,16 @@ class EngineCore {
|
|
|
210
227
|
this.logInfo(core.I18n.formatMessage("engineCore.componentsStopping"));
|
|
211
228
|
for (const instance of this._context.componentInstances) {
|
|
212
229
|
if (core.Is.function(instance.component.stop)) {
|
|
230
|
+
const instanceName = this.getInstanceName(instance);
|
|
231
|
+
const componentState = this._context.state.componentStates[instanceName] ?? {};
|
|
232
|
+
const lastState = core.ObjectHelper.clone(componentState);
|
|
213
233
|
this.logInfo(core.I18n.formatMessage("engineCore.componentStopping", { element: instance.instanceType }));
|
|
214
234
|
try {
|
|
215
|
-
await instance.component.stop(this._context.state.nodeIdentity, this._loggerTypeName);
|
|
235
|
+
await instance.component.stop(this._context.state.nodeIdentity, this._loggerTypeName, componentState);
|
|
236
|
+
if (!core.ObjectHelper.equal(lastState, componentState)) {
|
|
237
|
+
this._context.state.componentStates[instanceName] = componentState;
|
|
238
|
+
this._context.stateDirty = true;
|
|
239
|
+
}
|
|
216
240
|
}
|
|
217
241
|
catch (err) {
|
|
218
242
|
this.logError(new core.GeneralError(this.CLASS_NAME, "componentStopFailed", {
|
|
@@ -221,6 +245,7 @@ class EngineCore {
|
|
|
221
245
|
}
|
|
222
246
|
}
|
|
223
247
|
}
|
|
248
|
+
await this.stateSave();
|
|
224
249
|
this.logInfo(core.I18n.formatMessage("engineCore.componentsStopped"));
|
|
225
250
|
this.logInfo(core.I18n.formatMessage("engineCore.stopped"));
|
|
226
251
|
}
|
|
@@ -314,7 +339,7 @@ class EngineCore {
|
|
|
314
339
|
config: cloneData.config,
|
|
315
340
|
defaultTypes: {},
|
|
316
341
|
componentInstances: [],
|
|
317
|
-
state: { bootstrappedComponents: [] },
|
|
342
|
+
state: { bootstrappedComponents: [], componentStates: {} },
|
|
318
343
|
stateDirty: false
|
|
319
344
|
};
|
|
320
345
|
this._typeInitialisers = cloneData.typeInitialisers;
|
|
@@ -373,9 +398,11 @@ class EngineCore {
|
|
|
373
398
|
if (this._stateStorage) {
|
|
374
399
|
try {
|
|
375
400
|
this._context.state = ((await this._stateStorage.load(this)) ?? {
|
|
376
|
-
bootstrappedComponents: []
|
|
401
|
+
bootstrappedComponents: [],
|
|
402
|
+
componentStates: {}
|
|
377
403
|
});
|
|
378
404
|
this._context.state.bootstrappedComponents ??= [];
|
|
405
|
+
this._context.state.componentStates ??= {};
|
|
379
406
|
this._context.stateDirty = false;
|
|
380
407
|
return true;
|
|
381
408
|
}
|
|
@@ -407,54 +434,54 @@ class EngineCore {
|
|
|
407
434
|
}
|
|
408
435
|
/**
|
|
409
436
|
* Bootstrap the engine.
|
|
410
|
-
* @returns True if the engine can continue.
|
|
411
437
|
* @internal
|
|
412
438
|
*/
|
|
413
439
|
async bootstrap() {
|
|
414
|
-
let canContinue = true;
|
|
415
440
|
if (!this._skipBootstrap) {
|
|
416
441
|
this.logInfo(core.I18n.formatMessage("engineCore.bootstrapStarted"));
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
442
|
+
// First bootstrap the components.
|
|
443
|
+
for (const instance of this._context.componentInstances) {
|
|
444
|
+
if (core.Is.function(instance.component.bootstrap)) {
|
|
445
|
+
const instanceName = this.getInstanceName(instance);
|
|
446
|
+
if (!this._context.state.bootstrappedComponents.includes(instanceName)) {
|
|
447
|
+
this.logInfo(core.I18n.formatMessage("engineCore.bootstrapping", {
|
|
448
|
+
element: instanceName
|
|
449
|
+
}));
|
|
450
|
+
const componentState = this._context.state.componentStates[instanceName] ?? {};
|
|
451
|
+
const lastState = core.ObjectHelper.clone(componentState);
|
|
452
|
+
const bootstrapSuccess = await instance.component.bootstrap(this._loggerTypeName, componentState);
|
|
453
|
+
// If the bootstrap method failed then throw an error
|
|
454
|
+
if (!bootstrapSuccess) {
|
|
455
|
+
throw new core.GeneralError(this.CLASS_NAME, "bootstrapFailed", {
|
|
456
|
+
component: `${instance.component.CLASS_NAME}:${instance.instanceType}`
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
// Otherwise add the component to the bootstrapped list and set the state as dirty
|
|
460
|
+
this._context.state.bootstrappedComponents.push(instanceName);
|
|
461
|
+
if (!core.ObjectHelper.equal(lastState, componentState)) {
|
|
462
|
+
this._context.state.componentStates[instanceName] = componentState;
|
|
436
463
|
}
|
|
464
|
+
this._context.stateDirty = true;
|
|
437
465
|
}
|
|
438
466
|
}
|
|
439
|
-
// Now perform any custom bootstrap operations
|
|
440
|
-
if (canContinue && core.Is.function(this._customBootstrap)) {
|
|
441
|
-
await this._customBootstrap(this, this._context);
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
catch (err) {
|
|
445
|
-
canContinue = false;
|
|
446
|
-
this.logError(core.BaseError.fromError(err));
|
|
447
467
|
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
}
|
|
452
|
-
else {
|
|
453
|
-
canContinue = false;
|
|
454
|
-
}
|
|
468
|
+
// Now perform any custom bootstrap operations
|
|
469
|
+
if (core.Is.function(this._customBootstrap)) {
|
|
470
|
+
await this._customBootstrap(this, this._context);
|
|
455
471
|
}
|
|
472
|
+
this.logInfo(core.I18n.formatMessage("engineCore.bootstrapComplete"));
|
|
456
473
|
}
|
|
457
|
-
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Get the instance name.
|
|
477
|
+
* @param instance The instance to get the name for.
|
|
478
|
+
* @param instance.instanceType The instance type.
|
|
479
|
+
* @param instance.component The component.
|
|
480
|
+
* @returns The instance name.
|
|
481
|
+
* @internal
|
|
482
|
+
*/
|
|
483
|
+
getInstanceName(instance) {
|
|
484
|
+
return `${instance.component.CLASS_NAME}-${instance.instanceType}`;
|
|
458
485
|
}
|
|
459
486
|
}
|
|
460
487
|
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I18n, StringHelper, Is,
|
|
1
|
+
import { I18n, StringHelper, Is, ObjectHelper, BaseError, GeneralError, ErrorHelper, Guards } from '@twin.org/core';
|
|
2
2
|
import { EntitySchemaFactory } from '@twin.org/entity';
|
|
3
3
|
import { ConsoleLoggingConnector } from '@twin.org/logging-connector-console';
|
|
4
4
|
import { SilentLoggingConnector, LoggingConnectorFactory } from '@twin.org/logging-models';
|
|
@@ -137,7 +137,7 @@ class EngineCore {
|
|
|
137
137
|
config: options.config,
|
|
138
138
|
defaultTypes: {},
|
|
139
139
|
componentInstances: [],
|
|
140
|
-
state: { bootstrappedComponents: [] },
|
|
140
|
+
state: { bootstrappedComponents: [], componentStates: {} },
|
|
141
141
|
stateDirty: false
|
|
142
142
|
};
|
|
143
143
|
this._stateStorage = options.stateStorage;
|
|
@@ -176,27 +176,44 @@ class EngineCore {
|
|
|
176
176
|
if (this._context.config.debug) {
|
|
177
177
|
this.logInfo(I18n.formatMessage("engineCore.debuggingEnabled"));
|
|
178
178
|
}
|
|
179
|
-
let canContinue
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
await this.initialiseTypeConfig(type, typeConfig, module, method);
|
|
183
|
-
}
|
|
184
|
-
canContinue = await this.bootstrap();
|
|
179
|
+
let canContinue;
|
|
180
|
+
try {
|
|
181
|
+
canContinue = await this.stateLoad();
|
|
185
182
|
if (canContinue) {
|
|
183
|
+
for (const { type, typeConfig, module, method } of this._typeInitialisers) {
|
|
184
|
+
await this.initialiseTypeConfig(type, typeConfig, module, method);
|
|
185
|
+
}
|
|
186
|
+
await this.bootstrap();
|
|
186
187
|
this.logInfo(I18n.formatMessage("engineCore.componentsStarting"));
|
|
187
188
|
for (const instance of this._context.componentInstances) {
|
|
188
189
|
if (Is.function(instance.component.start)) {
|
|
189
|
-
this.
|
|
190
|
-
|
|
190
|
+
const instanceName = this.getInstanceName(instance);
|
|
191
|
+
this.logInfo(I18n.formatMessage("engineCore.componentStarting", {
|
|
192
|
+
element: instance.instanceType
|
|
193
|
+
}));
|
|
194
|
+
const componentState = this._context.state.componentStates[instanceName] ?? {};
|
|
195
|
+
const lastState = ObjectHelper.clone(componentState);
|
|
196
|
+
await instance.component.start(this._context.state.nodeIdentity, this._loggerTypeName, componentState);
|
|
197
|
+
if (!ObjectHelper.equal(lastState, componentState)) {
|
|
198
|
+
this._context.state.componentStates[instanceName] = componentState;
|
|
199
|
+
this._context.stateDirty = true;
|
|
200
|
+
}
|
|
191
201
|
}
|
|
192
202
|
}
|
|
193
203
|
this.logInfo(I18n.formatMessage("engineCore.componentsComplete"));
|
|
194
204
|
}
|
|
195
|
-
}
|
|
196
|
-
if (canContinue) {
|
|
197
205
|
this.logInfo(I18n.formatMessage("engineCore.started"));
|
|
198
206
|
this._isStarted = true;
|
|
199
207
|
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
canContinue = false;
|
|
210
|
+
this.logError(BaseError.fromError(err));
|
|
211
|
+
}
|
|
212
|
+
finally {
|
|
213
|
+
if (!(await this.stateSave())) {
|
|
214
|
+
canContinue = false;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
200
217
|
return canContinue;
|
|
201
218
|
}
|
|
202
219
|
/**
|
|
@@ -208,9 +225,16 @@ class EngineCore {
|
|
|
208
225
|
this.logInfo(I18n.formatMessage("engineCore.componentsStopping"));
|
|
209
226
|
for (const instance of this._context.componentInstances) {
|
|
210
227
|
if (Is.function(instance.component.stop)) {
|
|
228
|
+
const instanceName = this.getInstanceName(instance);
|
|
229
|
+
const componentState = this._context.state.componentStates[instanceName] ?? {};
|
|
230
|
+
const lastState = ObjectHelper.clone(componentState);
|
|
211
231
|
this.logInfo(I18n.formatMessage("engineCore.componentStopping", { element: instance.instanceType }));
|
|
212
232
|
try {
|
|
213
|
-
await instance.component.stop(this._context.state.nodeIdentity, this._loggerTypeName);
|
|
233
|
+
await instance.component.stop(this._context.state.nodeIdentity, this._loggerTypeName, componentState);
|
|
234
|
+
if (!ObjectHelper.equal(lastState, componentState)) {
|
|
235
|
+
this._context.state.componentStates[instanceName] = componentState;
|
|
236
|
+
this._context.stateDirty = true;
|
|
237
|
+
}
|
|
214
238
|
}
|
|
215
239
|
catch (err) {
|
|
216
240
|
this.logError(new GeneralError(this.CLASS_NAME, "componentStopFailed", {
|
|
@@ -219,6 +243,7 @@ class EngineCore {
|
|
|
219
243
|
}
|
|
220
244
|
}
|
|
221
245
|
}
|
|
246
|
+
await this.stateSave();
|
|
222
247
|
this.logInfo(I18n.formatMessage("engineCore.componentsStopped"));
|
|
223
248
|
this.logInfo(I18n.formatMessage("engineCore.stopped"));
|
|
224
249
|
}
|
|
@@ -312,7 +337,7 @@ class EngineCore {
|
|
|
312
337
|
config: cloneData.config,
|
|
313
338
|
defaultTypes: {},
|
|
314
339
|
componentInstances: [],
|
|
315
|
-
state: { bootstrappedComponents: [] },
|
|
340
|
+
state: { bootstrappedComponents: [], componentStates: {} },
|
|
316
341
|
stateDirty: false
|
|
317
342
|
};
|
|
318
343
|
this._typeInitialisers = cloneData.typeInitialisers;
|
|
@@ -371,9 +396,11 @@ class EngineCore {
|
|
|
371
396
|
if (this._stateStorage) {
|
|
372
397
|
try {
|
|
373
398
|
this._context.state = ((await this._stateStorage.load(this)) ?? {
|
|
374
|
-
bootstrappedComponents: []
|
|
399
|
+
bootstrappedComponents: [],
|
|
400
|
+
componentStates: {}
|
|
375
401
|
});
|
|
376
402
|
this._context.state.bootstrappedComponents ??= [];
|
|
403
|
+
this._context.state.componentStates ??= {};
|
|
377
404
|
this._context.stateDirty = false;
|
|
378
405
|
return true;
|
|
379
406
|
}
|
|
@@ -405,54 +432,54 @@ class EngineCore {
|
|
|
405
432
|
}
|
|
406
433
|
/**
|
|
407
434
|
* Bootstrap the engine.
|
|
408
|
-
* @returns True if the engine can continue.
|
|
409
435
|
* @internal
|
|
410
436
|
*/
|
|
411
437
|
async bootstrap() {
|
|
412
|
-
let canContinue = true;
|
|
413
438
|
if (!this._skipBootstrap) {
|
|
414
439
|
this.logInfo(I18n.formatMessage("engineCore.bootstrapStarted"));
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
440
|
+
// First bootstrap the components.
|
|
441
|
+
for (const instance of this._context.componentInstances) {
|
|
442
|
+
if (Is.function(instance.component.bootstrap)) {
|
|
443
|
+
const instanceName = this.getInstanceName(instance);
|
|
444
|
+
if (!this._context.state.bootstrappedComponents.includes(instanceName)) {
|
|
445
|
+
this.logInfo(I18n.formatMessage("engineCore.bootstrapping", {
|
|
446
|
+
element: instanceName
|
|
447
|
+
}));
|
|
448
|
+
const componentState = this._context.state.componentStates[instanceName] ?? {};
|
|
449
|
+
const lastState = ObjectHelper.clone(componentState);
|
|
450
|
+
const bootstrapSuccess = await instance.component.bootstrap(this._loggerTypeName, componentState);
|
|
451
|
+
// If the bootstrap method failed then throw an error
|
|
452
|
+
if (!bootstrapSuccess) {
|
|
453
|
+
throw new GeneralError(this.CLASS_NAME, "bootstrapFailed", {
|
|
454
|
+
component: `${instance.component.CLASS_NAME}:${instance.instanceType}`
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
// Otherwise add the component to the bootstrapped list and set the state as dirty
|
|
458
|
+
this._context.state.bootstrappedComponents.push(instanceName);
|
|
459
|
+
if (!ObjectHelper.equal(lastState, componentState)) {
|
|
460
|
+
this._context.state.componentStates[instanceName] = componentState;
|
|
434
461
|
}
|
|
462
|
+
this._context.stateDirty = true;
|
|
435
463
|
}
|
|
436
464
|
}
|
|
437
|
-
// Now perform any custom bootstrap operations
|
|
438
|
-
if (canContinue && Is.function(this._customBootstrap)) {
|
|
439
|
-
await this._customBootstrap(this, this._context);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
catch (err) {
|
|
443
|
-
canContinue = false;
|
|
444
|
-
this.logError(BaseError.fromError(err));
|
|
445
465
|
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
}
|
|
450
|
-
else {
|
|
451
|
-
canContinue = false;
|
|
452
|
-
}
|
|
466
|
+
// Now perform any custom bootstrap operations
|
|
467
|
+
if (Is.function(this._customBootstrap)) {
|
|
468
|
+
await this._customBootstrap(this, this._context);
|
|
453
469
|
}
|
|
470
|
+
this.logInfo(I18n.formatMessage("engineCore.bootstrapComplete"));
|
|
454
471
|
}
|
|
455
|
-
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Get the instance name.
|
|
475
|
+
* @param instance The instance to get the name for.
|
|
476
|
+
* @param instance.instanceType The instance type.
|
|
477
|
+
* @param instance.component The component.
|
|
478
|
+
* @returns The instance name.
|
|
479
|
+
* @internal
|
|
480
|
+
*/
|
|
481
|
+
getInstanceName(instance) {
|
|
482
|
+
return `${instance.component.CLASS_NAME}-${instance.instanceType}`;
|
|
456
483
|
}
|
|
457
484
|
}
|
|
458
485
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/engine-core",
|
|
3
|
-
"version": "0.0.1-next.
|
|
3
|
+
"version": "0.0.1-next.29",
|
|
4
4
|
"description": "Engine core.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@twin.org/crypto": "next",
|
|
19
19
|
"@twin.org/data-core": "next",
|
|
20
20
|
"@twin.org/data-schema-org": "next",
|
|
21
|
-
"@twin.org/engine-models": "0.0.1-next.
|
|
21
|
+
"@twin.org/engine-models": "0.0.1-next.29",
|
|
22
22
|
"@twin.org/entity": "next",
|
|
23
23
|
"@twin.org/logging-connector-console": "next",
|
|
24
24
|
"@twin.org/logging-models": "next",
|