Типизированные состояния с исчерпывающим сопоставлением с образцом в типизированном Akka - PullRequest
1 голос
/ 15 мая 2019

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

1 Ответ

0 голосов
/ 27 мая 2019

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

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
...