我一直在研究实验性的Akka Persistence Query模块,并且非常有兴趣为我的应用程序实现自定义读取日志。该文档描述了两种主要的查询形式,一种返回日志的当前状态(例如CurrentPersistenceIdsQuery
),另一种返回可订阅的流,当事件通过写入端提交给日志时发出事件。应用程序(例如AllPersistenceIdsQuery
)
对于我的设计应用程序,我使用Postgres和Slick 3.1.1来驱动这些查询的内容。我可以通过以下方式成功地传输数据库查询结果:
override def allPersistenceIds = {
val db = Database.forConfig("postgres")
val metadata = TableQuery[Metadata]
val query = for (m <- metadata) yield m.persistenceId
Source.fromPublisher(db.stream(query.result))
}
但是,只要基础Slick DB操作完成,就会将流信号通知为完成。这似乎不能满足能够发出新事件的永久开放流的要求。
我的问题是:
谢谢!
答案 0 :(得分:4)
这不像这一行代码那么简单,但你已经是正确的轨道了。
为了实现“无限”流,您需要多次查询 - 即实现轮询,除非底层数据库允许无限查询(这里不是AFAICS)。
轮询需要跟踪“偏移量”,因此如果您通过某个标记进行查询,并发出另一个轮询,则需要从“最后发出的元素”开始(第二个)查询,并且不是表的开头了。所以你需要某个地方,很可能是一个保持这种偏移的人。
Query Side LevelDB插件不是其他实现的最佳角色模型,因为它假设了很多关于底层日志及其工作原理。此外,LevelDB并不适用于Akka Persistence的制作 - 它是我们发行的期刊,以便拥有一个可以开箱即用的持久性日记(无需启动Cassandra等)。
如果您正在寻找灵感,MongoDB插件实际上应该是一个非常好的源,因为它们具有与SQL存储非常相似的限制。我不确定是否有任何SQL日志当前实现了Query端。
答案 1 :(得分:0)
可以使用Postgres replication API来获取“无限”的数据库事件流。 Postgres JDBC驱动程序从版本42.0.0开始支持它,请参阅相关的pull request。 但是,它不是真正的流,而是来自数据库WAL的缓冲同步读取器。
PGReplicationStream stream =
pgConnection
.replicationStream()
.logical()
.withSlotName("test_decoding")
.withSlotOption("include-xids", false)
.withSlotOption("skip-empty-xacts", true)
.start();
while (true) {
ByteBuffer buffer = stream.read();
//process logical changes
}
对于这个读者,在alpakka project中有一个Akka Streams适配器(Source)会很好。