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

Snapshots Deserialize to JObject and then ignored #91

Open
mrhockeymonkey opened this issue Apr 12, 2021 · 2 comments
Open

Snapshots Deserialize to JObject and then ignored #91

mrhockeymonkey opened this issue Apr 12, 2021 · 2 comments

Comments

@mrhockeymonkey
Copy link
Contributor

Related to: #63 and #49

I am currently using Akka.Persistence.PostgreSql version 1.4.17 and have seen issues recovering from snapshots using the JSON format. I am using PersistentFSM<TState, TData, TEvent> which is offered a snapshot which is subsequently ignored because it has not been deserialized to the correct type.

The actor handles this by reading all events from the journal instead so no errors are thrown, indeed its only by chance that I spotted this behavior.

protected override bool ReceiveRecover(object message)
    {
      switch (message)
      {
        case TEvent domainEvent:
          this.StartWith(this.StateName, this.ApplyEvent(domainEvent, this.StateData));
          return true;
        case PersistentFSM.StateChangeEvent stateChangeEvent:
          this.StartWith(this.StatesMap[stateChangeEvent.StateIdentifier], this.StateData, stateChangeEvent.Timeout);
          return true;
        case SnapshotOffer snapshotOffer:
          if (!(snapshotOffer.Snapshot is PersistentFSM.PersistentFSMSnapshot<TData> snapshot))
            return false; // <~~ snapshotOffer.snapshot is Newtonsoft.Json.Linq.JObject but should be PersistentFSM.PersistentFSMSnapshot<TData>
          this.StartWith(this.StatesMap[snapshot.StateIdentifier], snapshot.Data, snapshot.Timeout);
          return true;
        case RecoveryCompleted _:
          this.Initialize();
          this.OnRecoveryCompleted();
          return true;
        default:
          return false;
      }
    }

Reading the snapshot store from the DB I can see that the manifest field is "" as was mentioned to be the issue in #63.

Following through the code I can see the same method mentioned is at fault for not adding the manifest correctly.

    protected override void SetManifestParameters(object snapshot, DbCommand command)
    {
      Type type = snapshot.GetType();
      Serializer serializerForType = this.Serialization.FindSerializerForType(type, this.Configuration.DefaultSerializer);
      string str = "";
      if (serializerForType is SerializerWithStringManifest withStringManifest)
        str = withStringManifest.Manifest(snapshot);
      else if (!serializerForType.IncludeManifest)
        str = type.TypeQualifiedName();
      this.AddParameter(command, "@Manifest", DbType.String, (object) str); // <~~ str = ""
      this.AddParameter(command, "@SerializerId", DbType.Int32, (object) serializerForType.Identifier);
    }

I have also tried switching to BYTEA with a mind to use my own serialization but the lack of manifest again prevents me from doing so. Journal entries looks to have manifest set correctly, this only seems to effect snapshots.

My akka.conf for context:

akka {
    loglevel=DEBUG
    loggers=["Akka.Logger.Serilog.SerilogLogger, Akka.Logger.Serilog"]
    persistence {
        fsm {
            snapshot-after = 3 # for testing purposes, normally 100
        }
        journal {
            plugin = "akka.persistence.journal.postgresql"
            postgresql {
                class = "Akka.Persistence.PostgreSql.Journal.PostgreSqlJournal, Akka.Persistence.PostgreSql"
                connection-string = "<dbConnectionString>"
                schema-name = public
                table-name = event_journal
                auto-initialize = on
                stored-as = BYTEA
            }
        }    
        snapshot-store {
            plugin = "akka.persistence.snapshot-store.postgresql"
            postgresql {
                class = "Akka.Persistence.PostgreSql.Snapshot.PostgreSqlSnapshotStore, Akka.Persistence.PostgreSql"
                connection-string = "<dbConnectionString>"
                schema-name = public
                table-name = snapshot_store
                auto-initialize = on
                stored-as = JSON
            }
        }
    }
}

@mrhockeymonkey
Copy link
Contributor Author

@CumpsD your comment on #63 may be exactly what I am referring to potentially?

@CumpsD
Copy link
Member

CumpsD commented Apr 16, 2021

Yes, I think #63 was closed too soon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants