重播事件时持久性失败...System.NotSupportedException:尚不支持通用 IDictionary

Persistence failure when replaying events... System.NotSupportedException: Generic IDictionary are not yet supported

你能帮忙吗?保存一两次时效果很好。三个或更多,我得到这个:

    [INFO][11/28/2017 2:57:27 PM][Thread 0005][[akka://ECHO3DEV/user/api-master/PortfolioCoordinator/TK#425630680]] Portfolio Actor: TK completely recovered. Current Positions: ......
11/28/2017 9:57:27 AM portfolio- Actor started...
[ERROR][11/28/2017 2:57:27 PM][Thread 0005][[akka://ECHO3DEV/user/api-master/PortfolioCoordinator/TK/TK-IBM#1280277591]] **Persistence failure when replaying events for persistenceId [portfolio-TK-IBM]. **Last known sequence number [3]
Cause: System.NotSupportedException: Generic IDictionary<TKey,TValue> are not yet supported****
   at Hyperion.SerializerFactories.DictionarySerializerFactory.<>c__DisplayClass3_0.<BuildSerializer>b__0(Stream stream, DeserializerSession session)
   at Hyperion.ValueSerializers.ObjectSerializer.ReadValue(Stream stream, DeserializerSession session)
   at lambda_method(Closure , Stream , DeserializerSession )
   at Hyperion.ValueSerializers.ObjectSerializer.ReadValue(Stream stream, DeserializerSession session)
   at lambda_method(Closure , Stream , DeserializerSession )
   at Hyperion.ValueSerializers.ObjectSerializer.ReadValue(Stream stream, DeserializerSession session)
   at lambda_method(Closure , Stream , DeserializerSession )
   at Hyperion.ValueSerializers.ObjectSerializer.ReadValue(Stream stream, DeserializerSession session)
   at Hyperion.SerializerFactories.DefaultDictionarySerializerFactory.<>c__DisplayClass3_0.<BuildSerializer>b__0(Stream stream, DeserializerSession session)
   at Hyperion.ValueSerializers.ObjectSerializer.ReadValue(Stream stream, DeserializerSession session)
   at lambda_method(Closure , Stream , DeserializerSession )
   at Hyperion.ValueSerializers.ObjectSerializer.ReadValue(Stream stream, DeserializerSession session)
   at lambda_method(Closure , Stream , DeserializerSession )
   at Hyperion.ValueSerializers.ObjectSerializer.ReadValue(Stream stream, DeserializerSession session)
   at Hyperion.Serializer.Deserialize[T](Stream stream)
   at Akka.Serialization.HyperionSerializer.FromBinary(Byte[] bytes, Type type)
   at Akka.Persistence.Sql.Common.Journal.AbstractQueryExecutor.ReadEvent(DbDataReader reader)
   at Akka.Persistence.Sql.Common.Journal.AbstractQueryExecutor.<SelectByPersistenceIdAsync>d__44.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Akka.Persistence.Sql.Common.Journal.SqlJournal.<ReplayMessagesAsync>d__32.MoveNext()

我该如何调试它?

这不是 Akka.Persistence 本身的问题。该错误本身存在于 Hyperion 序列化程序中,您不应该将其用于持久性(仅用于远程处理)。毕竟,您要存储的数据是您自己的,如果您自己控制数据的存储方式会更好 ;)

我已经描述了这个和其他常见的 Akka.Persistence 错误 here

反对将 Hyperion 用于持久性的原因之一是它仍处于测试阶段,并且其二进制格式并未一成不变。这意味着升级序列化程序后,您可能无法再读回您的事件。

出于这个原因,最好为您的事件显式定义一个具有众所周知架构的序列化程序。您可以决定自己推出,或者选择 MsqPack or Microsoft Bond - 它们使用显式模式定义,随着时间的流逝和事件内容的变化,工作起来更容易。

要定义自定义序列化程序,您需要使用某种类型(即空接口)标记您的事件,您将使用该类型来识别哪个序列化程序适用于它们。然后只需简单地在 HOCON 配置中定义一个序列化器映射:

akka.actor {  
  serializers.msgpack= "Akka.Serialization.MessagePack.MsgPackSerializer, Akka.Serialization.MessagePack"
  serialization-bindings {
    "MyNamespace.IDomainEvent, MyAssembly" = msgpack
  }
}

我在这里使用 Akka.NET MsgPack 序列化程序来自定义接口 IDomainEvent,我将通过它来识别我的事件。类型识别需要带有程序集的完全限定类型名称。