async processDecisionQueue()

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)}".`);
  }