Akka - 无法在 F# 中将受歧视的联合作为消息发送
Akka - Unable to send Discriminated Unions as messages in F#
Akka - 区分联合作为 F# 中的消息
我无法使用受歧视的工会作为消息给 akka 演员。如果有人能指出一个这样做的例子,我将不胜感激。
我自己的尝试是在 git@github.com:Tweega/AkkaMessageIssue.git。 (下面的片段)。它是在 https://github.com/rikace/AkkaActorModel.git(聊天项目)
中找到的示例的简化版本
问题
DU 消息从未在服务器 actor 上找到它的目标,而是被发送到死信箱。相反,如果我发送对象,它们确实会到达。
如果我发送一个 DU,但将我的服务器 actor 设置为侦听通用对象,消息确实会到达,但它的类型是
seq [seq [seq []]
我无法了解底层 DU。
我正尝试作为消息发送的 DU
type PrinterJob =
| PrintThis of string
| Teardown
客户端代码
let system = System.create "MyClient" config
let chatClientActor =
spawn system "ChatClient" <| fun mailbox ->
let server = mailbox.Context.ActorSelection("akka.tcp://MyServer@localhost:8081/user/ChatServer")
let rec loop nick = actor {
let! (msg:PrinterJob) = mailbox.Receive()
server.Tell(msg)
return! loop nick
}
loop ""
while true do
let input = Console.ReadLine()
chatClientActor.Tell(PrintThis(input))
消息从控制台输入转发到客户端
while true do
let input = Console.ReadLine()
chatClientActor.Tell(PrintThis(input))
服务器代码
let system = System.create "MyServer" config
let chatServerActor =
spawn system "ChatServer" <| fun (mailbox:Actor<_>) ->
let rec loop (clients:Akka.Actor.IActorRef list) = actor {
let! (msg:PrinterJob) = mailbox.Receive()
printfn "Received %A" msg //Received seq [seq [seq []]; seq [seq [seq []]]] ???
match msg with
| PrintThis str ->
Console.WriteLine("Printing: {0} Do we get this?", str)
return! loop clients
| Teardown ->
Console.WriteLine("Tearing down now")
return! loop clients
}
loop []
依赖项
(我在这里没有使用 paket)- 下面的 PM 命令:
- 安装包 Akka -版本 1.4.23
- 安装包 Akka.Remote - 版本 1.4.23
- 安装包 Akka.FSharp - 版本 1.4.23
我在 net5.0 中托管应用程序
构造函数参数名称 - 奇怪?
当作为对象传入class实例时,akka似乎对构造函数参数的名称很敏感。消息得到处理,但数据没有从客户端复制到服务器。如果你有一个叫Username的属性,构造函数参数不能是,比如uName,否则到达服务器时它的值为null。代码在分支参数中。
type DoesWork(montelimar: string) =
member x.Montelimar = montelimar
type DoesNotWork(montelimaro: string) =
member x.Montelimar = montelimaro
我在 Akka.NET 存储库中打开了一个问题:https://github.com/akkadotnet/akka.net/issues/5194
并为此添加了详细的复制:https://github.com/akkadotnet/akka.net/pull/5196
但看起来 Newtonsoft.Json 在没有给出类型提示的情况下确实无法执行此反序列化,Akka.NET 的网络序列化默认情况下不会为 JSON 执行此反序列化:
type TestUnion =
| A of string
| B of int * string
type TestUnion2 =
| C of string * TestUnion
| D of int
[<Fact(Skip="JSON.NET really does not support even basic DU serialization")>]
member _.``JSON.NET must serialize DUs`` () =
let du = C("a-11", B(11, "a-12"))
let settings = new JsonSerializerSettings()
settings.Converters.Add(new DiscriminatedUnionConverter())
let serialized = JsonConvert.SerializeObject(du, settings)
let deserialized = JsonConvert.DeserializeObject(serialized, settings)
Assert.Equal(du :> obj, deserialized)
该测试不会通过,它根本不使用任何 Akka.NET 的基础结构 - 因此默认的 JSON 序列化程序根本不适用于真实世界的 F# 用例.
我们可以尝试更改序列化系统的默认设置以包含类型提示,但这需要进行大量验证测试(对于没有序列化的旧 Akka.Persistence 数据)。
一个更好的解决方案,我的拉请求验证,是使用 Hyperion 进行多态序列化 - 它对您来说同样透明,但它对复杂类型的处理比 Newtonsoft.Json 更强大,实际上是更快:https://getakka.net/articles/networking/serialization.html#how-to-setup-hyperion-as-default-serializer
Akka - 区分联合作为 F# 中的消息
我无法使用受歧视的工会作为消息给 akka 演员。如果有人能指出一个这样做的例子,我将不胜感激。
我自己的尝试是在 git@github.com:Tweega/AkkaMessageIssue.git。 (下面的片段)。它是在 https://github.com/rikace/AkkaActorModel.git(聊天项目)
中找到的示例的简化版本问题
DU 消息从未在服务器 actor 上找到它的目标,而是被发送到死信箱。相反,如果我发送对象,它们确实会到达。
如果我发送一个 DU,但将我的服务器 actor 设置为侦听通用对象,消息确实会到达,但它的类型是
seq [seq [seq []]
我无法了解底层 DU。
我正尝试作为消息发送的 DU
type PrinterJob =
| PrintThis of string
| Teardown
客户端代码
let system = System.create "MyClient" config
let chatClientActor =
spawn system "ChatClient" <| fun mailbox ->
let server = mailbox.Context.ActorSelection("akka.tcp://MyServer@localhost:8081/user/ChatServer")
let rec loop nick = actor {
let! (msg:PrinterJob) = mailbox.Receive()
server.Tell(msg)
return! loop nick
}
loop ""
while true do
let input = Console.ReadLine()
chatClientActor.Tell(PrintThis(input))
消息从控制台输入转发到客户端
while true do
let input = Console.ReadLine()
chatClientActor.Tell(PrintThis(input))
服务器代码
let system = System.create "MyServer" config
let chatServerActor =
spawn system "ChatServer" <| fun (mailbox:Actor<_>) ->
let rec loop (clients:Akka.Actor.IActorRef list) = actor {
let! (msg:PrinterJob) = mailbox.Receive()
printfn "Received %A" msg //Received seq [seq [seq []]; seq [seq [seq []]]] ???
match msg with
| PrintThis str ->
Console.WriteLine("Printing: {0} Do we get this?", str)
return! loop clients
| Teardown ->
Console.WriteLine("Tearing down now")
return! loop clients
}
loop []
依赖项
(我在这里没有使用 paket)- 下面的 PM 命令:
- 安装包 Akka -版本 1.4.23
- 安装包 Akka.Remote - 版本 1.4.23
- 安装包 Akka.FSharp - 版本 1.4.23
我在 net5.0 中托管应用程序
构造函数参数名称 - 奇怪?
当作为对象传入class实例时,akka似乎对构造函数参数的名称很敏感。消息得到处理,但数据没有从客户端复制到服务器。如果你有一个叫Username的属性,构造函数参数不能是,比如uName,否则到达服务器时它的值为null。代码在分支参数中。
type DoesWork(montelimar: string) =
member x.Montelimar = montelimar
type DoesNotWork(montelimaro: string) =
member x.Montelimar = montelimaro
我在 Akka.NET 存储库中打开了一个问题:https://github.com/akkadotnet/akka.net/issues/5194
并为此添加了详细的复制:https://github.com/akkadotnet/akka.net/pull/5196
但看起来 Newtonsoft.Json 在没有给出类型提示的情况下确实无法执行此反序列化,Akka.NET 的网络序列化默认情况下不会为 JSON 执行此反序列化:
type TestUnion =
| A of string
| B of int * string
type TestUnion2 =
| C of string * TestUnion
| D of int
[<Fact(Skip="JSON.NET really does not support even basic DU serialization")>]
member _.``JSON.NET must serialize DUs`` () =
let du = C("a-11", B(11, "a-12"))
let settings = new JsonSerializerSettings()
settings.Converters.Add(new DiscriminatedUnionConverter())
let serialized = JsonConvert.SerializeObject(du, settings)
let deserialized = JsonConvert.DeserializeObject(serialized, settings)
Assert.Equal(du :> obj, deserialized)
该测试不会通过,它根本不使用任何 Akka.NET 的基础结构 - 因此默认的 JSON 序列化程序根本不适用于真实世界的 F# 用例.
我们可以尝试更改序列化系统的默认设置以包含类型提示,但这需要进行大量验证测试(对于没有序列化的旧 Akka.Persistence 数据)。
一个更好的解决方案,我的拉请求验证,是使用 Hyperion 进行多态序列化 - 它对您来说同样透明,但它对复杂类型的处理比 Newtonsoft.Json 更强大,实际上是更快:https://getakka.net/articles/networking/serialization.html#how-to-setup-hyperion-as-default-serializer