protected object GetSnapshot(SnapshotRow reader) { var manifest = reader.Manifest; var binary = (byte[])reader.Payload; object obj; if (reader.SerializerId == null) { var type = Type.GetType(manifest, true); // TODO: hack. Replace when https://github.com/akkadotnet/akka.net/issues/3811 obj = Akka.Serialization.Serialization.WithTransport( _serialization.System, (serializer: _serialization.FindSerializerForType(type, _config.DefaultSerializer), binary, type), (state) => state.serializer.FromBinary(state.binary, state.type)); } else { var serializerId = reader.SerializerId.Value; obj = _serialization.Deserialize(binary, serializerId, manifest); } return(obj); }
/// <summary> /// TBD /// </summary> /// <param name="snapshot">TBD</param> /// <param name="command">TBD</param> protected virtual void SetPayloadParameter(object snapshot, DbCommand command) { var snapshotType = snapshot.GetType(); var serializer = Serialization.FindSerializerForType(snapshotType, Configuration.DefaultSerializer); // TODO: hack. Replace when https://github.com/akkadotnet/akka.net/issues/3811 var binary = Akka.Serialization.Serialization.WithTransport(Serialization.System, () => serializer.ToBinary(snapshot)); AddParameter(command, "@Payload", DbType.Binary, binary); }
/// <summary> /// TBD /// </summary> /// <param name="snapshot">TBD</param> /// <param name="command">TBD</param> protected virtual void SetPayloadParameter(object snapshot, DbCommand command) { var snapshotType = snapshot.GetType(); var serializer = Serialization.FindSerializerForType(snapshotType, Configuration.DefaultSerializer); var binary = serializer.ToBinary(snapshot); AddParameter(command, "@Payload", DbType.Binary, binary); }
private SelectedSnapshot ToSelectedSnapshot(SnapshotEntry entry) { var legacy = entry.SerializerId.HasValue || !string.IsNullOrEmpty(entry.Manifest); if (!legacy) { var ser = _serialization.FindSerializerForType(typeof(Serialization.Snapshot)); var snapshot = ser.FromBinary <Serialization.Snapshot>((byte[])entry.Snapshot); return(new SelectedSnapshot(new SnapshotMetadata(entry.PersistenceId, entry.SequenceNr), snapshot.Data)); } int? serializerId = null; Type type = null; // legacy serialization if (!entry.SerializerId.HasValue && !string.IsNullOrEmpty(entry.Manifest)) { type = Type.GetType(entry.Manifest, true); } else { serializerId = entry.SerializerId; } if (entry.Snapshot is byte[] bytes) { object deserialized; if (serializerId.HasValue) { deserialized = _serialization.Deserialize(bytes, serializerId.Value, entry.Manifest); } else { var deserializer = _serialization.FindSerializerForType(type); deserialized = deserializer.FromBinary(bytes, type); } if (deserialized is Serialization.Snapshot snap) { return(new SelectedSnapshot( new SnapshotMetadata(entry.PersistenceId, entry.SequenceNr, new DateTime(entry.Timestamp)), snap.Data)); } return(new SelectedSnapshot( new SnapshotMetadata(entry.PersistenceId, entry.SequenceNr, new DateTime(entry.Timestamp)), deserialized)); } // backwards compat - loaded an old snapshot using BSON serialization. No need to deserialize via Akka.NET return(new SelectedSnapshot( new SnapshotMetadata(entry.PersistenceId, entry.SequenceNr, new DateTime(entry.Timestamp)), entry.Snapshot)); }
/// <summary> /// TBD /// </summary> /// <param name="command">TBD</param> /// <param name="e">TBD</param> /// <param name="tags">TBD</param> /// <returns>TBD</returns> protected virtual void WriteEvent(DbCommand command, IPersistentRepresentation e, IImmutableSet <string> tags) { var serializer = Serialization.FindSerializerForType(e.Payload.GetType(), Configuration.DefaultSerializer); // TODO: hack. Replace when https://github.com/akkadotnet/akka.net/issues/3811 var(binary, manifest) = Akka.Serialization.Serialization.WithTransport(Serialization.System, (e.Payload, serializer), (state) => { var(thePayload, theSerializer) = state; string thisManifest = ""; if (theSerializer is SerializerWithStringManifest stringManifest) { thisManifest = stringManifest.Manifest(thePayload); } else { if (theSerializer.IncludeManifest) { thisManifest = thePayload.GetType().TypeQualifiedName(); } } return(theSerializer.ToBinary(thePayload), thisManifest ); }); AddParameter(command, "@PersistenceId", DbType.String, e.PersistenceId); AddParameter(command, "@SequenceNr", DbType.Int64, e.SequenceNr); AddParameter(command, "@Timestamp", DbType.Int64, e.Timestamp); AddParameter(command, "@IsDeleted", DbType.Boolean, false); AddParameter(command, "@Manifest", DbType.String, manifest); AddParameter(command, "@Payload", DbType.Binary, binary); AddParameter(command, "@SerializerId", DbType.Int32, serializer.Identifier); if (tags.Count != 0) { var tagBuilder = new StringBuilder(";", tags.Sum(x => x.Length) + tags.Count + 1); foreach (var tag in tags) { tagBuilder.Append(tag).Append(';'); } AddParameter(command, "@Tag", DbType.String, tagBuilder.ToString()); } else { AddParameter(command, "@Tag", DbType.String, DBNull.Value); } }
private Persistent ToPersistenceRepresentation(JournalEntry entry, IActorRef sender) { var legacy = entry.SerializerId.HasValue || !string.IsNullOrEmpty(entry.Manifest); if (!legacy) { var ser = _serialization.FindSerializerForType(typeof(Persistent)); return(ser.FromBinary <Persistent>((byte[])entry.Payload)); } int? serializerId = null; Type type = null; // legacy serialization if (!entry.SerializerId.HasValue && !string.IsNullOrEmpty(entry.Manifest)) { type = Type.GetType(entry.Manifest, true); } else { serializerId = entry.SerializerId; } if (entry.Payload is byte[] bytes) { object deserialized = null; if (serializerId.HasValue) { deserialized = _serialization.Deserialize(bytes, serializerId.Value, entry.Manifest); } else { var deserializer = _serialization.FindSerializerForType(type); deserialized = deserializer.FromBinary(bytes, type); } if (deserialized is Persistent p) { return(p); } return(new Persistent(deserialized, entry.SequenceNr, entry.PersistenceId, entry.Manifest, entry.IsDeleted, sender)); } else // backwards compat for object serialization - Payload was already deserialized by BSON { return(new Persistent(entry.Payload, entry.SequenceNr, entry.PersistenceId, entry.Manifest, entry.IsDeleted, sender)); } }
public PostgreSqlQueryExecutor(PostgreSqlQueryConfiguration configuration, Akka.Serialization.Serialization serialization) : base(configuration, serialization) { CreateSnapshotTableSql = $@" DO $do$ BEGIN IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{Configuration.SchemaName}' AND TABLE_NAME = '{Configuration.SnapshotTableName}') THEN CREATE TABLE {Configuration.FullSnapshotTableName} ( {Configuration.PersistenceIdColumnName} VARCHAR(255) NOT NULL, {Configuration.SequenceNrColumnName} BIGINT NOT NULL, {Configuration.TimestampColumnName} BIGINT NOT NULL, {Configuration.ManifestColumnName} VARCHAR(500) NOT NULL, {Configuration.PayloadColumnName} {configuration.StoredAs.ToString().ToUpperInvariant()} NOT NULL, CONSTRAINT {Configuration.SnapshotTableName}_pk PRIMARY KEY ({Configuration.PersistenceIdColumnName}, {Configuration.SequenceNrColumnName}) ); CREATE INDEX {Configuration.SnapshotTableName}_{Configuration.SequenceNrColumnName}_idx ON {Configuration.FullSnapshotTableName}({Configuration.SequenceNrColumnName}); CREATE INDEX {Configuration.SnapshotTableName}_{Configuration.TimestampColumnName}_idx ON {Configuration.FullSnapshotTableName}({Configuration.TimestampColumnName}); END IF; END $do$"; InsertSnapshotSql = $@" WITH upsert AS ( UPDATE {Configuration.FullSnapshotTableName} SET {Configuration.TimestampColumnName} = @Timestamp, {Configuration.PayloadColumnName} = @Payload WHERE {Configuration.PersistenceIdColumnName} = @PersistenceId AND {Configuration.SequenceNrColumnName} = @SequenceNr RETURNING *) INSERT INTO {Configuration.FullSnapshotTableName} ( {Configuration.PersistenceIdColumnName}, {Configuration.SequenceNrColumnName}, {Configuration.TimestampColumnName}, {Configuration.ManifestColumnName}, {Configuration.PayloadColumnName}) SELECT @PersistenceId, @SequenceNr, @Timestamp, @Manifest, @Payload WHERE NOT EXISTS (SELECT * FROM upsert)"; switch (configuration.StoredAs) { case StoredAsType.ByteA: _serialize = e => new KeyValuePair <NpgsqlDbType, object>(NpgsqlDbType.Bytea, serialization.FindSerializerFor(e).ToBinary(e)); _deserialize = (type, serialized) => serialization.FindSerializerForType(type).FromBinary((byte[])serialized, type); break; case StoredAsType.JsonB: _serialize = e => new KeyValuePair <NpgsqlDbType, object>(NpgsqlDbType.Jsonb, JsonConvert.SerializeObject(e, configuration.JsonSerializerSettings)); _deserialize = (type, serialized) => JsonConvert.DeserializeObject((string)serialized, type, configuration.JsonSerializerSettings); break; case StoredAsType.Json: _serialize = e => new KeyValuePair <NpgsqlDbType, object>(NpgsqlDbType.Json, JsonConvert.SerializeObject(e, configuration.JsonSerializerSettings)); _deserialize = (type, serialized) => JsonConvert.DeserializeObject((string)serialized, type, configuration.JsonSerializerSettings); break; default: throw new NotSupportedException($"{configuration.StoredAs} is not supported Db type for a payload"); } }
/// <summary> /// TBD /// </summary> /// <param name="command">TBD</param> /// <param name="e">TBD</param> /// <param name="tags">TBD</param> /// <returns>TBD</returns> protected virtual void WriteEvent(DbCommand command, IPersistentRepresentation e, IImmutableSet <string> tags) { var payloadType = e.Payload.GetType(); var serializer = Serialization.FindSerializerForType(payloadType, Configuration.DefaultSerializer); string manifest = ""; if (serializer is SerializerWithStringManifest) { manifest = ((SerializerWithStringManifest)serializer).Manifest(e.Payload); } else { if (serializer.IncludeManifest) { manifest = e.Payload.GetType().TypeQualifiedName(); } } var binary = serializer.ToBinary(e.Payload); AddParameter(command, "@PersistenceId", DbType.String, e.PersistenceId); AddParameter(command, "@SequenceNr", DbType.Int64, e.SequenceNr); AddParameter(command, "@Timestamp", DbType.Int64, TimestampProvider.GenerateTimestamp(e)); AddParameter(command, "@IsDeleted", DbType.Boolean, false); AddParameter(command, "@Manifest", DbType.String, manifest); AddParameter(command, "@Payload", DbType.Binary, binary); AddParameter(command, "@SerializerId", DbType.Int32, serializer.Identifier); if (tags.Count != 0) { var tagBuilder = new StringBuilder(";", tags.Sum(x => x.Length) + tags.Count + 1); foreach (var tag in tags) { tagBuilder.Append(tag).Append(';'); } AddParameter(command, "@Tag", DbType.String, tagBuilder.ToString()); } else { AddParameter(command, "@Tag", DbType.String, DBNull.Value); } }
protected override Try <JournalRow> Serialize(IPersistentRepresentation persistentRepr, IImmutableSet <string> tTags, long timeStamp = 0) { try { var serializer = _serializer.FindSerializerForType(persistentRepr.Payload.GetType(), _journalConfig.DefaultSerializer); // TODO: hack. Replace when https://github.com/akkadotnet/akka.net/issues/3811 string manifest = ""; var binary = Akka.Serialization.Serialization.WithTransport(_serializer.System, () => { if (serializer is SerializerWithStringManifest stringManifest) { manifest = stringManifest.Manifest(persistentRepr.Payload); } else { if (serializer.IncludeManifest) { manifest = persistentRepr.Payload.GetType().TypeQualifiedName(); } } return(serializer.ToBinary(persistentRepr.Payload)); }); return(new Try <JournalRow>(new JournalRow() { manifest = manifest, message = binary, persistenceId = persistentRepr.PersistenceId, tags = tTags.Any()? tTags.Aggregate((tl, tr) => tl + _separator + tr) : "", Identifier = serializer.Identifier, sequenceNumber = persistentRepr.SequenceNr, Timestamp = persistentRepr.Timestamp == 0? timeStamp: persistentRepr.Timestamp })); } catch (Exception e) { return(new Try <JournalRow>(e)); } }
protected override IPersistentRepresentation ReadEvent(DbDataReader reader) { var persistenceId = reader.GetString(PersistenceIdIndex); var sequenceNr = reader.GetInt64(SequenceNrIndex); var isDeleted = Convert.ToBoolean(reader.GetInt16(IsDeletedIndex)); var manifest = reader.GetString(ManifestIndex).Trim(); // HACK var payload = reader[PayloadIndex]; object deserialized; if (reader.IsDBNull(SerializerIdIndex)) { var type = Type.GetType(manifest, true); var deserializer = serialization.FindSerializerForType(type, Setup.DefaultSerializer); deserialized = deserializer.FromBinary((byte[])payload, type); } else { var serializerId = reader.GetInt32(SerializerIdIndex); deserialized = serialization.Deserialize((byte[])payload, serializerId, manifest); } return(new Persistent(deserialized, sequenceNr, persistenceId, manifest, isDeleted, ActorRefs.NoSender)); }
public LmdbDurableStore(Config config) { _config = config.GetConfig("lmdb"); if (_config.IsNullOrEmpty()) { throw ConfigurationException.NullOrEmptyConfig <LmdbDurableStore>("akka.cluster.distributed-data.durable.lmdb"); } _log = Context.GetLogger(); _serialization = Context.System.Serialization; _serializer = (SerializerWithStringManifest)_serialization.FindSerializerForType(typeof(DurableDataEnvelope)); _manifest = _serializer.Manifest(new DurableDataEnvelope(GCounter.Empty)); var useWriteBehind = _config.GetString("write-behind-interval", "").ToLowerInvariant(); _writeBehindInterval = useWriteBehind == "off" || useWriteBehind == "false" || useWriteBehind == "no" ? TimeSpan.Zero : _config.GetTimeSpan("write-behind-interval"); _mapSize = _config.GetByteSize("map-size") ?? 100 * 1024 * 1024; var path = _config.GetString("dir"); _dir = path.EndsWith(DatabaseName) ? Path.GetFullPath($"{path}-{Context.System.Name}-{Self.Path.Parent.Name}-{Cluster.Cluster.Get(Context.System).SelfAddress.Port}") : Path.GetFullPath(path); if (!Directory.Exists(_dir)) { Directory.CreateDirectory(_dir); } _log.Info($"Using durable data in LMDB directory [{_dir}]"); Init(); }
protected override Try <(IPersistentRepresentation, IImmutableSet <string>, long)> Deserialize(JournalRow t) { try { //object deserialized = null; var identifierMaybe = t.Identifier; if (identifierMaybe.HasValue == false) { var type = System.Type.GetType(t.manifest, true); // TODO: hack. Replace when https://github.com/akkadotnet/akka.net/issues/3811 return(new Try <(IPersistentRepresentation, IImmutableSet <string> , long)>(( new Persistent(Akka.Serialization.Serialization.WithTransport( _serializer.System, (_serializer.FindSerializerForType(type, _journalConfig.DefaultSerializer), t.message, type), (state) => { return state.Item1.FromBinary( state.message, state.type); }), t.sequenceNumber, t.persistenceId, t.manifest, t.deleted, ActorRefs.NoSender, null, t.Timestamp), t.tags?.Split(_separatorArray, StringSplitOptions.RemoveEmptyEntries) .ToImmutableHashSet() ?? ImmutableHashSet <string> .Empty, t.ordering))); } else { return(new Try <(IPersistentRepresentation, IImmutableSet <string> , long)>(( new Persistent(_serializer.Deserialize(t.message, identifierMaybe.Value, t.manifest), t.sequenceNumber, t.persistenceId, t.manifest, t.deleted, ActorRefs.NoSender, null, t.Timestamp), t.tags?.Split(_separatorArray, StringSplitOptions.RemoveEmptyEntries) .ToImmutableHashSet() ?? ImmutableHashSet <string> .Empty, t.ordering))); // TODO: hack. Replace when https://github.com/akkadotnet/akka.net/issues/3811 } } catch (Exception e) { return(new Try <(IPersistentRepresentation, IImmutableSet <string> , long)>(e)); } }