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

Persisence serializer setting #2933

Merged
merged 13 commits into from
Aug 11, 2017
Merged

Persisence serializer setting #2933

merged 13 commits into from
Aug 11, 2017

Conversation

Danthar
Copy link
Member

@Danthar Danthar commented Aug 4, 2017

Work in progress for the Persistence serializer proposal. See #2743 (comment)

@@ -130,6 +135,7 @@ public SnapshotStoreSettings(Config config)
SchemaName = config.GetString("schema-name");
TableName = config.GetString("table-name");
AutoInitialize = config.GetBoolean("auto-initialize");
DefaultSerializer = config.GetString("serializer");
Copy link
Member Author

Choose a reason for hiding this comment

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

Even if this setting is not specified by the plugin explicitly, it should still be available. See changes in persistence.conf

@@ -115,6 +115,9 @@ akka.persistence {
# Dispatcher for message replay.
replay-dispatcher = "akka.persistence.dispatchers.default-replay-dispatcher"

# Default serializer used as manifest serializer when applicable and payload serializer when no specific binding overrides are specified
serializer = "json"

Copy link
Member Author

Choose a reason for hiding this comment

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

Here i defined the default serializer setting in the journal-plugin-fallback. Which should be used by default as the fallback plugin for every journal plugin, by the persistence subsystem. But I still need to verify this is actually true

@@ -171,6 +174,9 @@ akka.persistence {
# Dispatcher for the plugin actor.
plugin-dispatcher = "akka.persistence.dispatchers.default-plugin-dispatcher"

# Default serializer used as manifest serializer when applicable and payload serializer when no specific binding overrides are specified
serializer = "json"

Copy link
Member Author

Choose a reason for hiding this comment

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

Same goes for this one, only then defined in the snapshot-store-plugin-fallback

@@ -119,6 +119,26 @@ public Serialization(ExtendedActorSystem system)
}
}

private Serializer GetSerializerByName(string name)
{
Copy link
Member Author

Choose a reason for hiding this comment

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

So this is the helper method for translating the serializer name to an actual instance.
Downside, having to translate it here. Upside, being able to leverage caching once this is done.

return null;

var serializersConfig = System.Settings.Config.GetConfig("akka.actor.serializers").AsEnumerable().ToList();
foreach (var kvp in serializersConfig)
Copy link
Member Author

Choose a reason for hiding this comment

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

Because this config is not saved in the Serialization subsystem, I have to retrieve this value again. Leaning on the assumption of hocon config caching here.

var serializerType = Type.GetType(serializerTypeName);

var serializerId = SerializerIdentifierHelper.GetSerializerIdentifierFromConfig(serializerType, (ExtendedActorSystem)System);
return GetSerializerById(serializerId);
Copy link
Member Author

Choose a reason for hiding this comment

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

Because I want to leverage existing infrastructure as much as possible, without having to resort to creating a new map from name to id (which is possibly easier, but costs more memory, although small). I resolve the name to the serializer ID and use the existing map to return the instance based on that ID.

Im still not completely set on this implementation though. I might just go with a seperate dict that maps name -> id which is initialised in the constructor like the other mappings are.

Impact of this method should be small though, as its only called once per type, after which caching takes over.

Copy link
Member

Choose a reason for hiding this comment

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

Impact of this method should be small though, as its only called once per type, after which caching takes over.

IMHO, should be fine.

@@ -507,7 +515,7 @@ public RequestChunk(int chunkId, IJournalRequest[] requests)
private readonly HashSet<IActorRef> _allIdsSubscribers;
private readonly HashSet<string> _allPersistenceIds;

private readonly Func<Type, Serializer> _getSerializer;
private readonly Func<Type,string, Serializer> _getSerializer;
Copy link
Member Author

Choose a reason for hiding this comment

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

@Horusiath why did you used this pattern? Why not simply call Context.System.Serialization.FindSerializerFor When where you need it? Why store a reference in a func ?

@Danthar
Copy link
Member Author

Danthar commented Aug 7, 2017

Needs ApiApproval. But im going to hold off with that untill i get some feedback.

@Danthar Danthar changed the title WIP Persisence serializer setting Persisence serializer setting Aug 8, 2017
@Danthar
Copy link
Member Author

Danthar commented Aug 8, 2017

Ready for review. Should probably update the DData integration as well. Which should not be hard to do. But want to get some feedback first.

@Danthar Danthar added this to the 1.3.0 milestone Aug 9, 2017
@heynickc
Copy link
Contributor

heynickc commented Aug 9, 2017

@Danthar can you add a quick spec or two for the key parts of this?

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.

Some minor changes needed, namely some unhappy path spec coverage.

@@ -224,6 +224,11 @@ public abstract class BatchingSqlJournalSetup
public QueryConfiguration NamingConventions { get; }

/// <summary>
/// The default serializer used when not type override matching is found
/// </summary>
public readonly string DefaultSerializer;
Copy link
Member

Choose a reason for hiding this comment

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

Make this a property

@@ -163,6 +163,11 @@ public class QueryConfiguration
public readonly TimeSpan Timeout;

/// <summary>
/// The default serializer used when not type override matching is found
/// </summary>
public readonly string DefaultSerializer;
Copy link
Member

Choose a reason for hiding this comment

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

Same as above

@@ -209,5 +209,14 @@ public void MessageSerializer_should_serialize_manifest_provided_by_EventAdapter

back.Manifest.ShouldBe(p1.Manifest);
}

[Fact]
public void Serialization_respects_default_serializer_parameter()
Copy link
Member

Choose a reason for hiding this comment

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

Add a spec to demonstrate what happens if the default serializer can't be found

var serializerType = Type.GetType(serializerTypeName);

var serializerId = SerializerIdentifierHelper.GetSerializerIdentifierFromConfig(serializerType, (ExtendedActorSystem)System);
return GetSerializerById(serializerId);
Copy link
Member

Choose a reason for hiding this comment

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

Impact of this method should be small though, as its only called once per type, after which caching takes over.

IMHO, should be fine.

old-payload = ""Akka.Persistence.Tests.Serialization.OldPayloadSerializer, Akka.Persistence.Tests""
testserializer = ""Akka.Serialization.HyperionSerializer, Akka.Serialization.Hyperion""
Copy link
Member Author

Choose a reason for hiding this comment

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

In order to fix these tests. I switched system default serializer for these tests to Hyperion.
But im not sure if thats a good idea.

Copy link
Member Author

@Danthar Danthar Aug 11, 2017

Choose a reason for hiding this comment

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

In fact. After talking this over with @alexvaluyskiy we are not sure why we have this Spec at all. It was disabled before. But it does not test any real-world scenario as far as we know.
What are the real-world scenario's for sending the Persistent or AtomicWrite types across the network.

Copy link
Member

Choose a reason for hiding this comment

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

None that I can think of

@@ -40,7 +40,7 @@ public void Serialization_respects_default_serializer_parameter()
{
var message = new TestMessage("this is my test message");
var serializer = _serialization.FindSerializerFor(message, "json");
Assert.True(serializer.Identifier == 1); //by default configuration the serializer id for json == newtonsoft == 1
Assert.Equal(1, serializer.Identifier); //by default configuration the serializer id for json == newtonsoft == 1
Copy link
Member Author

Choose a reason for hiding this comment

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

Upside is that this test is more explicit.

@@ -50,7 +50,7 @@ public void Serialization_falls_back_to_system_default_if_unknown_serializer_par
var serializer = _serialization.FindSerializerFor(message, "unicorn");
//since unicorn is an unknown serializer, the system default will be used
//which incedentally is JSON at the moment
Assert.True(serializer.Identifier == 1); //by default configuration the serializer id for json == newtonsoft == 1
Assert.Equal(-5, serializer.Identifier); //system serializer is currently configured to be hyperion which is -5
Copy link
Member Author

Choose a reason for hiding this comment

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

Same goes for this one

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.

Looks fine, sans a copyright header that needs to be changed

@@ -224,6 +224,11 @@ public abstract class BatchingSqlJournalSetup
public QueryConfiguration NamingConventions { get; }

/// <summary>
/// The default serializer used when not type override matching is found
/// </summary>
public string DefaultSerializer { get; }
Copy link
Member

Choose a reason for hiding this comment

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

Looks good to me

old-payload = ""Akka.Persistence.Tests.Serialization.OldPayloadSerializer, Akka.Persistence.Tests""
testserializer = ""Akka.Serialization.HyperionSerializer, Akka.Serialization.Hyperion""
Copy link
Member

Choose a reason for hiding this comment

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

None that I can think of

@@ -0,0 +1,56 @@
// <copyright file="SerializationSpec.cs" company="Copaco B.V.">
// Copyright (c) 2015 - 2017 All Right Reserved
// Author: Arjen Smits
Copy link
Member

Choose a reason for hiding this comment

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

Copyright header needs to be changed

Copy link
Member

Choose a reason for hiding this comment

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

@Danthar indicated in Gitter chat that this was a mistake with his ReSharper template, so no worries.

@Aaronontheweb Aaronontheweb merged commit eee1eba into akkadotnet:v1.3 Aug 11, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants