Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        /// <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);
        }
Esempio n. 3
0
        /// <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);
        }
Esempio n. 4
0
        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));
        }
Esempio n. 5
0
        /// <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);
            }
        }
Esempio n. 6
0
        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));
            }
        }
Esempio n. 7
0
        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");
            }
        }
Esempio n. 8
0
        /// <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));
        }
Esempio n. 11
0
        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();
        }
Esempio n. 12
0
        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));
            }
        }