Akka文档区分了验证错误和失败。但是,虽然有一整章是关于失败的,但我没有看到太多关于验证错误的内容。
验证错误意味着发送给参与者的命令数据无效,这应该被建模为参与者协议的一部分,而不是让参与者抛出异常。
——https://doc.akka.io/docs/akka/current/typed/fault-tolerance.html
我搜索了一下,但仍然没有找到关于那个主题的很多信息。此时,我看到两个选项:
选项1,类型层次:
我们可以使用类型层次结构在命令、成功答案和错误之间建立一个类型结构:
class MyCommand {
ActorRef<MyCommandAnswer> replyTo;
// ..
}
interface MyCommandAnswer { }
class MyCommandSuccess implements MyCommandAnswer { /* .. */ }
class MyCommandError implements MyCommandAnswer { /* .. */ }
👍好处是命令和两种可能的答案之间有很强的关系。
👎然而,这太啰嗦了,答案的类型也不明显(我们必须阅读类型层次结构来发现可能的类型)。此外,必须使用instanceof
或类似访问者的模式(这不会减少冗长)来处理答案
选项2,一个类似
的Either
Scala有一个Either
类型,可以是Left
或Right
。Left
端通常是错误,而Right
端则是成功。也有Try
使用相同的模式。
表示两种可能类型之一的值(不联合并)。Either的实例是scala.util.Left或scala.util.Right的实例。
——https://www.scala-lang.org/api/2.13.3/scala/util/Either.html
我们可以创建一个类似的类型,它将被actor返回。
abstract class Either<L, R> {
public static <L> Either<L, ?> left(L error) {
return new Left(error);
}
public static <R> Either<?, R> right(R value) {
return new Right(value);
}
public abstract boolean isLeft();
public abstract boolean isRight();
public abstract <O> Either<L, O> map(Function<R, O> mapping);
public abstract <O> O orElse(Supplier<O> other);
// ...
}
class MyCommand {
ActorRef<Either<MyCommandError, MyCommandSuccess>> replyTo;
// ..
}
👍好处是我们总是知道可能的答案,并且Either
类可以在所有参与者之间重用。这使得在项目中更容易使用。我们可以有许多这种类型的方法来处理这两种情况,而不必为所有命令复制代码。
👎这段受功能启发的代码可能对每个人来说都不自然。
我的偏好显然是Either
类型。但是我想知道社区里关于这个话题的知识。
那么,我的问题是,你是如何处理akka类型和Java的错误的?
感谢StatusReply
旨在作为参与者协议的成功/错误响应的良好编码,参见docs: https://doc.akka.io/docs/akka/current/typed/interaction-patterns.html#generic-response-wrapper