顺序执行到来的消息 actor
在某项目里,有个 actor 需要做一些持久化的操作,这些操作耗时比较久,理应使用异步的代码来写,但是需求又强调每次只能做一个持久化操作,后来的请求应该等待。一个显然的做法是阻塞式的写,这样就能比较简单的实现顺序花操作。
代码写完以后,我觉得在 actor 中 block 不够完美,就想其他的解决方案。实际上,借助 akka actor 的一些函数,可以实现在不阻塞的情况下实现顺序执行请求的功能的。这种办法的核心是使用 become, unbecome 函数:actor 设置两种状态 free 和 busy,当 free 的时,处理消息,当 busy 时,暂时将消息存储起来,处理消息后,给 actor 返回 done 指令,actor 的状态重新返回到 free,准备处理下一个请求。具体的实现又有很多细节可以考虑,比如当 busy 时到来的请求存储到哪里,是 stash 起来还是在 actor 内部维护一个 queue。请求的处理逻辑是写在 actor 内部,还是借鉴 cameo 模式,再创建一个 actor。
网上已有一种实现,我看了下,觉得应该没有问题。只不过 actor 内部维护了一个 queue,这可能会造成 actor 死亡后重启数据丢失的情况。更好的办法应该是 cameo 模式创建新的 actor 来处理可能出现异常(危险)的工作,其次是把 actor 的 mailbox 当做那个 queue,不要自己维护,按照 doc 缩写,actor 重启后,mailbox 的消息不会丢失。
package actors import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global import akka.actor.{ Actor, ActorRef } import play.api.libs.concurrent.Akka
import play.api.Logger
import play.api.Play.current trait SequentialActor {
this: Actor => import SequentialActor._ // Actor defines type Receive as PartialFunction[Any, Unit]
type ReceiveAsync = PartialFunction[Any, Future[_]] private val queue = scala.collection.mutable.Queue[Job]()
private def enqueue(job: Job): Unit = queue enqueue job
private def dequeue: Option[Job] = if (queue.isEmpty) None else Some(queue.dequeue) private var _senderAsync: ActorRef = _
def senderAsync = _senderAsync def receive: Receive = {
case msg =>
context become busy
process(Job(msg, sender))
} def busy: Receive = {
case Done =>
dequeue match {
case None => context.unbecome
case Some(job) => process(job)
}
case msg =>
enqueue(Job(msg, sender))
} def process(job: Job) {
_senderAsync = job.sender
(receiveAsync orElse fallback)(job.msg).onComplete { _ => self ! Done }
} def receiveAsync: ReceiveAsync def fallback: ReceiveAsync = {
case msg =>
Logger.error(s"Unhandled message: $msg")
Future.successful{ () }
} }
object SequentialActor {
case object Done
case class Job(msg: Any, sender: ActorRef)
}
顺序执行到来的消息 actor的更多相关文章
- 关于MQ的几件小事(五)如何保证消息按顺序执行
		
1.为什么要保证顺序 消息队列中的若干消息如果是对同一个数据进行操作,这些操作具有前后的关系,必须要按前后的顺序执行,否则就会造成数据异常.举例: 比如通过mysql binlog进行两个数据库的数据 ...
 - .NET中按预定顺序执行任务
		
更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月1日. 一.说明 在.NET中线程可以定义按先后顺序进行执行,适合部分有先后次序的业务逻辑.Task也可以按照预定义的先后顺序执行 ...
 - js的并行加载以及顺序执行
		
重新温习了下这段内容,发现各个浏览器的兼容性真的是搞大了头,处理起来很是麻烦. 现在现总结下并行加载多个js的方法: 1,对于动态createElement('script')的方式,对所有浏览器都是 ...
 - 【原创】cs+html+js+css模式(七): 顺序执行与并发执行问题,IIS7及其以上版本的抛错问题解决
		
在进行开发的过程中,针对于这种模式,我们继承的IRequiresSessionState,这种对于我们的同一个IIS的执行中是顺序执行即一个ajax请求处理完成后,才能执行下一个ajax, ...
 - testng xml中按顺序执行java类
		
如红字部份,将安顺序执行4个类 <?xml version="1.0" encoding="UTF-8"?><suite name=" ...
 - js的并行加载与顺序执行
		
javaScript文件(下面简称脚本文件)需要被HTML文件引用才能在浏览器中运行.在HTML文件中可以通过不同的方式来引用脚本文件,我们需要关注的是,这些方式的具体实现和这些方式可能会带来的性能问 ...
 - gulp顺序执行任务
		
gulp的任务的执行是异步的. 所以,当我写完一系列的任务,准备一股脑地执行. # gulp.task('prod', ['clean', 'compass', 'image', 'style', ' ...
 - testng.xml顺序执行多个case配置
		
testng.xml顺序执行多个case配置 项目结构如图:
 - 多命令顺序执行、管道符  ;  &&  ||  |
		
多命令顺序执行:
 
随机推荐
- Dynamic CRM 2013学习笔记(十六)用JS控制Tab可见,可用
			
一个Form里经常会有好几个Tab,有时要根据一些条件设置哪些Tab可用,可见.下面就介绍下如何用JS对Tab进行控制. 1. 控制可见 function setTabVisableByName( ...
 - ASP.NET WebAPI 生成帮助文档与使用Swagger服务测试
			
帮助HELP 要实现如WCF中的Help帮助文档,Web API 2 中已经支持很方便的实现了这一特性 http://www.asp.net/web-api/overview/creating-we ...
 - [转]删除SQL Server Management Studio中保存的帐户信息
			
http://www.2cto.com/database/201208/149850.html 删除SQL Server Management Studio中保存的帐户信息 SQL Serve ...
 - 你不得不知道的HTML5的新型标签
			
<article>标签定义外部的内容.比如来自一个外部的新闻提供者的一篇新的文章,或者来自 blog 的文本,或者是来自论坛的文本.亦或是来自其他外部源内容. <aside>标 ...
 - hibernate date类型插入数据库时精度只到日期没有时间
			
由hibernate 的逆向工具从数据库表生成的*.hbm.xml ,对于数据库的date类型生成如下: <property name = "crttime" ...
 - 每周一道数据结构(四)A*算法&博弈树α-β剪枝
			
A*算法/博弈树 前阵子考试学了A*算法.博弈树和回溯,自己真是愚蠢至极,根本没就搞明白这些,所以对于这些算法问道的话就不能说清楚,也记不住,所以才有了这篇笔记.在这里感谢面试我的那位工程师~~ A* ...
 - [游戏学习25] MFC 橡皮筋画线效果
			
>_<:这是给出窗口内外不同情况的处理展示的例子. >_<:MouseCap.h #include<afxwin.h> class CMyApp :public C ...
 - jQuery的XX如何实现?——1.框架
			
源码链接:内附实例代码 jQuery使用许久了,但是有一些API的实现实在想不通.于是抽空看了jQuery源码,现在把学习过程中发现的一些彩蛋介绍给大家(⊙0⊙). 下面将使用简化的代码来介绍,主要关 ...
 - SVN中Branch的创建与合并
			
在使用源代码版本控制工具时,最佳实践是一直保持一个主干版本.但是为了应付实际开发中的各种情况,适时的开辟一些分支也是很有必要的.比如在持续开发新功能的同时,需要发布一个新版本,那么就需要从开发主干中建 ...
 - atitit.提升开发效率---MDA 软件开发方式的革命(4)----编辑表单建模
			
)----编辑表单建模 1. 建模语言的选型anno+html...不是uml 1 2. 指定显示模板 @BeanEditForm(tmplt="c:/edit.html") 1 ...