【发布时间】:2021-04-08 06:38:52
【问题描述】:
我们正在构建一个基于 Akka-Typed 的事件源系统。我们很快陷入了这样一种情况,即我们的状态需要许多参数作为隐式参数传递。
样式指南上有一个使用封闭类的解决方案; https://doc.akka.io/docs/akka/current/typed/style-guide.html#passing-around-too-many-parameters.
但是,这是针对“简单”行为,而不是针对 EventSourcedBehaviors。这种使用产生行为的封闭类的技术不适用于事件源行为,因为事件源行为由一个命令处理程序和一个事件处理程序组成。
在我们的例子中,我们有一个State trait,它定义了一种接收命令的方法和另一种处理事件的方法。如果我们应用封闭类技术,我们必须为所有状态创建匿名类,但这些不能被序列化。
object SampleEventSourced {
trait State extends CborSerializable {
def execute(cmd: Command): ReplyEffect
def apply(evt: Event): State
}
def apply(
persistenceId: PersistenceId,
config: Config,
): Behavior[Command] = {
EventSourcedBehavior
.withEnforcedReplies[Command, Event, State](
persistenceId,
new SampleEventSourced(config).empty(),
(state, cmd) => state.execute(cmd),
(state, evt) => state.apply(evt)
)// ...
}
}
class SampleEventSourced private(config: Config) {
import SampleEventSourced._
private def empty(): State = new State {
override def execute(cmd: Command): ReplyEffect = cmd match {
// ..
}
override def apply(evt: Event): State = evt match {
// ..
}
}
java.lang.IllegalArgumentException:空状态 [org.acme.SampleEventSourced$$anon$1@36d7d2fe] 不可序列化。
一种解决方案是在每个“状态”方法中复制事件源行为的创建。但这会产生很多重复。
object SampleEventSourced {
def apply(
persistenceId: PersistenceId,
config: Config,
): Behavior[Command] = new SampleEventSourced(config).empty()
}
class SampleEventSourced private(config: Config) {
import SampleEventSourced._
private def empty(): Behavior[Command] = EventSourcedBehavior
.withEnforcedReplies[Command, Event, State](
persistenceId,
new State(),
(state, cmd) => state.execute(cmd),
(state, evt) => state.apply(evt)
)// ...
}
另一种方法是创建State 的具体子类,但我们必须在所有这些状态之间传递参数。
object SampleEventSourced {
class EmptyState extends State(config:Config, otherUselessParameter:Any) {
// ...
override def apply(evt: Event): evt match {
case _ => new OtherState(config, otherUselessParameter)
}
}
class OtherState extends State(config:Config, veryImportantParameter:Any) {
// ..
}
}
将这些状态类放在封闭类中是行不通的,因为这些非静态内部类无法反序列化。
那么,对于这种情况,你的解决方案是什么,你如何处理需要许多参数的状态的 EventSourcedBehavior?
【问题讨论】:
标签: scala akka event-sourcing