Skip to content
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

Serializing a SinkRef wrapped inside a POCO failed. #4421

Closed
Arkatufus opened this issue May 19, 2020 · 2 comments · Fixed by #4425
Closed

Serializing a SinkRef wrapped inside a POCO failed. #4421

Arkatufus opened this issue May 19, 2020 · 2 comments · Fixed by #4425

Comments

@Arkatufus
Copy link
Contributor

Arkatufus commented May 19, 2020

Serializing SinkRef inside a POCO failed because it is serialized using NewtonSoftJsonSerializer instead of the proper StreamRefSerializer

[ERROR][5/19/2020 10:55:22 PM][Thread 0008][akka://DataSourceActorSystem/system/endpointManager/reliableEndpointWriter-akka.tcp%3A%2F%2FReceiverActorSystem%40localhost%3A8081-1/endpointWriter] Cannot preserve reference to readonly dictionary, or dictionary created from a non-default constructor: System.Collections.Immutable.IImmutableDictionary`2[Akka.Streams.InPort,Akka.Streams.OutPort]. Path 'SinkRef.Sink.Module.Upstreams', line 1, position 1235.
Cause: Newtonsoft.Json.JsonSerializationException: Cannot preserve reference to readonly dictionary, or dictionary created from a non-default constructor: System.Collections.Immutable.IImmutableDictionary`2[Akka.Streams.InPort,Akka.Streams.OutPort]. Path 'SinkRef.Sink.Module.Upstreams', line 1, position 1235.
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Akka.Serialization.NewtonSoftJsonSerializer.FromBinary(Byte[] bytes, Type type)
   at Akka.Serialization.Serialization.Deserialize(Byte[] bytes, Int32 serializerId, String manifest)
   at Akka.Remote.MessageSerializer.Deserialize(ExtendedActorSystem system, Payload messageProtocol)
   at Akka.Remote.DefaultMessageDispatcher.Dispatch(IInternalActorRef recipient, Address recipientAddress, Payload message, IActorRef senderOption)
   at Akka.Remote.EndpointReader.<Reading>b__11_0(InboundPayload inbound)
   at lambda_method(Closure , Object , Action`1 , Action`1 , Action`1 )
   at Akka.Tools.MatchHandler.PartialHandlerArgumentsCapture`4.Handle(T value)
   at Akka.Actor.ReceiveActor.ExecutePartialMessageHandler(Object message, PartialAction`1 partialAction)
   at Akka.Actor.ReceiveActor.OnReceive(Object message)
   at Akka.Actor.UntypedActor.Receive(Object message)
   at Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
   at Akka.Actor.ActorCell.ReceiveMessage(Object message)
   at Akka.Actor.ActorCell.Invoke(Envelope envelope)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Akka.Actor.ActorCell.HandleFailed(Failed f)
   at Akka.Actor.ActorCell.SysMsgInvokeAll(EarliestFirstSystemMessageList messages, Int32 currentState)

This is related to this StackOverflow question.

@Arkatufus Arkatufus changed the title Deserializing SinkRef inside a ReceiveActor Receive failed. Serializing a SinkRef wrapped inside a POCO failed. May 20, 2020
@Aaronontheweb Aaronontheweb added this to the 1.4.7 milestone May 21, 2020
@Arkatufus
Copy link
Contributor Author

Arkatufus commented May 21, 2020

One possibility to fix this is to add a registry of JsonConverter that gets loaded into the NewtonSoftJsonSerializer.

The job of the JsonConverter is to act as an automatic serializer for these Akka specific classes into byte arrays using protobuff and write these as Base64 encoded string property inside the JSON payload. The reverse is done on the receiving end.

@Aaronontheweb
Copy link
Member

As I mentioned in Gitter chat - I think we might be able to accomplish this using the ISurrogate interface. That's how IActorRef serialization is currently handled inside POCO classes today.

@Aaronontheweb Aaronontheweb modified the milestones: 1.4.12, 1.4.13 Nov 16, 2020
@Aaronontheweb Aaronontheweb modified the milestones: 1.4.13, 1.4.14 Dec 16, 2020
Aaronontheweb added a commit to Arkatufus/akka.net that referenced this issue Dec 29, 2020
Had to decorate the `ISinkRef<T>` interface with the `ISurrogated` interface. `ISourceRef<T>` had always been done this way but not `ISinkRef<T>` for some reason.
@Aaronontheweb Aaronontheweb added this to To do in Dec 14-25 2020 Sprint via automation Dec 29, 2020
Dec 14-25 2020 Sprint automation moved this from To do to Done Dec 29, 2020
Aaronontheweb added a commit that referenced this issue Dec 29, 2020
* Add bug reproduction spec

* Add throttling because throttle populates the ImmutableDictionary in `Sink`

* close #4421 - enabled SinkRef<T> to work in POCO serialization

Had to decorate the `ISinkRef<T>` interface with the `ISurrogated` interface. `ISourceRef<T>` had always been done this way but not `ISinkRef<T>` for some reason.

Co-authored-by: Aaron Stannard <aaron@petabridge.com>
This was referenced Dec 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

Successfully merging a pull request may close this issue.

2 participants