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

Fix broken object type serializer in QueryExecutor #6528

Merged

Conversation

Arkatufus
Copy link
Contributor

Fixes akkadotnet/Akka.Hosting#127
Fixes #6389

A Port of #6223 from v1.4 branch to dev branch

Changes

  • Removed persistence default deserializer feature

Issue

Any non-serializer mapped objects being serialized by Akka.Persistence.Sql.Common.Journal.QueryExecutor will use the JSON serializer and not the object type serializer.

Problem is with this line:

var serializer = Serialization.FindSerializerForType(e.Payload.GetType(), Configuration.DefaultSerializer);

which takes its value from the very obscure and very rarely used HOCON override here:

Workaround

Override the HOCON setting:

akka.persistence.journal-plugin-fallback.serializer = null
akka.persistence.snapshot-store-plugin-fallback.serializer = null

or declare the default non-mapped object serializer in the journal/snapshot settings:

akka.persistence.journal.sqlite.serializer = mySerializer
akka.persistence.snapshot-store.sqlite.serializer = mySerializer

@@ -1228,7 +1229,7 @@ private async Task<WriteMessagesResult> HandleWriteMessages(WriteMessages req, T
protected virtual void WriteEvent(TCommand command, IPersistentRepresentation persistent, string tags = "")
{
var payloadType = persistent.Payload.GetType();
var serializer = _serialization.FindSerializerForType(payloadType, Setup.DefaultSerializer);
var serializer = _serialization.FindSerializerForType(payloadType);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the actual fix, we do not use the default serializer set in the persistence plugin HOCON settings for writes anymore.

@@ -780,7 +781,7 @@ protected DbCommand GetCommand(DbConnection connection, string sql)
protected virtual void WriteEvent(DbCommand command, IPersistentRepresentation e, IImmutableSet<string> tags)
{

var serializer = Serialization.FindSerializerForType(e.Payload.GetType(), Configuration.DefaultSerializer);
var serializer = Serialization.FindSerializerForType(e.Payload.GetType());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the actual fix, we do not use the default serializer set in the persistence plugin HOCON settings for writes anymore.

@@ -846,7 +847,10 @@ protected virtual IPersistentRepresentation ReadEvent(DbDataReader reader)
{
// Support old writes that did not set the serializer id
var type = Type.GetType(manifest, true);
#pragma warning disable CS0618
// Backward compatibility code, we still need to use the old default serializer on read to support legacy data
var deserializer = Serialization.FindSerializerForType(type, Configuration.DefaultSerializer);
Copy link
Contributor Author

@Arkatufus Arkatufus Mar 17, 2023

Choose a reason for hiding this comment

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

This is the only code in the SQL common journal that still uses the old settings. The purpose of this code is to make sure that really old (pre-v1.3.0) data are still readable by the journal. These pre-v1.3.0 event data does not have their serializer_id column populated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Another piece of code that still uses this still uses this setting is the snapshot store reader, just like this one, it is there to make sure that legacy data are still readable.

@@ -224,22 +224,5 @@ protected override async Task DeleteAsync(string persistenceId, SnapshotSelectio
await QueryExecutor.DeleteBatchAsync(connection, nestedCancellationTokenSource.Token, persistenceId, criteria.MaxSequenceNr, criteria.MaxTimeStamp);
}
}

private SnapshotEntry ToSnapshotEntry(SnapshotMetadata metadata, object snapshot)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Byte-rot method, this method is not being used anymore.

}

[Fact(DisplayName = "Legacy v1.3.0 and below data (null serializer_id) should be read correctly")]
public void ReadLegacyDataTest()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The purpose of this test is to make sure that data saved from v1.3.0 can still be recovered successfully. The Sqlite file were generated using v.1.3.0 code and is being recovered in this unit test.

await record.ReadAsync();

// In the bug this fails, the serializer id is JSON id instead of MySerializer id
record[0].Should().Be(9999);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This unit test makes sure that the old serializer HOCON setting are not being used in journal writes anymore.

Copy link
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

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

LGTM

@Aaronontheweb Aaronontheweb merged commit 7ca22af into akkadotnet:dev Mar 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants