Skip to content

Commit 7fb8e2d

Browse files
authored
Merge branch 'master' into propser-shutdown-handling2
2 parents 252ead0 + 38f3b48 commit 7fb8e2d

File tree

8 files changed

+1148
-175
lines changed

8 files changed

+1148
-175
lines changed

package-lock.json

Lines changed: 1045 additions & 95 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/adapter/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"@iobroker/db-states-redis": "file:../db-states-redis",
1616
"@iobroker/js-controller-common": "file:../common",
1717
"@iobroker/js-controller-common-db": "file:../common-db",
18-
"@iobroker/plugin-base": "~2.0.1",
18+
"@iobroker/plugin-base": "~3.0.3",
1919
"deep-clone": "^3.0.3",
2020
"fs-extra": "^11.3.2",
2121
"jsonwebtoken": "^9.0.0",

packages/adapter/src/lib/adapter/adapter.ts

Lines changed: 83 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import fs from 'fs-extra';
1515
import type { CommandResult } from '@alcalzone/pak';
1616
import * as url from 'node:url';
1717

18-
import { PluginHandler } from '@iobroker/plugin-base';
18+
import { PluginHandler, type IoPackageFile } from '@iobroker/plugin-base';
1919
import {
2020
EXIT_CODES,
2121
getObjectsConstructor,
@@ -61,7 +61,7 @@ import {
6161
SYSTEM_ADMIN_GROUP,
6262
SYSTEM_ADMIN_USER,
6363
} from '@/lib/adapter/constants.js';
64-
import type { PluginHandlerSettings } from '@iobroker/plugin-base/types';
64+
import type { PluginHandlerSettings } from '@iobroker/plugin-base';
6565
import type {
6666
AdapterOptions,
6767
AliasDetails,
@@ -706,7 +706,7 @@ export class AdapterClass extends EventEmitter {
706706
/** An array of instances, that support auto subscribe */
707707
private autoSubscribe: string[] = [];
708708
private defaultHistory: null | string = null;
709-
private pluginHandler?: InstanceType<typeof PluginHandler>;
709+
private pluginHandler?: PluginHandler;
710710
private _reportInterval?: null | NodeJS.Timeout;
711711
private getPortRunning: null | InternalGetPortOptions = null;
712712
private readonly _namespaceRegExp: RegExp;
@@ -1494,68 +1494,83 @@ export class AdapterClass extends EventEmitter {
14941494
}
14951495
this.terminated = true;
14961496

1497-
this.pluginHandler && this.pluginHandler.destroyAll();
1498-
1499-
if (this._reportInterval) {
1500-
clearInterval(this._reportInterval);
1501-
this._reportInterval = null;
1502-
}
1503-
if (this._restartScheduleJob) {
1504-
this._restartScheduleJob.cancel();
1505-
this._restartScheduleJob = null;
1506-
}
1507-
1508-
let _reason = 'Without reason';
1509-
let _exitCode: number;
1497+
let shutdownStarted = false;
1498+
const shutdownLogic: () => void = () => {
1499+
if (shutdownStarted) {
1500+
return;
1501+
}
1502+
shutdownStarted = true;
15101503

1511-
if (typeof reason === 'number') {
1512-
// Only the exit code was passed
1513-
exitCode = reason;
1514-
_reason = 'Without reason';
1515-
} else if (reason && typeof reason === 'string') {
1516-
_reason = reason;
1517-
}
1504+
if (this._reportInterval) {
1505+
clearInterval(this._reportInterval);
1506+
this._reportInterval = null;
1507+
}
1508+
if (this._restartScheduleJob) {
1509+
this._restartScheduleJob.cancel();
1510+
this._restartScheduleJob = null;
1511+
}
15181512

1519-
if (typeof exitCode !== 'number') {
1520-
_exitCode = !this._config.isInstall ? EXIT_CODES.ADAPTER_REQUESTED_TERMINATION : EXIT_CODES.NO_ERROR;
1521-
} else {
1522-
_exitCode = exitCode;
1523-
}
1513+
let _reason = 'Without reason';
1514+
let _exitCode: number;
15241515

1525-
const isNotCritical =
1526-
_exitCode === EXIT_CODES.ADAPTER_REQUESTED_TERMINATION ||
1527-
_exitCode === EXIT_CODES.START_IMMEDIATELY_AFTER_STOP ||
1528-
_exitCode === EXIT_CODES.NO_ERROR;
1529-
const text = `${this.namespaceLog} Terminated (${Validator.getErrorText(_exitCode)}): ${_reason}`;
1530-
if (isNotCritical) {
1531-
this._logger.info(text);
1532-
} else {
1533-
this._logger.warn(text);
1534-
}
1535-
setTimeout(async () => {
1536-
// give last states some time to get handled
1537-
if (this.#states) {
1538-
try {
1539-
await this.#states.destroy();
1540-
} catch {
1541-
// ignore
1542-
}
1516+
if (typeof reason === 'number') {
1517+
// Only the exit code was passed
1518+
exitCode = reason;
1519+
_reason = 'Without reason';
1520+
} else if (reason && typeof reason === 'string') {
1521+
_reason = reason;
15431522
}
1544-
if (this.#objects) {
1545-
try {
1546-
await this.#objects.destroy();
1547-
} catch {
1548-
//ignore
1549-
}
1523+
1524+
if (typeof exitCode !== 'number') {
1525+
_exitCode = !this._config.isInstall ? EXIT_CODES.ADAPTER_REQUESTED_TERMINATION : EXIT_CODES.NO_ERROR;
1526+
} else {
1527+
_exitCode = exitCode;
15501528
}
1551-
if (this.startedInCompactMode) {
1552-
this.emit('exit', _exitCode, reason);
1553-
this.#states = null;
1554-
this.#objects = null;
1529+
1530+
const isNotCritical =
1531+
_exitCode === EXIT_CODES.ADAPTER_REQUESTED_TERMINATION ||
1532+
_exitCode === EXIT_CODES.START_IMMEDIATELY_AFTER_STOP ||
1533+
_exitCode === EXIT_CODES.NO_ERROR;
1534+
const text = `${this.namespaceLog} Terminated (${Validator.getErrorText(_exitCode)}): ${_reason}`;
1535+
if (isNotCritical) {
1536+
this._logger.info(text);
15551537
} else {
1556-
process.exit(_exitCode);
1538+
this._logger.warn(text);
15571539
}
1558-
}, 500);
1540+
setTimeout(async () => {
1541+
// give last states some time to get handled
1542+
if (this.#states) {
1543+
try {
1544+
await this.#states.destroy();
1545+
} catch {
1546+
// ignore
1547+
}
1548+
}
1549+
if (this.#objects) {
1550+
try {
1551+
await this.#objects.destroy();
1552+
} catch {
1553+
//ignore
1554+
}
1555+
}
1556+
if (this.startedInCompactMode) {
1557+
this.emit('exit', _exitCode, reason);
1558+
this.#states = null;
1559+
this.#objects = null;
1560+
} else {
1561+
process.exit(_exitCode);
1562+
}
1563+
}, 500);
1564+
};
1565+
1566+
if (this.pluginHandler) {
1567+
this.pluginHandler
1568+
.destroyAll()
1569+
.then(() => shutdownLogic())
1570+
.catch(() => shutdownLogic());
1571+
} else {
1572+
shutdownLogic();
1573+
}
15591574
}
15601575

15611576
// external signature
@@ -11068,11 +11083,16 @@ export class AdapterClass extends EventEmitter {
1106811083
this.pluginHandler.getPluginConfig(pluginName) || {},
1106911084
thisDir,
1107011085
);
11086+
// @ts-expect-error objects and state object version conflicts that are none
1107111087
this.pluginHandler.setDatabaseForPlugin(pluginName, this.#objects, this.#states);
11072-
this.pluginHandler.initPlugin(pluginName, this.adapterConfig || {});
11088+
11089+
await this.pluginHandler.initPlugin(
11090+
pluginName,
11091+
(this.adapterConfig || {}) as IoPackageFile,
11092+
);
1107311093
}
1107411094
} else {
11075-
if (!this.pluginHandler.destroy(pluginName)) {
11095+
if (!(await this.pluginHandler.destroy(pluginName))) {
1107611096
this._logger.info(
1107711097
`${this.namespaceLog} Plugin ${pluginName} could not be disabled. Please restart adapter to disable it.`,
1107811098
);
@@ -11489,8 +11509,9 @@ export class AdapterClass extends EventEmitter {
1148911509
if (!this.pluginHandler) {
1149011510
return;
1149111511
}
11512+
// @ts-expect-error objects and state object version conflicts that are none
1149211513
this.pluginHandler.setDatabaseForPlugins(this.#objects, this.#states);
11493-
await this.pluginHandler.initPlugins(adapterConfig || {});
11514+
await this.pluginHandler.initPlugins((adapterConfig || {}) as IoPackageFile);
1149411515
if (!this.#states || !this.#objects || this.terminated) {
1149511516
// if adapterState was destroyed, we should not continue
1149611517
return;
@@ -12160,8 +12181,7 @@ export class AdapterClass extends EventEmitter {
1216012181
// @ts-expect-error
1216112182
log: this._logger,
1216212183
iobrokerConfig: this._config,
12163-
// @ts-expect-error
12164-
parentPackage: this.pack,
12184+
parentPackage: this.pack!,
1216512185
controllerVersion,
1216612186
};
1216712187

packages/cli/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
"dependencies": {
99
"@iobroker/js-controller-common": "file:../common",
1010
"@iobroker/js-controller-common-db": "file:../common-db",
11-
"@iobroker/plugin-base": "~2.0.1",
11+
"@iobroker/plugin-base": "~3.0.3",
1212
"axios": "^1.12.0",
1313
"chokidar": "^3.5.3",
14-
"debug": "^4.3.4",
14+
"debug": "^4.4.3",
1515
"deep-clone": "^3.0.3",
1616
"event-stream": "^4.0.1",
1717
"fs-extra": "^11.3.2",

packages/cli/src/lib/setup/dbConnection.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { setTimeout as wait } from 'node:timers/promises';
1212
import type { Client as StatesRedisClient } from '@iobroker/db-states-redis';
1313
import type { Client as ObjectsInRedisClient } from '@iobroker/db-objects-redis';
1414
import path from 'node:path';
15-
import type { PluginHandlerSettings } from '@iobroker/plugin-base/types';
15+
import type { InternalAdapterJsonConfig, PluginHandlerSettings } from '@iobroker/plugin-base';
1616
import { PluginHandler } from '@iobroker/plugin-base';
1717

1818
let pluginHandler: InstanceType<typeof PluginHandler>;
@@ -359,7 +359,7 @@ export async function resetDbConnect(): Promise<void> {
359359
}
360360

361361
if (pluginHandler) {
362-
pluginHandler.destroyAll();
362+
await pluginHandler.destroyAll();
363363
}
364364
}
365365

@@ -403,14 +403,15 @@ function initializePlugins(config: Record<string, any>): Promise<void> {
403403
error: (msg: string) => console.log(msg),
404404
level: 'warn',
405405
},
406-
iobrokerConfig: config,
406+
iobrokerConfig: config as InternalAdapterJsonConfig,
407407
parentPackage: packageJson,
408408
controllerVersion: ioPackage.common.version,
409409
};
410410

411411
pluginHandler = new PluginHandler(pluginSettings);
412412
pluginHandler.addPlugins(ioPackage.common.plugins, tools.getControllerDir()); // Plugins from io-package have priority over ...
413413
pluginHandler.addPlugins(config.plugins, tools.getControllerDir()); // ... plugins from iobroker.json
414+
// @ts-expect-error objects and state object version conflicts that are none
414415
pluginHandler.setDatabaseForPlugins(objects, states);
415416

416417
return pluginHandler.initPlugins(ioPackage);

packages/controller/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
"@iobroker/js-controller-cli": "file:../cli",
2121
"@iobroker/js-controller-common": "file:../common",
2222
"@iobroker/js-controller-common-db": "file:../common-db",
23-
"@iobroker/plugin-base": "~2.0.1",
24-
"@iobroker/plugin-sentry": "~2.0.4",
23+
"@iobroker/plugin-base": "~3.0.3",
24+
"@iobroker/plugin-sentry": "~3.0.0",
2525
"axios": "^1.12.0",
2626
"cron-parser": "^4.9.0",
27-
"debug": "^4.3.4",
27+
"debug": "^4.4.3",
2828
"decache": "^4.6.1",
2929
"deep-clone": "^3.0.3",
3030
"fs-extra": "^11.3.2",

packages/controller/src/main.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import type { Client as StatesClient } from '@iobroker/db-states-redis';
3737
import { Upload, PacketManager, type UpgradePacket } from '@iobroker/js-controller-cli';
3838
import decache from 'decache';
3939
import cronParser from 'cron-parser';
40-
import type { PluginHandlerSettings } from '@iobroker/plugin-base/types';
40+
import type { PluginHandlerSettings } from '@iobroker/plugin-base';
4141
import type { GetDiskInfoResponse } from '@iobroker/js-controller-common-db/tools';
4242
import { DEFAULT_DISK_WARNING_LEVEL, getCronExpression, getDiskWarningLevel } from '@/lib/utils.js';
4343
import { AdapterAutoUpgradeManager } from '@/lib/adapterAutoUpgradeManager.js';
@@ -615,11 +615,12 @@ function createStates(onConnect: () => void): void {
615615
pluginHandler.getPluginConfig(pluginName)!,
616616
controllerDir,
617617
);
618+
// @ts-expect-error objects and state object version conflicts that are none
618619
pluginHandler.setDatabaseForPlugin(pluginName, objects, states);
619-
pluginHandler.initPlugin(pluginName, ioPackage);
620+
await pluginHandler.initPlugin(pluginName, ioPackage);
620621
}
621622
} else {
622-
if (!pluginHandler.destroy(pluginName)) {
623+
if (!(await pluginHandler.destroy(pluginName))) {
623624
logger.info(
624625
`${hostLogPrefix} Plugin ${pluginName} could not be disabled. Please restart ioBroker to disable it.`,
625626
);
@@ -704,6 +705,7 @@ async function initializeController(): Promise<void> {
704705
if (connected === null) {
705706
connected = true;
706707
if (!isStopping) {
708+
// @ts-expect-error objects and state object version conflicts that are none
707709
pluginHandler.setDatabaseForPlugins(objects, states);
708710
await pluginHandler.initPlugins(ioPackage);
709711
states.subscribe(`${hostObjectPrefix}.plugins.*`);
@@ -3006,7 +3008,7 @@ async function processMessage(msg: ioBroker.SendableMessage): Promise<null | voi
30063008
const extraInfo: Record<string, unknown> = msg.message.extraInfo;
30073009

30083010
const sentryObj = (
3009-
pluginHandler.getPluginInstance('sentry') as InstanceType<typeof SentryPlugin> | null
3011+
pluginHandler.getPluginInstance('sentry') as InstanceType<typeof SentryPlugin.default> | null
30103012
)?.getSentryObject();
30113013

30123014
if (!sentryObj) {
@@ -5141,7 +5143,7 @@ function stop(force?: boolean, callback?: () => void): void {
51415143
}
51425144

51435145
stopInstances(force, async wasForced => {
5144-
pluginHandler.destroyAll();
5146+
await pluginHandler.destroyAll();
51455147
notificationHandler && notificationHandler.storeNotifications();
51465148

51475149
try {

packages/types-dev/objects.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ declare global {
431431
tmpdir: ReturnType<(typeof os)['tmpdir']>;
432432
};
433433
hardware: {
434-
/** Return value of os.cpu but property `times` could be removed from every entry */
434+
/** Return value of `os.cpu` but property `times` could be removed from every entry */
435435
cpus: (Omit<ReturnType<(typeof os)['cpus']>[number], 'times'> &
436436
Partial<Pick<ReturnType<(typeof os)['cpus']>[number], 'times'>>)[];
437437
totalmem: ReturnType<(typeof os)['totalmem']>;
@@ -1056,7 +1056,7 @@ declare global {
10561056
version: string;
10571057
/** Array of blocked versions, each entry represents a semver range */
10581058
blockedVersions: string[];
1059-
/** If true the unsafe perm flag is needed on install */
1059+
/** If true, the unsafe perm flag is needed on install */
10601060
unsafePerm?: boolean;
10611061
/** If given, the packet name differs from the adapter name, e.g. because it is a scoped package */
10621062
packetName?: string;
@@ -1072,7 +1072,7 @@ declare global {
10721072
name: Required<ioBroker.Translated>;
10731073
/** Time of repository update */
10741074
repoTime: string;
1075-
/** Time when repository was last read/fetched */
1075+
/** Time when the repository was last read/fetched */
10761076
repoReadTime?: string;
10771077
}
10781078

0 commit comments

Comments
 (0)