我正在构建一个Akka应用程序,并希望将某些actor的FSM状态转换暴露给外部消费者。 (最终目标是能够将状态转换消息推送到websocket,以便可以实时查看它们。)
基于文档Combining dynamic stages to build a simple Publish-Subscribe service,看起来我需要公开代表pub-sub通道的Flow,以便消费者和生产者可以使用它。
我遇到问题的部分是将新的源附加到Flow,以便生成的每个新actor将其状态转换发布到Source。另一个问题是向Flow添加新的接收器(最后,这将是websockets,但出于测试目的,它可能是任何新的接收器。)
首先,我连接MergeHub和BroadcastHub以形成"频道"然后从物化接收器和源创建Flow:
Set objShell = CreateObject("WScript.Shell")
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFso.GetFolder(objShell.CurrentDirectory)
Set TifCollection = CreateObject("Scripting.Dictionary")
Set objLines = CreateObject("Scripting.Dictionary")
' Compile 2-dimensional array listing all documents with their pages
For Each objFile In objFolder.Files
If objFso.GetExtensionName (objFile.Path) = "jpg" Then
file = Split(objFile.Name, "_")(0)
page = Split(objFile.Name, "_")(1)
If Not TifCollection.Exists(file) Then
TifCollection.Add file, CreateObject("Scripting.Dictionary")
End If
TifCollection.Item(file).Add page, ""
End If
Next
funcSortKeysByLengthDesc(TifCollection)
' Loop through the array to compile the loadfile
For Each file In TifCollection.Keys
For Each page In TifCollection(file)
If (page = "1.jpg") Then
objLines.Add file & ",," & file & "_" & page & ",Y,,," & TifCollection(file).Count, ""
Else
objLines.Add file & ",," & file & "_" & page & ",,,,", ""
End If
Next
Next
' Write to filesystem
strFileName = year(date) & month(date) & day(date) & hour(time) & minute(time) & second(time) & "-" & objLines.Count & "-IMAGES.opt"
Set objLoadfile = objFso.CreateTextFile(objFolder & "\" & strFileName,True)
objLoadfile.Write(Join(objLines.Keys, VBCRLF))
Function funcSortKeysByLengthDesc(dctList As Object) As Object
'todo
End Function
那么问题是如何动态地将新生产者和消费者添加到此流程?有什么想法吗?
答案 0 :(得分:1)
我在我的一个项目中使用以下解决方案,以通过多个请求处理器处理来自websocket的请求,这些请求处理器可能产生响应流或提供无穷的订阅。
// requests coming from websocket, it could be any source, it's doesn't matter
val requests: Source[Request, NotUsed] = ...
// the request processing here can provide endles stream of responses
val requestProcessing: Flow[Request, Response, NotUsed] = ...
val (outSink, outSource) =
MergeHub
.source[Result](perProducerBufferSize = 4)
.toMat(BroadcastHub.sink(bufferSize = 32))(Keep.both)
.run()
Source.tick(Duration.Zero, KeepAliveInterval, ConnectionKeepAlive)
.to(outSink)
.run()
requests.fold {
case State(state, AuthRequest(r)) if checkAuth(r) =>
Source.single(AuthenticationAck).to(outSink)
state.copy(isAuthenticated = true)
case State(state, AuthRequest(r)) =>
Source.single(AuthenticationFailedError).to(outSink)
state
case State(state, request) if s.isAuthenticated =>
// here the most of busines
Source.single(request).via(requestProcessing).to(outSink)
state
case State(state, _) =>
Source.single(NonAuthorizedError).to(outSink)
state
}.toMat(Sink.ignore)(Keep.right)
outSource.runForeach { response =>
// here we get the stream of responses mixed from all requests
}
outSource.runForeach { response =>
// of course, we could have as many subscribers as we need
}
我希望这会有所帮助:)
答案 1 :(得分:0)
对于这个特殊问题,我不会使用akka-stream
。您描述的多播pub-sub类型更适合原始Actor
消息传递和EventStream
。
在某些情况下,我是akka-stream的忠实粉丝,但在这种情况下,我认为你正试图通过圆孔安装方形钉。