Как использовать Behaviors.canonicalize в Акке - PullRequest
0 голосов
/ 09 февраля 2020

Я выполняю упражнение по курсу «Реактивное программирование», которое требует, чтобы студенты украсили типизированное поведение актера для поддержки необработанного сообщения. Это программа, которую я написал до сих пор.

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, чтобы избежать исключения. Но я попробовал несколько способов использовать эту функцию в коде и не могу найти способ избежать этого. Итак, я хочу спросить, каков случай использования канонизированного метода поведения? И как использовать этот метод в приведенном выше коде.

...