Типобезопасные состояния с исчерпывающим сопоставлением с образцом в Akka Typed

Я начал работать с 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. Я просто не могу заставить типы работать для реализации такой функции.


person Arne Claassen    schedule 15.05.2019    source источник


Ответы (1)


Одна из идей состоит в том, чтобы выполнить начальное сопоставление подмножества команд, зависящих от состояния. Что-то типа:

def accumulating: Behavior[Command] = 
  Behaviors.receive { 
    case acc: Accumulating => 
      acc match {
        //... complete for the message subtype or compiler fails...
      }
    case _ => 
      // other state subtypes are 
      Behaviors.unhandled
person johanandren    schedule 27.05.2019
comment
Что удивительно близко к тому, как раньше выглядели мои нетипизированные актеры. Я надеялся на синтаксический сахар, который сделает его более явным, чем шаблон кодирования. - person Arne Claassen; 27.05.2019
comment
Я предполагаю, что вы могли бы добиться чего-то вроде предложенной вами подписи `V ‹: T`, используя тег класса, но нет ничего готового, что делает это. - person johanandren; 28.05.2019