@atomist/sdm
Version:
Atomist Software Delivery Machine SDK
152 lines • 7.04 kB
JavaScript
;
/*
* Copyright © 2020 Atomist, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleSdmGoalSetEvent = exports.Queue = exports.DefaultQueueOptions = void 0;
const graphQL_1 = require("@atomist/automation-client/lib/graph/graphQL");
const HandlerResult_1 = require("@atomist/automation-client/lib/HandlerResult");
const GraphClient_1 = require("@atomist/automation-client/lib/spi/graph/GraphClient");
const logger_1 = require("@atomist/automation-client/lib/util/logger");
const _ = require("lodash");
const storeGoals_1 = require("../../../api-helper/goal/storeGoals");
const logInterpreters_1 = require("../../../api-helper/log/logInterpreters");
const types_1 = require("../../../typings/types");
const commonPushTests_1 = require("../../mapping/support/commonPushTests");
const GoalNameGenerator_1 = require("../GoalNameGenerator");
const GoalWithFulfillment_1 = require("../GoalWithFulfillment");
const environment_1 = require("../support/environment");
exports.DefaultQueueOptions = {
concurrent: 2,
fetch: 10,
};
/**
* Goal to queue current goal set until it is the first in the list and can execute
*/
class Queue extends GoalWithFulfillment_1.FulfillableGoal {
constructor(options = exports.DefaultQueueOptions, ...dependsOn) {
super(Object.assign({}, GoalWithFulfillment_1.getGoalDefinitionFrom(options, GoalNameGenerator_1.DefaultGoalNameGenerator.generateName("queue"), QueueDefinition)), ...dependsOn);
this.options = options;
}
register(sdm) {
super.register(sdm);
const optsToUse = Object.assign(Object.assign({}, exports.DefaultQueueOptions), this.options);
this.addFulfillment({
name: `queue-${this.definition.uniqueName}`,
pushTest: commonPushTests_1.AnyPush,
goalExecutor: async (gi) => {
const { context, configuration, goalEvent, progressLog } = gi;
const goalSets = await context.graphClient.query({
name: "InProcessSdmGoalSets",
variables: {
fetch: optsToUse.fetch + optsToUse.concurrent,
offset: 0,
registration: [configuration.name],
},
options: GraphClient_1.QueryNoCacheOptions,
});
if (!!goalSets && !!goalSets.SdmGoalSet) {
const ix = goalSets.SdmGoalSet.findIndex(gs => gs.goalSetId === goalEvent.goalSetId);
if (ix >= 0) {
progressLog.write(`Goal set currently at position ${ix + 1} in queue`);
if (ix < optsToUse.concurrent) {
progressLog.write(`Goal set can start immediately`);
return {
state: types_1.SdmGoalState.success,
};
}
}
else {
progressLog.write(`Goal set not currently pending`);
}
}
return {
state: types_1.SdmGoalState.in_process,
};
},
logInterpreter: logInterpreters_1.LogSuppressor,
});
sdm.addEvent({
name: `OnAnySdmGoalSet`,
description: `Handle queuing for goal ${this.definition.uniqueName}`,
subscription: graphQL_1.subscription({
name: "OnAnySdmGoalSet",
variables: {
registration: [sdm.configuration.name],
},
}),
listener: handleSdmGoalSetEvent(optsToUse, this.definition, sdm.configuration),
});
}
}
exports.Queue = Queue;
const QueueDefinition = {
uniqueName: "queue",
displayName: "queue goals",
environment: environment_1.IndependentOfEnvironment,
workingDescription: "Queued",
completedDescription: "Started goals",
failedDescription: "Failed to queue goals",
};
function handleSdmGoalSetEvent(options, definition, configuration) {
return async (e, ctx) => {
const optsToUse = Object.assign(Object.assign({}, exports.DefaultQueueOptions), options);
const goalSets = await ctx.graphClient.query({
name: "InProcessSdmGoalSets",
variables: {
fetch: optsToUse.fetch + optsToUse.concurrent,
offset: 0,
registration: [configuration.name],
},
options: GraphClient_1.QueryNoCacheOptions,
});
if (goalSets && goalSets.SdmGoalSet && goalSets.SdmGoalSet.length > 0) {
await startGoals(goalSets, optsToUse, definition, ctx);
// await updateGoals(goalSets, optsToUse, details, ctx);
}
return HandlerResult_1.Success;
};
}
exports.handleSdmGoalSetEvent = handleSdmGoalSetEvent;
async function loadQueueGoals(goalsSets, definition, ctx) {
return (await ctx.graphClient.query({
name: "SdmGoalsByGoalSetIdAndUniqueName",
variables: {
goalSetId: goalsSets.map(gs => gs.goalSetId),
uniqueName: [definition.uniqueName],
},
options: GraphClient_1.QueryNoCacheOptions,
})).SdmGoal || [];
}
async function startGoals(goalSets, options, definition, ctx) {
// Update goal sets that are allowed to start
const goalSetsToStart = goalSets.SdmGoalSet.slice(0, options.concurrent)
.filter(gs => gs.goals.some(g => g.uniqueName === definition.uniqueName));
if (goalSetsToStart.length > 0) {
logger_1.logger.debug(`Following goal sets are ready to start: '${goalSetsToStart.map(gs => gs.goalSetId).join(", ")}'`);
const queueGoals = await loadQueueGoals(goalSetsToStart, definition, ctx);
for (const goalSetToStart of goalSetsToStart) {
const queueGoal = _.maxBy(queueGoals.filter(g => g.goalSetId === goalSetToStart.goalSetId), "ts");
logger_1.logger.debug(`Updating goal '${definition.uniqueName}' of goal set '${queueGoal.goalSetId}' to 'success'`);
if (queueGoal.state === types_1.SdmGoalState.in_process) {
await storeGoals_1.updateGoal(ctx, queueGoal, {
state: types_1.SdmGoalState.success,
description: definition.completedDescription,
});
}
}
}
}
//# sourceMappingURL=Queue.js.map