-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Updated PersistenceMessageSerializer #3069
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
Updated PersistenceMessageSerializer #3069
Conversation
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); |
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 should not test all our serialization infrastructure here, just a concrete 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.
You moved this and the test above to a seperate spec file. But the tests remain the same. So what do you mean ?
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 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); |
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.
PersistentFSMSnapshot should not be put into Persistent
object
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.
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 |
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.
obj.GetType().GetTypeInfo().IsGenericType
- it prevents us from unhandled exceptions
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.
It will still cause an exception down the line. Namely the ArgumentException. But that will be for more descriptive.
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.
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()); |
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.
Type qualified name is without the assemblyname right ?
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.
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
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.
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.
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.
@joshgarnett is this an issue with this specific change, or also with the previous code?
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.
Actually I take that back, in theory the default should always deserialize properly for types with no assembly included?
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.
@heynickc Anyway, we have used the similar method in 1.2.x
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.
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.
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.
@alexvaluyskiy ok sorry, I was in the wrong vacinity. this is where I was curious about such an issue: https://github.com/akkadotnet/akka.net/blob/dev/src/contrib/persistence/Akka.Persistence.Sql.Common/Journal/QueryExecutor.cs#L656
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.
@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.
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.
@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()}]"); |
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.
Should this also be updated to SerializationException?
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.
good point
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 sync it with JVM version. They have NonSerializableException
in FromBinary
and they don't treat this exception as a fatal
Fix #3067