Skip to content

Conversation

alexvaluyskiy
Copy link
Contributor

@alexvaluyskiy alexvaluyskiy commented Sep 5, 2017

Fix #3067

public void MessageSerializer_should_serialize_state_change_event()
{
var p1 = new Persistent(new PersistentFSM.StateChangeEvent("a", TimeSpan.FromSeconds(10)), sender: TestActor);
var serializer = _serialization.FindSerializerFor(p1);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not test all our serialization infrastructure here, just a concrete serializer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You moved this and the test above to a seperate spec file. But the tests remain the same. So what do you mean ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stopped using FindSerializerFor and added a test for AtLeastOnceDeliverySnapshot
We have integrations tests for all standard persistence messages in Persistence.TCK

public void MessageSerializer_should_serialize_fsm_snapshot()
{
var snapshot = new PersistentFSM.PersistentFSMSnapshot<MyPayload>("a", new MyPayload("b"), TimeSpan.FromSeconds(10));
var p1 = new Persistent(snapshot, sender: TestActor);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PersistentFSMSnapshot should not be put into Persistent object

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. There is a special case scenario in the PersistenceMessageSerializer to handle it. Putting it in the Persistent envelope is wrong.

if (obj is AtomicWrite aw) return GetAtomicWrite(aw).ToByteArray();
if (obj is AtLeastOnceDeliverySnapshot snap) return GetAtLeastOnceDeliverySnapshot(snap).ToByteArray();
if (obj is PersistentFSM.StateChangeEvent stateEvent) return GetStateChangeEvent(stateEvent).ToByteArray();
if (obj.GetType().GetTypeInfo().IsGenericType
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

obj.GetType().GetTypeInfo().IsGenericType - it prevents us from unhandled exceptions

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will still cause an exception down the line. Namely the ArgumentException. But that will be for more descriptive.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ArgumentException is fine, by design

payload.PayloadManifest = ByteString.CopyFromUtf8(manifest);
}
else
{
if (serializer.IncludeManifest)
{
var payloadType = obj.GetType();
payload.PayloadManifest = ByteString.CopyFromUtf8(payloadType.AssemblyQualifiedName);
payload.PayloadManifest = ByteString.CopyFromUtf8(obj.GetType().TypeQualifiedName());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type qualified name is without the assemblyname right ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this is an extension method in the Akka.Util package, which will attempt to serialize without the assembly name if it is part of the core assembly. I'm a little bit nervous on how well this works across runtime versions and if there are going to be an issues during upgrades. The change can be found at d3328ca

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, so I just did a quick comparison. A mono 4.8 app has a core assembly name of mscorlib, while a .net core standard app has a core assembly name of System.Private.CoreLib. This could cause issues with people that are trying to switch runtimes. I'll create an issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joshgarnett is this an issue with this specific change, or also with the previous code?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I take that back, in theory the default should always deserialize properly for types with no assembly included?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@heynickc Anyway, we have used the similar method in 1.2.x

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think we are fine, I retracted my comment right after yours @heynickc I was concerned at first, but all this is doing is grouping together objects that would be under the core assembly, which should be the same set of objects regardless of the actual name of the core assembly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@heynickc as for IncludeManifest, that is how serializers should work, right? If they do not set IncludeManifest to true, then the assumption is that the serializer does not need the manifest in order to deserialize the data properly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joshgarnett gotcha, thanks. I ran into the issue testing backwards compatibility, but I may have been testing an edge case that wasn't possible.

if (obj is AtLeastOnceDeliverySnapshot snap) return GetAtLeastOnceDeliverySnapshot(snap).ToByteArray();
if (obj is PersistentFSM.StateChangeEvent stateEvent) return GetStateChangeEvent(stateEvent).ToByteArray();
if (obj.GetType().GetTypeInfo().IsGenericType
&& obj.GetType().GetGenericTypeDefinition() == typeof(PersistentFSM.PersistentFSMSnapshot<>)) return GetPersistentFSMSnapshot(obj).ToByteArray();

throw new ArgumentException($"Can't serialize object of type [{obj.GetType()}] in [{GetType()}]");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also be updated to SerializationException?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sync it with JVM version. They have NonSerializableException in FromBinary and they don't treat this exception as a fatal

@heynickc heynickc merged commit 2acaa55 into akkadotnet:dev Sep 5, 2017
@alexvaluyskiy alexvaluyskiy deleted the fixpersistenceserializer branch September 5, 2017 17:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants