Я выполняю упражнение по курсу «Реактивное программирование», которое требует, чтобы студенты украсили типизированное поведение актера для поддержки необработанного сообщения. Это программа, которую я написал до сих пор.
package protocols
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl._
import scala.reflect.ClassTag
object SelectiveReceive {
def apply[T: ClassTag](bufferCapacity: Int, initialBehavior: Behavior[T]): Behavior[T] =
Behaviors.withStash(bufferCapacity) { buffer =>
Behaviors.setup[T] { ctx =>
intercept(bufferCapacity, buffer, initialBehavior)
}
}
/**
* @return A behavior that interprets the incoming messages with the supplied `started`
* behavior to compute the next behavior. If the message has been unhandled, it
* is stashed in the `buffer`. If the message has been handled, the previously
* stashed messages are also sent to the next behavior.
*
* @param bufferSize Capacity of the StashBuffer
* @param buffer Buffer to stash unhandled messages to
* @param started Behavior to decorate. Must be a valid “initial” behavior.
* @tparam T Type of messages
*
* Hints: Use [[Behavior.interpretMessage]] to compute the next behavior.
* Use [[Behavior.isUnhandled]] to know if the message was unhandled by the behavior.
* Use [[Behavior.canonicalize]] to make the next behavior applicable to the
* `unstashAll` operation of the `StashBuffer` (otherwise, an
* `IllegalArgumentException` will be thrown by the actor system).
*/
private def intercept[T: ClassTag](bufferSize: Int, buffer: StashBuffer[T], started: Behavior[T]): Behavior[T] =
Behaviors.receive { case (ctx, message) =>
// If the next behavior does not handle the incoming `message`, stash the `message` and
// return an unchanged behavior. Otherwise, return a behavior resulting from
// “unstash-ing” all the stashed messages to the next behavior wrapped in an `SelectiveReceive`
// interceptor.
val nextBehavior = Behavior.interpretMessage(started, ctx, message)
if (Behavior.isUnhandled(nextBehavior)) {
if (buffer.size == bufferSize) {
throw new StashOverflowException("stash overflow")
} else {
buffer.stash(message)
Behaviors.same
}
} else {
//SelectiveReceive(bufferSize, buffer.unstashAll(Behavior.canonicalize(nextBehavior, started, ctx)))
val current = intercept(bufferSize, buffer, started)
val next = SelectiveReceive(bufferSize, nextBehavior)
val canonicalizeNextBehavior = Behavior.canonicalize(next, current, ctx)
SelectiveReceive(bufferSize, buffer.unstashAll(canonicalizeNextBehavior))
}
}
}
В подсказке они сказали, что используют метод canonicalize
, чтобы избежать исключения. Но я попробовал несколько способов использовать эту функцию в коде и не могу найти способ избежать этого. Итак, я хочу спросить, каков случай использования канонизированного метода поведения? И как использовать этот метод в приведенном выше коде.