From e4b8e32db91e4042e080826b9cfc740d1c2504da Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 27 Oct 2025 12:30:29 +0100 Subject: [PATCH 1/2] fix(dashmate): rs-dapi not stopped when dashmate reset --platform -f is called --- .../platform/v0/objective-c/Platform.pbobjc.h | 10 ++++-- .../src/config/getPlatformProfilesFactory.js | 32 +++++++++++++++++++ packages/dashmate/src/createDIContainer.js | 2 ++ .../src/listr/tasks/resetNodeTaskFactory.js | 16 +++++++--- .../src/listr/tasks/startNodeTaskFactory.js | 15 ++------- .../src/listr/tasks/stopNodeTaskFactory.js | 23 +++++-------- 6 files changed, 63 insertions(+), 35 deletions(-) create mode 100644 packages/dashmate/src/config/getPlatformProfilesFactory.js diff --git a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h index 261fab62628..7f6df1c7aa4 100644 --- a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h +++ b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h @@ -3362,7 +3362,7 @@ GPB_FINAL @interface GetFinalizedEpochInfosResponse_GetFinalizedEpochInfosRespon /** The actual finalized information about the requested epochs */ @property(nonatomic, readwrite, strong, null_resettable) GetFinalizedEpochInfosResponse_GetFinalizedEpochInfosResponseV0_FinalizedEpochInfos *epochs; -/** Cryptographic proof of the finalized epoch information, if requested */ +/** Cryptographic proof of the finalized epoch */ @property(nonatomic, readwrite, strong, null_resettable) Proof *proof; /** Metadata about the blockchain state */ @@ -3384,7 +3384,8 @@ typedef GPB_ENUM(GetFinalizedEpochInfosResponse_GetFinalizedEpochInfosResponseV0 }; /** - * FinalizedEpochInfos holds a collection of finalized epoch information entries + * FinalizedEpochInfos holds a collection of finalized epoch information + * entries **/ GPB_FINAL @interface GetFinalizedEpochInfosResponse_GetFinalizedEpochInfosResponseV0_FinalizedEpochInfos : GPBMessage @@ -6438,7 +6439,10 @@ GPB_FINAL @interface GetTokenPerpetualDistributionLastClaimRequest_GetTokenPerpe /** 32‑byte token identifier */ @property(nonatomic, readwrite, copy, null_resettable) NSData *tokenId; -/** This should be set if you wish to get back the last claim info as a specific type */ +/** + * This should be set if you wish to get back the last claim info as a + * specific type + **/ @property(nonatomic, readwrite, strong, null_resettable) GetTokenPerpetualDistributionLastClaimRequest_ContractTokenInfo *contractInfo; /** Test to see if @c contractInfo has been set. */ @property(nonatomic, readwrite) BOOL hasContractInfo; diff --git a/packages/dashmate/src/config/getPlatformProfilesFactory.js b/packages/dashmate/src/config/getPlatformProfilesFactory.js new file mode 100644 index 00000000000..b8a6f86285f --- /dev/null +++ b/packages/dashmate/src/config/getPlatformProfilesFactory.js @@ -0,0 +1,32 @@ +const PLATFORM_PROFILES = [ + 'platform', + 'platform-dapi-deprecated', + 'platform-dapi-rs', +]; + +/** + * @param {getConfigProfiles} getConfigProfiles + * @return {getPlatformProfiles} + */ +export default function getPlatformProfilesFactory(getConfigProfiles) { + /** + * @typedef {function} getPlatformProfiles + * @param {Config} config + * @param {{includeAll?: boolean}} [options] + * @returns {string[]} + */ + function getPlatformProfiles(config, { includeAll = false } = {}) { + if (!config.get('platform.enable')) { + return []; + } + + if (includeAll) { + return [...PLATFORM_PROFILES]; + } + + return getConfigProfiles(config) + .filter((profile) => profile.startsWith('platform')); + } + + return getPlatformProfiles; +} diff --git a/packages/dashmate/src/createDIContainer.js b/packages/dashmate/src/createDIContainer.js index 3b2e657d2b9..ab8bb8c8677 100644 --- a/packages/dashmate/src/createDIContainer.js +++ b/packages/dashmate/src/createDIContainer.js @@ -117,6 +117,7 @@ import assertLocalServicesRunningFactory from './test/asserts/assertLocalService import assertServiceRunningFactory from './test/asserts/assertServiceRunningFactory.js'; import generateEnvsFactory from './config/generateEnvsFactory.js'; import getConfigProfilesFactory from './config/getConfigProfilesFactory.js'; +import getPlatformProfilesFactory from './config/getPlatformProfilesFactory.js'; import createIpAndPortsFormFactory from './listr/prompts/createIpAndPortsForm.js'; import registerMasternodeWithCoreWalletFactory from './listr/tasks/setup/regular/registerMasternode/registerMasternodeWithCoreWallet.js'; import registerMasternodeWithDMTFactory from './listr/tasks/setup/regular/registerMasternode/registerMasternodeWithDMT.js'; @@ -169,6 +170,7 @@ export default async function createDIContainer(options = {}) { getConnectionHost: asFunction(getConnectionHostFactory).singleton(), generateEnvs: asFunction(generateEnvsFactory).singleton(), getConfigProfiles: asFunction(getConfigProfilesFactory).singleton(), + getPlatformProfiles: asFunction(getPlatformProfilesFactory).singleton(), ensureFileMountExists: asFunction(ensureFileMountExistsFactory).singleton(), // `configFile` and `config` are registering on command init }); diff --git a/packages/dashmate/src/listr/tasks/resetNodeTaskFactory.js b/packages/dashmate/src/listr/tasks/resetNodeTaskFactory.js index 506e601778d..f955d039e4e 100644 --- a/packages/dashmate/src/listr/tasks/resetNodeTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/resetNodeTaskFactory.js @@ -12,6 +12,7 @@ import wait from '../../util/wait.js'; * @param {ConfigFile} configFile * @param {HomeDir} homeDir * @param {generateEnvs} generateEnvs + * @param {getPlatformProfiles} getPlatformProfiles * @return {resetNodeTask} */ export default function resetNodeTaskFactory( @@ -23,6 +24,7 @@ export default function resetNodeTaskFactory( configFile, homeDir, generateEnvs, + getPlatformProfiles, ) { /** * Remove path but ignore permission issues to avoid failing reset on root-owned directories. @@ -70,9 +72,13 @@ export default function resetNodeTaskFactory( title: 'Check services are not running', skip: (ctx) => ctx.isForce, task: async (ctx) => { + const profiles = ctx.isPlatformOnlyReset + ? getPlatformProfiles(config, { includeAll: true }) + : []; + if (await dockerCompose.isNodeRunning( config, - { profiles: ctx.isPlatformOnlyReset ? ['platform'] : [] }, + { profiles }, )) { throw new Error('Running services detected. Please ensure all services are stopped for this config before starting'); } @@ -98,12 +104,14 @@ export default function resetNodeTaskFactory( title: 'Remove platform services and associated data', enabled: (ctx) => ctx.isPlatformOnlyReset, task: async (ctx, task) => { + const profiles = getPlatformProfiles(config, { includeAll: true }); + if (ctx.keepData) { // eslint-disable-next-line no-param-reassign task.title = 'Remove platform services and keep associated data'; } - await dockerCompose.rm(config, { profiles: ['platform'] }); + await dockerCompose.rm(config, { profiles }); // Remove volumes if (!ctx.keepData) { @@ -111,7 +119,7 @@ export default function resetNodeTaskFactory( const projectVolumeNames = await dockerCompose.getVolumeNames( config, - { profiles: ['platform'] }, + { profiles }, ); await Promise.all( @@ -132,7 +140,7 @@ export default function resetNodeTaskFactory( await wait(1000); // Remove containers - await dockerCompose.rm(config, { profiles: ['platform'] }); + await dockerCompose.rm(config, { profiles }); isRetry = true; diff --git a/packages/dashmate/src/listr/tasks/startNodeTaskFactory.js b/packages/dashmate/src/listr/tasks/startNodeTaskFactory.js index e517bdbbd00..9ec4e53f4a4 100644 --- a/packages/dashmate/src/listr/tasks/startNodeTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/startNodeTaskFactory.js @@ -19,7 +19,7 @@ const DAPI_PROFILE_SERVICES = { * @param {getConnectionHost} getConnectionHost * @param {ensureFileMountExists} ensureFileMountExists * @param {HomeDir} homeDir - * @param {getConfigProfiles} getConfigProfiles + * @param {getPlatformProfiles} getPlatformProfiles * @return {startNodeTask} */ export default function startNodeTaskFactory( @@ -31,19 +31,8 @@ export default function startNodeTaskFactory( getConnectionHost, ensureFileMountExists, homeDir, - getConfigProfiles, + getPlatformProfiles, ) { - function getPlatformProfiles(config) { - const platformProfiles = getConfigProfiles(config) - .filter((profile) => profile.startsWith('platform')); - - if (platformProfiles.length === 0) { - platformProfiles.push('platform'); - } - - return Array.from(new Set(platformProfiles)); - } - /** * @typedef {startNodeTask} * @param {Config} config diff --git a/packages/dashmate/src/listr/tasks/stopNodeTaskFactory.js b/packages/dashmate/src/listr/tasks/stopNodeTaskFactory.js index 264aac6dd92..5c0c47cc08f 100644 --- a/packages/dashmate/src/listr/tasks/stopNodeTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/stopNodeTaskFactory.js @@ -7,26 +7,15 @@ import waitForDKGWindowPass from '../../core/quorum/waitForDKGWindowPass.js'; * @param {DockerCompose} dockerCompose * @param {createRpcClient} createRpcClient * @param {getConnectionHost} getConnectionHost - * @param {getConfigProfiles} getConfigProfiles + * @param {getPlatformProfiles} getPlatformProfiles * @return {stopNodeTask} */ export default function stopNodeTaskFactory( dockerCompose, createRpcClient, getConnectionHost, - getConfigProfiles, + getPlatformProfiles, ) { - function getPlatformProfiles(config) { - const platformProfiles = getConfigProfiles(config) - .filter((profile) => profile.startsWith('platform')); - - if (platformProfiles.length === 0) { - platformProfiles.push('platform'); - } - - return Array.from(new Set(platformProfiles)); - } - /** * Stop node * @typedef stopNodeTask @@ -40,7 +29,9 @@ export default function stopNodeTaskFactory( title: 'Check node is running', skip: (ctx) => ctx.isForce, task: async (ctx) => { - const profiles = ctx.platformOnly ? getPlatformProfiles(config) : []; + const profiles = ctx.platformOnly + ? getPlatformProfiles(config, { includeAll: true }) + : []; if (!await dockerCompose.isNodeRunning(config, { profiles })) { throw new Error('Node is not running'); @@ -80,7 +71,9 @@ export default function stopNodeTaskFactory( { title: `Stopping ${config.getName()} node`, task: async (ctx) => { - const profiles = ctx.platformOnly ? getPlatformProfiles(config) : []; + const profiles = ctx.platformOnly + ? getPlatformProfiles(config, { includeAll: true }) + : []; await dockerCompose.stop(config, { profiles }); }, From da65aa4f170879d575c08ccc9e3c44873b0d17bd Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 27 Oct 2025 12:56:42 +0100 Subject: [PATCH 2/2] refactor --- .../src/config/getConfigProfilesFactory.js | 13 +++++--- .../src/config/getPlatformProfilesFactory.js | 32 ------------------- packages/dashmate/src/createDIContainer.js | 2 -- .../src/listr/tasks/resetNodeTaskFactory.js | 13 +++++--- .../src/listr/tasks/startNodeTaskFactory.js | 13 +++++--- .../src/listr/tasks/stopNodeTaskFactory.js | 13 +++++--- 6 files changed, 36 insertions(+), 50 deletions(-) delete mode 100644 packages/dashmate/src/config/getPlatformProfilesFactory.js diff --git a/packages/dashmate/src/config/getConfigProfilesFactory.js b/packages/dashmate/src/config/getConfigProfilesFactory.js index c1aa1bf6428..655386979aa 100644 --- a/packages/dashmate/src/config/getConfigProfilesFactory.js +++ b/packages/dashmate/src/config/getConfigProfilesFactory.js @@ -5,9 +5,10 @@ export default function getConfigProfilesFactory() { /** * @typedef {function} getConfigProfiles * @param {Config} config + * @param {{ includeAll?: boolean }} [options] * @returns {string[]} */ - function getConfigProfiles(config) { + function getConfigProfiles(config, { includeAll = false } = {}) { const profiles = []; profiles.push('core'); @@ -15,15 +16,19 @@ export default function getConfigProfilesFactory() { if (config.get('platform.enable')) { profiles.push('platform'); - // Select which DAPI stack to enable via profiles - if (config.get('platform.dapi.deprecated.enabled')) { + const deprecatedEnabled = config.get('platform.dapi.deprecated.enabled'); + + if (includeAll) { + profiles.push('platform-dapi-deprecated'); + profiles.push('platform-dapi-rs'); + } else if (deprecatedEnabled) { profiles.push('platform-dapi-deprecated'); } else { profiles.push('platform-dapi-rs'); } } - return profiles; + return Array.from(new Set(profiles)); } return getConfigProfiles; diff --git a/packages/dashmate/src/config/getPlatformProfilesFactory.js b/packages/dashmate/src/config/getPlatformProfilesFactory.js deleted file mode 100644 index b8a6f86285f..00000000000 --- a/packages/dashmate/src/config/getPlatformProfilesFactory.js +++ /dev/null @@ -1,32 +0,0 @@ -const PLATFORM_PROFILES = [ - 'platform', - 'platform-dapi-deprecated', - 'platform-dapi-rs', -]; - -/** - * @param {getConfigProfiles} getConfigProfiles - * @return {getPlatformProfiles} - */ -export default function getPlatformProfilesFactory(getConfigProfiles) { - /** - * @typedef {function} getPlatformProfiles - * @param {Config} config - * @param {{includeAll?: boolean}} [options] - * @returns {string[]} - */ - function getPlatformProfiles(config, { includeAll = false } = {}) { - if (!config.get('platform.enable')) { - return []; - } - - if (includeAll) { - return [...PLATFORM_PROFILES]; - } - - return getConfigProfiles(config) - .filter((profile) => profile.startsWith('platform')); - } - - return getPlatformProfiles; -} diff --git a/packages/dashmate/src/createDIContainer.js b/packages/dashmate/src/createDIContainer.js index ab8bb8c8677..3b2e657d2b9 100644 --- a/packages/dashmate/src/createDIContainer.js +++ b/packages/dashmate/src/createDIContainer.js @@ -117,7 +117,6 @@ import assertLocalServicesRunningFactory from './test/asserts/assertLocalService import assertServiceRunningFactory from './test/asserts/assertServiceRunningFactory.js'; import generateEnvsFactory from './config/generateEnvsFactory.js'; import getConfigProfilesFactory from './config/getConfigProfilesFactory.js'; -import getPlatformProfilesFactory from './config/getPlatformProfilesFactory.js'; import createIpAndPortsFormFactory from './listr/prompts/createIpAndPortsForm.js'; import registerMasternodeWithCoreWalletFactory from './listr/tasks/setup/regular/registerMasternode/registerMasternodeWithCoreWallet.js'; import registerMasternodeWithDMTFactory from './listr/tasks/setup/regular/registerMasternode/registerMasternodeWithDMT.js'; @@ -170,7 +169,6 @@ export default async function createDIContainer(options = {}) { getConnectionHost: asFunction(getConnectionHostFactory).singleton(), generateEnvs: asFunction(generateEnvsFactory).singleton(), getConfigProfiles: asFunction(getConfigProfilesFactory).singleton(), - getPlatformProfiles: asFunction(getPlatformProfilesFactory).singleton(), ensureFileMountExists: asFunction(ensureFileMountExistsFactory).singleton(), // `configFile` and `config` are registering on command init }); diff --git a/packages/dashmate/src/listr/tasks/resetNodeTaskFactory.js b/packages/dashmate/src/listr/tasks/resetNodeTaskFactory.js index f955d039e4e..2fbf5d6c660 100644 --- a/packages/dashmate/src/listr/tasks/resetNodeTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/resetNodeTaskFactory.js @@ -12,7 +12,7 @@ import wait from '../../util/wait.js'; * @param {ConfigFile} configFile * @param {HomeDir} homeDir * @param {generateEnvs} generateEnvs - * @param {getPlatformProfiles} getPlatformProfiles + * @param {getConfigProfiles} getConfigProfiles * @return {resetNodeTask} */ export default function resetNodeTaskFactory( @@ -24,8 +24,13 @@ export default function resetNodeTaskFactory( configFile, homeDir, generateEnvs, - getPlatformProfiles, + getConfigProfiles, ) { + function selectPlatformProfiles(config, options) { + return getConfigProfiles(config, options) + .filter((profile) => profile.startsWith('platform')); + } + /** * Remove path but ignore permission issues to avoid failing reset on root-owned directories. * @@ -73,7 +78,7 @@ export default function resetNodeTaskFactory( skip: (ctx) => ctx.isForce, task: async (ctx) => { const profiles = ctx.isPlatformOnlyReset - ? getPlatformProfiles(config, { includeAll: true }) + ? selectPlatformProfiles(config, { includeAll: true }) : []; if (await dockerCompose.isNodeRunning( @@ -104,7 +109,7 @@ export default function resetNodeTaskFactory( title: 'Remove platform services and associated data', enabled: (ctx) => ctx.isPlatformOnlyReset, task: async (ctx, task) => { - const profiles = getPlatformProfiles(config, { includeAll: true }); + const profiles = selectPlatformProfiles(config, { includeAll: true }); if (ctx.keepData) { // eslint-disable-next-line no-param-reassign diff --git a/packages/dashmate/src/listr/tasks/startNodeTaskFactory.js b/packages/dashmate/src/listr/tasks/startNodeTaskFactory.js index 9ec4e53f4a4..23b460f0b31 100644 --- a/packages/dashmate/src/listr/tasks/startNodeTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/startNodeTaskFactory.js @@ -19,7 +19,7 @@ const DAPI_PROFILE_SERVICES = { * @param {getConnectionHost} getConnectionHost * @param {ensureFileMountExists} ensureFileMountExists * @param {HomeDir} homeDir - * @param {getPlatformProfiles} getPlatformProfiles + * @param {getConfigProfiles} getConfigProfiles * @return {startNodeTask} */ export default function startNodeTaskFactory( @@ -31,8 +31,13 @@ export default function startNodeTaskFactory( getConnectionHost, ensureFileMountExists, homeDir, - getPlatformProfiles, + getConfigProfiles, ) { + function selectPlatformProfiles(config, options) { + return getConfigProfiles(config, options) + .filter((profile) => profile.startsWith('platform')); + } + /** * @typedef {startNodeTask} * @param {Config} config @@ -91,7 +96,7 @@ export default function startNodeTaskFactory( title: 'Check node is not started', enabled: (ctx) => !ctx.isForce, task: async (ctx) => { - const profiles = ctx.platformOnly ? getPlatformProfiles(config) : []; + const profiles = ctx.platformOnly ? selectPlatformProfiles(config) : []; if (await dockerCompose.isNodeRunning(config, { profiles })) { throw new Error('Running services detected. Please ensure all services are stopped for this config before starting'); @@ -146,7 +151,7 @@ export default function startNodeTaskFactory( config.get('core.masternode.operator.privateKey', true); } - const profiles = ctx.platformOnly ? getPlatformProfiles(config) : []; + const profiles = ctx.platformOnly ? selectPlatformProfiles(config) : []; await dockerCompose.up(config, { profiles }); }, diff --git a/packages/dashmate/src/listr/tasks/stopNodeTaskFactory.js b/packages/dashmate/src/listr/tasks/stopNodeTaskFactory.js index 5c0c47cc08f..9fdf39c6c53 100644 --- a/packages/dashmate/src/listr/tasks/stopNodeTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/stopNodeTaskFactory.js @@ -7,15 +7,20 @@ import waitForDKGWindowPass from '../../core/quorum/waitForDKGWindowPass.js'; * @param {DockerCompose} dockerCompose * @param {createRpcClient} createRpcClient * @param {getConnectionHost} getConnectionHost - * @param {getPlatformProfiles} getPlatformProfiles + * @param {getConfigProfiles} getConfigProfiles * @return {stopNodeTask} */ export default function stopNodeTaskFactory( dockerCompose, createRpcClient, getConnectionHost, - getPlatformProfiles, + getConfigProfiles, ) { + function selectPlatformProfiles(config, options) { + return getConfigProfiles(config, options) + .filter((profile) => profile.startsWith('platform')); + } + /** * Stop node * @typedef stopNodeTask @@ -30,7 +35,7 @@ export default function stopNodeTaskFactory( skip: (ctx) => ctx.isForce, task: async (ctx) => { const profiles = ctx.platformOnly - ? getPlatformProfiles(config, { includeAll: true }) + ? selectPlatformProfiles(config, { includeAll: true }) : []; if (!await dockerCompose.isNodeRunning(config, { profiles })) { @@ -72,7 +77,7 @@ export default function stopNodeTaskFactory( title: `Stopping ${config.getName()} node`, task: async (ctx) => { const profiles = ctx.platformOnly - ? getPlatformProfiles(config, { includeAll: true }) + ? selectPlatformProfiles(config, { includeAll: true }) : []; await dockerCompose.stop(config, { profiles });