akka.netakka.net-persistence

By default where Akka.net stores its messages?


I have downloaded a sample code from github and run AtLeastOnceDelivery.sln Every new run it is sending messages with it. And if I change the message namespace it shows an error started with

Error loading snapshot [SnapshotMetadata<pid: delivery, seqNr: 0, timestamp: 2018/09/24>], remaining attempts: [0]

If I could clear the persistence hopefully it will accept then changed namespace and restart messaging id.


Solution

  • By default, all snapshots are stored as files directly in ./snapshots directory of the application, while events are stored in the memory. Because of that you should consider using a one of the akka.persistence plugins for the production purposes.

    Your problem happens because you're using akka.net default serializers (dedicated for networking) which are not very version tolerant - so changing any fields, their types, class names or namespaces makes previous version of the class non-deserializable - and in future will be subject to change. This is also why it's strongly discouraged to use default serializers for persistence.

    How to make a custom Akka.NET Serializer

    While there are plans to improve serializers API, at the current moment (Akka.NET v1.3.9), to make your own serializer you need to simply inherit from Akka.Serialization.Serializer class:

    public sealed class MySerializer : Serializer
    {
        public MySerializer(ExtendedActorSystem system) : base(system) { }
        public override int Identifier => /* globaly unique serializer id */;
        public override bool IncludeManifest => true;
    
        public override byte[] ToBinary(object obj)
        {
            // serialize object
        }
    
        public override object FromBinary(byte[] bytes, Type type)
        {
            // deserialize object 
        }
    }
    

    Keep in mind that Identifier property must be unique in cluster scope - usually values below 100 are used by akka.net internal serializers, therefore it's better to use higher values.

    How to bind serializer to be used for a given type

    By convention Akka.NET uses empty interfaces to mark message types that are supposed to be serialized. Then you can setup your HOCON configuration to use a specific serializer for a given interface:

    akka.actor {
        serializers {
            my-serializer = ""MyNamespace.MySerializer, MyAssembly""
        }
        serialization-bindings {
            ""MyNamespace.MyInterface, MyAssembly"" = my-serializer
        }
    }
    

    Where MyInterface is interface assigned to a message type you want to serialize/deserialize with MySerializer.