in addons/addon-base-workflow/packages/workflow-engine/lib/step/step-loop.js [161:239]
async processDecisionQueue() {
if (this.decisionQueue.length === 0) throw new Error('No decisions in the step Loop to process.');
const decision = this.decisionQueue[0];
// A helper function that inserts a call decision if we have "thenCall", otherwise,
// it returns a pass decision after calling onPass
const thenCallOrPass = async () => {
this.decisionQueue.shift(); // remove the first element
if (decision.thenCall) {
this.decisionQueue.unshift(new CallDecision(decision.thenCall));
return this.loopDecision();
}
await this.callOnPass();
return this.passDecision();
};
// A helper function that calls the "check" function
const callCheckFn = async () => {
const impl = this.stepImplementation;
await this.safeFireEvent('stepLoopMethodCall', decision.check.methodName);
const result = await decision.check.invoke(impl);
if (!_.isBoolean(result)) throw new Error(decision.checkNotBooleanMessage());
return result;
};
// A helper function that inserts a call decision for the "otherwise" function if it exists,
// otherwise, it throws an exceed max attempts error
const otherwiseOrError = async () => {
this.decisionQueue.shift(); // remove the first element
if (decision.otherwise) {
this.decisionQueue.unshift(new CallDecision(decision.otherwise));
return this.loopDecision();
}
throw new Error(decision.maxReachedMessage());
};
// The logic for processing the decision queue
if (WaitDecision.is(decision)) {
decision.decrement();
if (_.isNil(decision.max)) return thenCallOrPass();
const isTrue = await callCheckFn();
if (isTrue) return thenCallOrPass();
if (decision.reachedMax()) return otherwiseOrError();
return this.waitDecision(decision.seconds);
}
if (PauseDecision.is(decision)) {
decision.decrement();
if (_.isNil(decision.max)) return thenCallOrPass();
const isTrue = await callCheckFn();
if (isTrue) {
await this.safeFireEvent('stepLoopStepResuming', 'resume condition met');
return thenCallOrPass();
}
if (decision.reachedMax()) {
await this.safeFireEvent('stepLoopStepMaxPauseReached');
return otherwiseOrError();
}
return this.pauseDecision(decision.seconds);
}
if (CallDecision.is(decision)) {
this.decisionQueue.shift(); // remove the first element
await this.safeFireEvent('stepLoopMethodCall', decision.methodName);
const impl = this.stepImplementation;
const stepDecision = await decision.thenCall.invoke(impl);
return this.processStepDecision(stepDecision);
}
if (GoToDecision.is(decision)) {
this.decisionQueue.shift(); // remove the first element
await this.safeFireEvent('stepLoopRequestingGoTo', decision.stepIndex);
// Call "OnPass" on current step before returning GoTo and resuming workflow from other step
await this.callOnPass();
return this.goToDecision(decision.stepIndex);
}
throw new Error(`The step loop decision queue contains an unsupported decision "${JSON.stringify(decision)}".`);
}