-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
added reproduction for DU serialization #5196
added reproduction for DU serialization #5196
Conversation
| D of int | ||
|
||
type RemoteSpecs(output:ITestOutputHelper) as this = | ||
inherit AkkaSpec((remoteConfig 0), output) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A little convoluted, but this is how you can pass through the XUnit ITestOutputHelper
and the AkkaSpec
/ TestKit
base members into an F# test
spawne clientSys "a-1" <@ actorOf2 (fun mailbox msg -> | ||
match msg with | ||
| C("a-11", B(11, "a-12")) -> mailbox.Sender() <! msg | ||
| _ -> mailbox.Unhandled msg) @> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a clear reproduction here - we receive a JObject
instead of a DU here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated this to use Hyperion - even a basic Newtonsoft.Json serialization setup can't handle DUs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I remember correctly - but I might be wrong - the issue might be caused by the fact that you either didn't configured JSON.NET to include type name as part of the payload or to use it if it was included. Since at the deserialization time payload type is still unknown and JSON.NET will use JObject as representation of System.Object
instance. Casting it to typed actor message afterwards is already too late and will fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, with type hints Newtonsoft.Json correctly deserializes DUs:
akka.net/src/core/Akka.FSharp.Tests/SerializationSpecs.fs
Lines 41 to 50 in d201452
member this.VerifySerialization msg = | |
let serializer = this.Sys.Serialization.FindSerializerFor msg | |
let t = msg.GetType() | |
let bytes = this.Sys.Serialization.Serialize msg | |
let deserialized = | |
match serializer :> obj with | |
| :? SerializerWithStringManifest as str -> this.Sys.Serialization.Deserialize(bytes, serializer.Identifier, str.Manifest msg) | |
| _ -> this.Sys.Serialization.Deserialize(bytes, serializer.Identifier, t) | |
Assert.Equal(msg, deserialized) |
We disabled exposing type hints during the advent of Akka.NET v1.3 because of mscorlib
namespace issues introduced by the creation of .NET Core: https://twitter.com/Danthar/status/1426204694310014981 cc @Danthar
We could fix the issue by turning type hints on, but it would blow up anyone doing .NET Framework --> .NET Core interop with Newtonsoft.Json (population of people doing that is great than zero) - or we could make it configurable to turn that setting on or off.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can potentially handle that as special case inside of typed actor itself:
akka.net/src/core/Akka.FSharp/FsApi.fs
Lines 291 to 297 in d201452
override x.OnReceive msg = | |
match state with | |
| Func f -> | |
match msg with | |
| :? 'Message as m -> state <- f m | |
| _ -> x.Unhandled msg | |
| Return _ -> x.PostStop() |
Add another match case to check if obj
is JObject
and if so use its ToObject method.
Now checking for whether or not manifests are emitted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Described my work on adding better F# DU testing support going forward - looks like Newtonsoft.Json really can't support DUs even with DiscriminatedUnionConverter
spawne clientSys "a-1" <@ actorOf2 (fun mailbox msg -> | ||
match msg with | ||
| C("a-11", B(11, "a-12")) -> mailbox.Sender() <! msg | ||
| _ -> mailbox.Unhandled msg) @> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated this to use Hyperion - even a basic Newtonsoft.Json serialization setup can't handle DUs
[<MemberData(nameof(SerializationSpecs.FSharpTypes))>] | ||
member _.``Must verify serialization of F#-specific types`` (t:obj) = | ||
this.VerifySerialization t | ||
// uncomment the section below when experimenting with IncludeManifest = true on the Newtonsoft.Json serializer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we enable IncludeManifest = true
in the NewtonsoftJsonSerializer
all of these tests will pass, including the ones currently using Hyperion right now. However, I'm not sure how significant of a change that might be and I'm loathe to touch it given that it powers so many Akka.Persistence serialization schemes.
@@ -35,7 +35,7 @@ module Serialization = | |||
override __.FromBinary(bytes, _) = deserializeFromBinary fsp bytes | |||
|
|||
|
|||
let internal exprSerializationSupport (system: ActorSystem) = | |||
let exprSerializationSupport (system: ActorSystem) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made this public
|
||
|
||
[<Fact(Skip="JSON.NET really does not support even basic DU serialization")>] | ||
member _.``JSON.NET must serialize DUs`` () = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Smoking gun - JsonConvert
can't deserialize a DU even with DiscriminatedUnionConverter
and none of our other customizations to Newtonsoft.Json. Will need to file an issue over there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
close #5194