UNPKG

@atomist/sdm

Version:

Atomist Software Delivery Machine SDK

152 lines 7.04 kB
"use strict"; /* * 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