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
}
}
}
}