From 2270c80ac94f5c3117ecf1f6d853e08ef5524fb0 Mon Sep 17 00:00:00 2001 From: Antranig Basman Date: Fri, 5 Apr 2019 00:58:25 +0100 Subject: [PATCH] GPII-3759: Bodge quality fix to allow language solution to have its settings applied last --- .../lifecycleManager/src/LifecycleManager.js | 80 +++++++++++++------ testData/solutions/win32.json5 | 1 + 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/gpii/node_modules/lifecycleManager/src/LifecycleManager.js b/gpii/node_modules/lifecycleManager/src/LifecycleManager.js index 44ee7b2bd..6b24e64a4 100644 --- a/gpii/node_modules/lifecycleManager/src/LifecycleManager.js +++ b/gpii/node_modules/lifecycleManager/src/LifecycleManager.js @@ -1181,6 +1181,30 @@ var gpii = fluid.registerNamespace("gpii"); return restorePromise; }; + /** Iterates through a block of lifecycleInstructions in an order induced by their "settingsApplicationPriority" + * fields. This ensures that solutions' settingsHandlers are invoked in an appropriate order for the terms of + * GPII-3759. + * @param {Object} lifecycleInstructions - The `lifecycleInstructions` member of a configuration's worth of payloads + * @param {Object} solutionsRegistryEntries - The `solutionsRegistryEntries' block of the final payload + * @param {Function} solutionFunc - A function with signature (solution, solutionId) that will be executed + * for each solution in the sorted payload + */ + gpii.lifecycleManager.lifecycleInstructionsByPriority = function (lifecycleInstructions, solutionsRegistryEntries, + solutionFunc) { + var priorityRecords = []; + fluid.each(lifecycleInstructions, function (solution, solutionId) { + priorityRecords.push({ + priority: fluid.parsePriority(solution.settingsApplicationPriority, 0, false, "solutions registry entry"), + namespace: solutionId + }); + }); + fluid.sortByPriority(priorityRecords); + priorityRecords.forEach(function (sortedRecord) { + var solutionId = sortedRecord.namespace; + solutionFunc(lifecycleInstructions[solutionId], solutionId); + }); + }; + /** * Apply lifecycle instructions to the local computer. * @param {Component} that - A instance of gpii.lifecycleManager. @@ -1199,14 +1223,16 @@ var gpii = fluid.registerNamespace("gpii"); var appliedSolutions = userSession.model.appliedSolutions; var promises = []; - fluid.each(lifecycleInstructions, function (solution, solutionId) { - var sol = fluid.copy(solution); - if (appliedSolutions[solutionId]) { - // merge already applied settings with the updates - sol = fluid.extend(true, {}, appliedSolutions[solutionId], sol); + gpii.lifecycleManager.lifecycleInstructionsByPriority(lifecycleInstructions, + finalPayload.solutionsRegistryEntries, function (solution, solutionId) { + var sol = fluid.copy(solution); + if (appliedSolutions[solutionId]) { + // merge already applied settings with the updates + sol = fluid.extend(true, {}, appliedSolutions[solutionId], sol); + } + promises.push(that.applySolution(solutionId, sol, userSession, [ "update" ], "update")); } - promises.push(that.applySolution(solutionId, sol, userSession, [ "update" ], "update")); - }); + ); return fluid.promise.sequence(promises); }; @@ -1230,25 +1256,27 @@ var gpii = fluid.registerNamespace("gpii"); // When "stop" is called this payload will be used to restore the settings back to their // original state. var tasks = []; - fluid.each(lifecycleInstructions, function (solution, solutionId) { - tasks.push(function () { - if (!fluid.isDestroyed(that)) { // See above comment for GPII-580 - // check the current state of the solution to decide whether we should run the - // "update", "start" or "stop" directive - return that.getSolutionRunningState(solutionId, solution, userSession); - } - }); - tasks.push(function () { - if (!fluid.isDestroyed(that)) { // See above comment for GPII-580 - // if solution is already running, call "update" directive - else use "start" directive - var isRunning = userSession.model.runningOnLogin[solutionId]; - var actions = gpii.lifecycleManager.calculateLifecycleActions(isRunning, solution.active); - - // build structure for returned values (for later reset) - return that.applySolution(solutionId, solution, userSession, actions, "start"); - } - }); - }); + gpii.lifecycleManager.lifecycleInstructionsByPriority(lifecycleInstructions, + finalPayload.solutionsRegistryEntries, function (solution, solutionId) { + tasks.push(function () { + if (!fluid.isDestroyed(that)) { // See above comment for GPII-580 + // check the current state of the solution to decide whether we should run the + // "update", "start" or "stop" directive + return that.getSolutionRunningState(solutionId, solution, userSession); + } + }); + tasks.push(function () { + if (!fluid.isDestroyed(that)) { // See above comment for GPII-580 + // if solution is already running, call "update" directive - else use "start" directive + var isRunning = userSession.model.runningOnLogin[solutionId]; + var actions = gpii.lifecycleManager.calculateLifecycleActions(isRunning, solution.active); + + // build structure for returned values (for later reset) + return that.applySolution(solutionId, solution, userSession, actions, "start"); + } + }); + } + ); // Note that these promises are only sequenced for their side-effects (the ones on user session state within applySolution and on the system at large // via the settings handlers) return fluid.promise.sequence(tasks); diff --git a/testData/solutions/win32.json5 b/testData/solutions/win32.json5 index 218cdb89b..db47e930a 100644 --- a/testData/solutions/win32.json5 +++ b/testData/solutions/win32.json5 @@ -6549,6 +6549,7 @@ } ] }, + "settingsApplicationPriority": "last", "settingsHandlers": { "configure1": { "type": "gpii.windows.registrySettingsHandler",