This article is for Data Center. Visit Cloud
Run all effectors by schedule
This script can be used in ScriptRunner to run effectors by schedule. See ScriptRunner Jobs.
Run effectors
/* * This script allows to start specified or all effectors for chosen structure. * It will ping started effector process until it finishes. * It will NOT acknowledge the process at the end so the process will be available in the structure status bar process list. */ // params def structureId = 14 // target structure ID def effectorIds = [2, 1] // effector IDs to run or empty to run all effectors in structure def processCheckInterval = 1000; // milliseconds // Structure imports import com.almworks.jira.structure.api.StructurePluginHelper import com.almworks.jira.structure.api.auth.StructureAuth import com.almworks.jira.structure.api.effector.instance.EffectorInstanceManager import com.almworks.jira.structure.api.effector.process.EffectorProcessManager import com.almworks.jira.structure.api.error.StructureException import com.almworks.jira.structure.api.forest.ForestSpec import com.almworks.jira.structure.api.forest.ForestService import com.almworks.jira.structure.api.forest.ForestSource import com.almworks.jira.structure.api.StructureComponents import com.almworks.jira.structure.api.item.CoreIdentities import com.almworks.jira.structure.api.permissions.PermissionLevel import com.almworks.jira.structure.api.process.ProcessHandleManager import com.almworks.jira.structure.api.process.ProcessStatus import com.almworks.jira.structure.api.row.RowManager import com.almworks.jira.structure.api.structure.StructureManager import com.almworks.jira.structure.api.util.StructureUtil // ScriptRunner imports import com.onresolve.scriptrunner.runner.customisers.PluginModule import com.onresolve.scriptrunner.runner.customisers.WithPlugin import com.onresolve.scriptrunner.runner.ScriptRunnerImpl // Atlassian import (might be available without the import in some instances, but better safe than sorry) import com.atlassian.jira.component.ComponentAccessor import static java.util.Arrays.asList // switch to plugin @Grab(group = 'com.almworks.jira.structure', module = 'structure-api', version = '*') @WithPlugin('com.almworks.jira.structure') class EffectorRunner { StructureComponents SC = ScriptRunnerImpl.getPluginComponent(StructureComponents) ForestService FS = SC.getForestService() RowManager RM = SC.getRowManager() StructureManager SM = SC.getStructureManager() ProcessHandleManager PHM = SC.getProcessHandleManager() // next components are not available from StructureComponents in Structure 6.x, but who knows :) EffectorInstanceManager EIM = ScriptRunnerImpl.getPluginComponent(EffectorInstanceManager) EffectorProcessManager EPM = ScriptRunnerImpl.getPluginComponent(EffectorProcessManager) def user = StructureAuth.getUser() ForestSource source def structureId def effectorIds def log def processCheckInterval EffectorRunner(def log, def structureId, def effectorIds, def processCheckInterval) { this.structureId = structureId this.effectorIds = effectorIds this.log = log this.processCheckInterval = processCheckInterval try { // check for structure existence and permissions SM.getStructure(structureId, PermissionLevel.VIEW) source = FS.getForestSource(ForestSpec.skeleton(structureId)) } catch (StructureException ex) { log.error("Cant create forest source for structure id=${structureId} for user ${user}.\n${trimStackTrace(ex)}") } } def run() { def caption = "See logs for results." if (source == null) return caption def structureName = FS.getDisplayName(ForestSpec.skeleton(structureId)) def effectors = getEffectorInstances() if (effectors.isEmpty()) { log.warn("No effectors were found.") return caption } if (!effectorIds.isEmpty() && effectorIds.size != effectors.size()) { return caption } log.warn("Starting to execute effectors for structure '${structureName}' for user ${user}") // print effectors list to run effectors.each {ef -> log.warn("\teffector: id=${ef.getId()} ${ef.getModuleKey()} ${ef.getParameters()}") } // start effectors process def processId = runEffectors(effectors) if (processId == null) return caption log.warn("Effector process id=${processId} started.") // await process finish if (awaitFinish(processId)) { // print produced effect records and errors printResults(processId) log.warn("Done.") } else { log.error("Failed.") } return caption } def printResults(def processId) { def records = EPM.getEffectRecords(processId) if (records.isEmpty()) { log.warn("No effect records were produced.") } else if (records.size() > 100) { // just not to spam log.warn("There are ${records.size()} applied effects.") } else { records.each {record -> // choose right log level for errors and applied effects if (record.isError()) { log.error(StructureUtil.getTextInCurrentUserLocale(record.getEffectMessage())) } else { log.warn(StructureUtil.getTextInCurrentUserLocale(record.getEffectMessage())) } } } } // This is blocking method will run until effectors process finish. def awaitFinish(def processId) { def handleId try { def process = EPM.getProcess(processId) handleId = process.getProcessHandleId() } catch (StructureException ex) { log.error("Failed to get process info\n.${trimStackTrace(ex)}") return false } def info = PHM.getInfo(handleId) if (info == null) return false def prevProgress = 0 while (info != null && info.getStatus() != ProcessStatus.FINISHED && sleep()) { info = PHM.getInfo(handleId) if (info.percentComplete != prevProgress) { def process = EPM.getProcess(processId) log.warn("\tprocess complete ${info.getPercentComplete()}%. Status ${process.getStatus()}") prevProgress = info.getPercentComplete() } } return info != null } def sleep() { try { Thread.sleep(processCheckInterval) return true } catch (InterruptedException ex) { log.warn(${trimStackTrace(ex)}) Thread.currentThread().interrupt() return false } return true } def runEffectors(def effectors) { try { return EPM.startProcess(effectors, structureId, false) } catch (StructureException ex) { log.error("Effector process validation failed.\n${trimStackTrace(ex)}") return null } } def getEffectorInstances() { def ids = effectorIds.isEmpty() ? findEffectors() : effectorIds def instances = [] ids.each {id -> try { instances.add(EIM.getEffectorInstance(id)) } catch (StructureException ex) { log.error("Unable to find effector with id=${id}.\n${trimStackTrace(ex)}") } } return instances } def findEffectors() { def effectorIds = [] source.getLatest().getForest().forEach {row -> def rowId = row.left() def itemId = RM.getRow(rowId).getItemId() if (CoreIdentities.isEffector(itemId)) { effectorIds.add(itemId.getLongId()) } } return effectorIds } def trimStackTrace(Exception e) { return asList(e.stackTrace).subList(0, 20).join('\n ') + '\n ...' } } new EffectorRunner(log, structureId, effectorIds, processCheckInterval).run()