Я начал работать с Akka Typed, чтобы получить исчерпывающее сопоставление шаблонов с моим поведением, что отлично подходит для внешнего контракта каждого актера. Однако, если актор является конечным автоматом, скорее всего, разные состояния имеют команды, специфичные для состояния.
Я могу скрыть команды, зависящие от состояния, как частные члены общей команды, например:
sealed trait Command
final case class Add(id: Int) extends Command
private final case object AccumulationTimeout extends Command
private final case object Ack extends Command
Однако два моих состояния accumulating
и emitting
должны обрабатывать команды друг друга. Я мог бы использовать .receivePartial
или включить все
case _ => Behaviors.unhandled
В обоих случаях я потерял исчерпывающее сопоставление с образцом, чтобы убедиться, что я правильно обрабатываю свое состояние.
Я могу дополнительно уточнить команды как таковые:
sealed trait Command
sealed trait Accumulating extends Command
private final case object AccumulationTimeout extends Accumulating
sealed trait Emitting extends Command
private final case object Ack extends Emitting
final case class Add(id: Int) extends Accumulating with Emitting
С помощью этого я могу определить Behavior[Accumulating]
и Behavior[Emitting]
, которые оба являются Behavior[Command]
, но загвоздка в том, что ни одно из поведений не может перейти к другому, поскольку оба должны возвращать свой собственный тип.
Я пробовал различные перестановки .widen
и .narrow
безрезультатно и понял, что мне действительно нужен способ определить Behavior
как
def receiveMessage[T, V <: T](handler: V => Behavior[T]): Behavior[T] = ???
где handler
даст мне исчерпывающую проверку узкого типа V
, а для любого сообщения T
вне V
вернет Behaviors.unhandled
. Я просто не могу заставить типы работать для реализации такой функции.