Akka Typed Behavior.orElse appears not to propagate termination signals

We have some code that receives into its behaviour and uses orElse so that another behaviour’s signal handler can continue handling signals i.e.:

      Behaviors
        .receive[T] {...}
        .orElse(behavior) // handle signals immediately

What we’re seeing is that the signal handling of behavior isn’t called. The specific signal in use here is Terminated.

The API doc for orElse states:

Composes this Behavior with a fallback Behaviorwhich is used when thisBehavior` doesn’t handle the message or signal…

However, I think that in the case of the Terminated signal, this isn’t the case. Looking at the code of Behavior, I see the following:

  def interpretSignal[T](behavior: Behavior[T], ctx: TypedActorContext[T], signal: Signal): Behavior[T] = {
    val result = interpret(behavior, ctx, signal)
    // we need to throw here to allow supervision of deathpact exception
    signal match {
      case Terminated(ref) if result == UnhandledBehavior ⇒ throw DeathPactException(ref)
      case _ ⇒ result
    }
  }

This appears to handle the termination signal especially, as the comment states. However, it also appears that the orElse behavior doesn’t get the opportunity to execute.

I was hoping that the correct API behaviour could be clarified.

Relevant code example: MQTT streaming: SourceQueue backpressure by longshorej · Pull Request #1577 · akka/alpakka · GitHub

Naturally, I’m happy to raise an issue if there is one. Thanks for your guidance.

Good catch, I think that should be changed so the Terminated signal is passed on to all orElse. The DeathPactException might have to be solved elsewhere. Issue please.

Thanks. Issue created: https://github.com/akka/akka/issues/26518