private def handleCompletionMessage()

in core/controller/src/main/scala/org/apache/openwhisk/core/loadBalancer/InvokerSupervision.scala [358:411]


  private def handleCompletionMessage(result: InvocationFinishedResult,
                                      buffer: RingBuffer[InvocationFinishedResult]) = {
    buffer.add(result)

    // If the action is successful, the Invoker is Healthy. We execute additional test actions
    // immediately to clear the RingBuffer as fast as possible.
    // The actions that arrive while the invoker is unhealthy are most likely health actions.
    // It is possible they are normal user actions as well. This can happen if such actions were in the
    // invoker queue or in progress while the invoker's status flipped to Unhealthy.
    if (result == InvocationFinishedResult.Success && stateName == Unhealthy) {
      invokeTestAction()
    }

    // Stay online if the activations was successful.
    // Stay offline if an activeAck is received (a stale activation) but the invoker ceased pinging.
    if ((stateName == Healthy && result == InvocationFinishedResult.Success) || stateName == Offline) {
      stay
    } else {
      val entries = buffer.toList

      // Goto Unhealthy or Unresponsive respectively if there are more errors than accepted in buffer at steady state.
      // Otherwise transition to Healthy on successful activations only.
      if (entries.count(_ == InvocationFinishedResult.SystemError) > InvokerActor.bufferErrorTolerance) {
        // Note: The predicate is false if the ring buffer is still being primed
        // (i.e., the entries.size <=  bufferErrorTolerance).
        gotoIfNotThere(Unhealthy)
      } else if (entries.count(_ == InvocationFinishedResult.Timeout) > InvokerActor.bufferErrorTolerance) {
        // Note: The predicate is false if the ring buffer is still being primed
        // (i.e., the entries.size <=  bufferErrorTolerance).
        gotoIfNotThere(Unresponsive)
      } else {
        result match {
          case InvocationFinishedResult.Success =>
            // Eagerly transition to healthy, at steady state (there aren't sufficient contra-indications) or
            // during priming of the ring buffer. In case of the latter, there is at least one additional test
            // action in flight which can reverse the transition later.
            gotoIfNotThere(Healthy)

          case InvocationFinishedResult.SystemError if (entries.size <= InvokerActor.bufferErrorTolerance) =>
            // The ring buffer is not fully primed yet, stay/goto Unhealthy.
            gotoIfNotThere(Unhealthy)

          case InvocationFinishedResult.Timeout if (entries.size <= InvokerActor.bufferErrorTolerance) =>
            // The ring buffer is not fully primed yet, stay/goto Unresponsive.
            gotoIfNotThere(Unresponsive)

          case _ =>
            // At steady state, the state of the buffer superceded and we hold the current state
            // until enough events have occurred to transition to a new state.
            stay
        }
      }
    }
  }