1.Command,Event,State
在这里,我们先介绍一下Command,Event,State的概念。
Command,Event,State的类型由PersistentEntity的实现类给出,赋值方法如下:
import com.lightbend.lagom.scaladsl.persistence.PersistentEntity
final class Post1 extends PersistentEntity {
override type Command = BlogCommand
override type Event = BlogEvent
override type State = BlogState
override def initialState: BlogState = BlogState.empty
override def behavior: Behavior = Actions()
}
每一个更改和查询entity的命令,我们称之为Command,如果Command合理并无任何问题,则会产生一个event,event会以追加的形式持久化到数据库,使用的时候会重播所有的event,得到最终的state。也可以把重播的部分event以snapshot的形式缓存下来,这样下次重播的时候会快很多。
2.entityId
在lagom中,所有持久化类都要继承自PersistentEntity ,每一个持久化类的每一个实例都要有一个唯一标识符,可以通过
entityId方法获取。Service的实现可以通过唯一标识来定位一个持久化类,如下
pser.refFor[Entity](entityId).ask(command)
其中:pser是PersistentEntityRegistry类型,Entity是PersistentEntity的实现类,command由实现类指定。
3.InitialState
PersistentEntity的initialState是抽象方法,具体的实现一定要实现它,当新的PersistentEntity实例创建的时候,会调用该方法,作物初始的值
4.Command Handlers
这个函数处理commands请求,使用onCommand通过Actions注册
// Command handlers are invoked for incoming messages (commands).
// A command handler must "return" the events to be persisted (if any).
Actions()
.onCommand[AddPost, AddPostDone] {
case (AddPost(content), ctx, state) =>
ctx.thenPersist(PostAdded(entityId, content)) { evt =>
// After persist is done additional side effects can be performed
ctx.reply(AddPostDone(entityId))
}
}
onCommand需要一个Persist对象作为返回值,CommandContext的如下3种方法可以获取到Command的返回值
thenPersist
将会持久化一个eventthenPersistAll
将会持久化多个event,如果任何一个event持久化失败,则全部都不会被持久化done
没有任何event被持久化
当event被持久化成功,会调用 after persist 函数。
onReadOnlyCommand 函数用于只读的command请求,你不需要返回任何对象
5.Event Handlers
当一个event被成功的持久化,通过调用onEvent来更新当前的状态
// Event handlers are used both when persisting new events and when replaying
// events.
.onEvent {
case (PostAdded(postId, content), state) =>
BlogState(Some(content), published = false)
}
6.Replies
每一个command 必须实现PersistentEntity.ReplyType interface,如下
final case class AddPost(content: PostContent) extends BlogCommand with ReplyType[AddPostDone]
你调用reply 方法通过 传给command函数context参数。
你可以使用ctx.invalidCommand 拒绝一个无效的command,它将使发送方的future失败通过 PersistentEntity.InvalidCommandException 异常
如果PersistentEntity 收到一个不知道类型的command,它将使发送方的future失败通过PersistentEntity.UnhandledCommandException 异常
如果你不调用reply方法,会产生akka.pattern.AskTimeoutException 异常
7.Changing Behavior
override def behavior: Behavior = {
case state if state.isEmpty => initial
case state if !state.isEmpty => postAdded
}