有一些用例如下。
1)createUser
API调用是通过前端进行的。一旦此调用成功,意味着数据成功保存到db,将成功返回到前端。 API合同在前端和后端之间结束。
2)现在后端需要生成并触发CreateUser
事件,该事件将用户创建到第三方应用程序中(为了示例,我们可以说它将createUser创建到外部授权系统中)。这是完全异步和后台类型的过程,其中客户端既不知道它也不等待此API的成功或失败。但是,必须记录对此CreateUser
事件的所有调用以及审核和修复(如果出现故障)失败或成功。
第一种方法是我们为这些异步事件设计基于Future
的异步API(应用的其余部分使用Futures
,async
严重),日志传入事件和结果成功/失败到db。
第二种方法是我们使用Akka并为这些事件设置个体演员(例如CreateUser
就是一个例子)。这可能看起来像
class CreateUserActor extends Actor {
def receive = {
case CreateUserEvent(user, role) =>
val originalSender = sender
val res = Future {
blocking {
//persist CreateUserEvent to db
SomeService.createUser(user, role)
}
}
res onComplete {
case Success(u) => //persist success to db
case Failure(e) => //persist failure to db
}
}
第三种方法使用Akka Persistence,因此可以通过事件源日记功能实现持久的事件。但事件成功或失败的第二个持久性将是手动的(为其编写代码)。虽然第三种方法可能看起来很有希望但它可能不会很好,因为现在我们依靠Akka持久性来持续发生事件,持续成功/失败事件的第二个要求仍然是手动的,现在必须再维持一个存储(持久的期刊)等等)所以不确定我们在这里买多少?
第二种方法需要为两种情况(传入事件和事件结果)编写持久代码。
第一种方法可能看起来不太有希望。
虽然听起来可能听起来像我并不打算创建一个听起来像“基于意见”的问题但是试图在提到的方法或其他任何可能适合的方法中提供有关其优缺点的真实建议这里。
仅供参考:此特定应用程序是在播放服务器上运行的播放应用程序,因此使用Actors不是问题。
答案 0 :(得分:2)
由于这是一个Play应用程序,您可以使用Akka事件流来发布事件,而无需引用后端工作者角色。
例如,actors/Subscriber.scala
中包含以下内容:
package actors
import akka.actor.Actor
import model._
class Subscriber extends Actor {
context.system.eventStream.subscribe(self, classOf[DomainEvent])
def receive = {
case event: DomainEvent =>
println("Received DomainEvent: " + event)
}
}
... model/events.scala
中的类似内容:
package model
trait DomainEvent
case class TestEvent(message: String) extends DomainEvent
...你的控制器可以像这样发布一个TestEvent:
object Application extends Controller {
import akka.actor.Props
import play.libs.Akka
Akka.system.actorOf(Props(classOf[actors.Subscriber])) // Create the backend actor
def index = Action {
Akka.system.eventStream.publish(model.TestEvent("message")) // publish an event
Ok(views.html.index("Hi!"))
}
}