Beispiel #1
0
        public void Save(Guid batchId, IEnumerable <EventData> events)
        {
            lock (_lock)
            {
                var batch = events.ToList();

                bool isCorrupted;
                var  globalSequenceNumber = CommitLog.Read(out isCorrupted);
                if (isCorrupted)
                {
                    CommitLog.Recover();
                }

                GlobalSequenceIndex.DetectCorruptionAndRecover(DataStore, globalSequenceNumber);

                foreach (var domainEvent in batch)
                {
                    domainEvent.Meta[DomainEvent.MetadataKeys.GlobalSequenceNumber] = (++globalSequenceNumber).ToString(Metadata.NumberCulture);
                    domainEvent.Meta[DomainEvent.MetadataKeys.BatchId] = batchId.ToString();
                }

                EventValidation.ValidateBatchIntegrity(batchId, batch);

                GlobalSequenceIndex.Write(batch);
                DataStore.Write(batchId, batch);
                CommitLog.Write(globalSequenceNumber);
            }
        }
Beispiel #2
0
        public void Save(Guid batchId, IEnumerable <EventData> batch)
        {
            var nextGlobalSequenceNumber = GetNextGlobalSequenceNumber();

            var domainEventsList = batch.ToList();

            foreach (var domainEvent in domainEventsList)
            {
                domainEvent.Meta[DomainEvent.MetadataKeys.GlobalSequenceNumber] = (nextGlobalSequenceNumber++).ToString(Metadata.NumberCulture);
                domainEvent.Meta[DomainEvent.MetadataKeys.BatchId] = batchId.ToString();
            }

            EventValidation.ValidateBatchIntegrity(batchId, domainEventsList);

            var eventList = domainEventsList
                            .Select(e => new Event
            {
                GlobalSequenceNumber = e.GetGlobalSequenceNumber(),
                AggregateRootId      = e.GetAggregateRootId(),
                BatchId        = batchId,
                SequenceNumber = e.GetSequenceNumber(),
                Data           = e.Data,
                Meta           = Encoding.UTF8.GetBytes(_metadataSerializer.Serialize(e.Meta))
            })
                            .ToList();

            _connection.BeginTransaction();

            try
            {
                foreach (var e in eventList)
                {
                    _connection.Insert(e);
                }

                _connection.Commit();
            }
            catch (SQLiteException sqLiteException)
            {
                _connection.Rollback();

                if (sqLiteException.Result == SQLite3.Result.Constraint)
                {
                    throw new ConcurrencyException(batchId, domainEventsList, sqLiteException);
                }
            }
            catch (Exception)
            {
                _connection.Rollback();
                throw;
            }
        }
Beispiel #3
0
        public void Save(Guid batchId, IEnumerable <EventData> events)
        {
            var batch = events.ToList();

            if (!batch.Any())
            {
                throw new InvalidOperationException(string.Format("Attempted to save batch {0}, but the batch of events was empty!", batchId));
            }

            var nextGlobalSeqNo = GetNextGlobalSequenceNumber();

            foreach (var e in batch)
            {
                e.Meta[DomainEvent.MetadataKeys.GlobalSequenceNumber] = (nextGlobalSeqNo++).ToString(Metadata.NumberCulture);
                e.Meta[DomainEvent.MetadataKeys.BatchId] = batchId.ToString();
            }

            EventValidation.ValidateBatchIntegrity(batchId, batch);

            try
            {
                _eventBatches.Save(new MongoEventBatch
                {
                    BatchId = batchId.ToString(),
                    Events  = batch
                              .Select(b =>
                    {
                        var isJson = b.IsJson();

                        return(new MongoEvent
                        {
                            Meta = GetMetadataAsDictionary(b.Meta),
                            Bin = isJson ? null : b.Data,
                            Body = isJson ? GetBsonValue(b.Data) : null,
                            SequenceNumber = b.GetSequenceNumber(),
                            GlobalSequenceNumber = b.GetGlobalSequenceNumber(),
                            AggregateRootId = b.GetAggregateRootId()
                        });
                    })
                              .ToList()
                });
            }
            catch (MongoDuplicateKeyException exception)
            {
                throw new ConcurrencyException(batchId, batch, exception);
            }
        }
Beispiel #4
0
        public void Save(Guid batchId, IEnumerable <EventData> events)
        {
            var batch = events.ToList();

            var tuplesInBatch = batch
                                .Select(e => string.Format("{0}:{1}", e.GetAggregateRootId(), e.GetSequenceNumber()))
                                .ToList();

            lock (_lock)
            {
                var globalSequenceNumberToAssign = _globalSequenceNumber;

                foreach (var e in batch)
                {
                    e.Meta[DomainEvent.MetadataKeys.GlobalSequenceNumber] = globalSequenceNumberToAssign.ToString(Metadata.NumberCulture);
                    e.Meta[DomainEvent.MetadataKeys.BatchId] = batchId.ToString();

                    globalSequenceNumberToAssign++;
                }

                try
                {
                    foreach (var tuple in tuplesInBatch)
                    {
                        if (_idAndSeqNoTuples.Contains(tuple))
                        {
                            throw new InvalidOperationException(string.Format("Found duplicate event: {0}", tuple));
                        }
                    }

                    _globalSequenceNumber += batch.Count;
                }
                catch (Exception exception)
                {
                    throw new ConcurrencyException(batchId, batch, exception);
                }

                foreach (var tuple in tuplesInBatch)
                {
                    _idAndSeqNoTuples.Add(tuple);
                }

                EventValidation.ValidateBatchIntegrity(batchId, batch);

                _savedEventBatches.Add(new EventBatch(batchId, batch.Select(Clone)));
            }
        }
Beispiel #5
0
        public void Save(Guid batchId, IEnumerable <EventData> batch)
        {
            var eventList = batch.ToList();

            try
            {
                using (var connection = GetConnection())
                    using (var tx = connection.BeginTransaction())
                    {
                        var nextSequenceNumber = GetNextGlobalSequenceNumber(connection, tx);

                        foreach (var e in eventList)
                        {
                            e.Meta[DomainEvent.MetadataKeys.GlobalSequenceNumber] = (nextSequenceNumber++).ToString(Metadata.NumberCulture);
                            e.Meta[DomainEvent.MetadataKeys.BatchId] = batchId.ToString();
                        }

                        EventValidation.ValidateBatchIntegrity(batchId, eventList);

                        foreach (var e in eventList)
                        {
                            using (var cmd = connection.CreateCommand())
                            {
                                cmd.Transaction = tx;
                                cmd.CommandText = string.Format(@"

INSERT INTO ""{0}"" (
    ""batchId"",
    ""aggId"",
    ""seqNo"",
    ""globSeqNo"",
    ""data"",
    ""meta""
) VALUES (
    @batchId,
    @aggId,
    @seqNo,
    @globSeqNo,
    @data,
    @meta
)

", _tableName);


                                cmd.Parameters.AddWithValue("batchId", batchId);
                                cmd.Parameters.AddWithValue("aggId", e.GetAggregateRootId());
                                cmd.Parameters.AddWithValue("seqNo", e.Meta[DomainEvent.MetadataKeys.SequenceNumber]);
                                cmd.Parameters.AddWithValue("globSeqNo", e.Meta[DomainEvent.MetadataKeys.GlobalSequenceNumber]);
                                cmd.Parameters.AddWithValue("data", e.Data);
                                cmd.Parameters.AddWithValue("meta", Encoding.UTF8.GetBytes(_metadataSerializer.Serialize(e.Meta)));

                                cmd.ExecuteNonQuery();
                            }
                        }

                        tx.Commit();
                    }
            }
            catch (NpgsqlException exception)
            {
                if (exception.Code == "23505")
                {
                    throw new ConcurrencyException(batchId, eventList, exception);
                }

                throw;
            }
        }
Beispiel #6
0
        public void Save(Guid batchId, IEnumerable <EventData> events)
        {
            var eventList = events.ToList();

            try
            {
                WithConnection(conn =>
                {
                    using (var tx = conn.BeginTransaction())
                    {
                        var globalSequenceNumber = GetNextGlobalSequenceNumber(conn, tx);

                        foreach (var e in eventList)
                        {
                            e.Meta[DomainEvent.MetadataKeys.GlobalSequenceNumber] = (globalSequenceNumber++).ToString(Metadata.NumberCulture);
                            e.Meta[DomainEvent.MetadataKeys.BatchId] = batchId.ToString();
                        }

                        EventValidation.ValidateBatchIntegrity(batchId, eventList);

                        foreach (var batch in eventList.Batch(10))
                        {
                            var commandInfo = batch
                                              .Select((@event, index) => new
                            {
                                AggregateRootId               = @event.Meta[DomainEvent.MetadataKeys.AggregateRootId],
                                AggregateRootIdParameter      = string.Format("aggId{0}", index),
                                SequenceNumber                = @event.Meta[DomainEvent.MetadataKeys.SequenceNumber],
                                SequenceNumberParameter       = string.Format("seqNo{0}", index),
                                GlobalSequenceNumber          = @event.Meta[DomainEvent.MetadataKeys.GlobalSequenceNumber],
                                GlobalSequenceNumberParameter = string.Format("globSeqNo{0}", index),
                                Meta          = JsonConvert.SerializeObject(@event.Meta),
                                MetaParameter = string.Format("meta{0}", index),
                                Data          = @event.Data,
                                DataParameter = string.Format("data{0}", index),
                            })
                                              .ToList();

                            using (var cmd = conn.CreateCommand())
                            {
                                cmd.Transaction = tx;

                                var values = commandInfo.Select(s => string.Format(@"(@batchId,@{0},@{1},@{2},@{3},@{4})",
                                                                                   s.AggregateRootIdParameter,
                                                                                   s.SequenceNumberParameter,
                                                                                   s.GlobalSequenceNumberParameter,
                                                                                   s.MetaParameter,
                                                                                   s.DataParameter));

                                var sql =
                                    string.Format(@"INSERT INTO [{0}] (
    [batchId],
    [aggId],
    [seqNo],
    [globSeqNo],
    [meta],
    [data]
) VALUES 
{1}", _tableName, string.Join("," + Environment.NewLine, values));


                                cmd.CommandText = sql;

                                cmd.Parameters.Add("batchId", SqlDbType.UniqueIdentifier).Value = batchId;

                                foreach (var info in commandInfo)
                                {
                                    cmd.Parameters.Add(info.AggregateRootIdParameter, SqlDbType.NVarChar).Value    = info.AggregateRootId;
                                    cmd.Parameters.Add(info.SequenceNumberParameter, SqlDbType.BigInt).Value       = info.SequenceNumber;
                                    cmd.Parameters.Add(info.GlobalSequenceNumberParameter, SqlDbType.BigInt).Value = info.GlobalSequenceNumber;
                                    cmd.Parameters.Add(info.MetaParameter, SqlDbType.NVarChar).Value  = info.Meta;
                                    cmd.Parameters.Add(info.DataParameter, SqlDbType.VarBinary).Value = info.Data;
                                }

                                cmd.ExecuteNonQuery();
                            }

                            //using (var cmd = conn.CreateCommand())
//                            {
//                                cmd.Transaction = tx;
//                                cmd.CommandText = string.Format(@"

//INSERT INTO [{0}] (
//    [batchId],
//    [aggId],
//    [seqNo],
//    [globSeqNo],
//    [meta],
//    [data]
//) VALUES (
//    @batchId,
//    @aggId,
//    @seqNo,
//    @globSeqNo,
//    @meta,
//    @data
//)

//", _tableName);
//                                cmd.Parameters.Add("batchId", SqlDbType.UniqueIdentifier).Value = batchId;
//                                cmd.Parameters.Add("aggId", SqlDbType.NVarChar).Value = @event.Meta[DomainEvent.MetadataKeys.AggregateRootId];
//                                cmd.Parameters.Add("seqNo", SqlDbType.BigInt).Value = @event.Meta[DomainEvent.MetadataKeys.SequenceNumber];
//                                cmd.Parameters.Add("globSeqNo", SqlDbType.BigInt).Value = @event.Meta[DomainEvent.MetadataKeys.GlobalSequenceNumber];
//                                cmd.Parameters.Add("meta", SqlDbType.NVarChar).Value = JsonConvert.SerializeObject(@event.Meta);
//                                cmd.Parameters.Add("data", SqlDbType.VarBinary).Value = @event.Data;

//                                cmd.ExecuteNonQuery();
//                            }
                        }

                        tx.Commit();
                    }
                });
            }
            catch (SqlException sqlException)
            {
                if (sqlException.Errors.Cast <SqlError>().Any(e => e.Number == 2601))
                {
                    throw new ConcurrencyException(batchId, eventList, sqlException);
                }

                throw;
            }
        }
Beispiel #7
0
        public void Save(Guid batchId, IEnumerable <EventData> events)
        {
            var eventList = events.ToList();

            try
            {
                WithConnection(conn =>
                {
                    using (var tx = conn.BeginTransaction())
                    {
                        var globalSequenceNumber = GetNextGlobalSequenceNumber(conn, tx);

                        foreach (var e in eventList)
                        {
                            e.Meta[DomainEvent.MetadataKeys.GlobalSequenceNumber] = (globalSequenceNumber++).ToString(Metadata.NumberCulture);
                            e.Meta[DomainEvent.MetadataKeys.BatchId] = batchId.ToString();
                        }

                        EventValidation.ValidateBatchIntegrity(batchId, eventList);

                        foreach (var @event in eventList)
                        {
                            using (var cmd = conn.CreateCommand())
                            {
                                cmd.Transaction = tx;
                                cmd.CommandText = string.Format(@"

INSERT INTO [{0}] (
    [batchId],
    [aggId],
    [seqNo],
    [globSeqNo],
    [meta],
    [data]
) VALUES (
    @batchId,
    @aggId,
    @seqNo,
    @globSeqNo,
    @meta,
    @data
)

", _tableName);
                                cmd.Parameters.Add("batchId", SqlDbType.UniqueIdentifier).Value = batchId;
                                cmd.Parameters.Add("aggId", SqlDbType.NVarChar).Value           = @event.Meta[DomainEvent.MetadataKeys.AggregateRootId];
                                cmd.Parameters.Add("seqNo", SqlDbType.BigInt).Value             = @event.Meta[DomainEvent.MetadataKeys.SequenceNumber];
                                cmd.Parameters.Add("globSeqNo", SqlDbType.BigInt).Value         = @event.Meta[DomainEvent.MetadataKeys.GlobalSequenceNumber];
                                cmd.Parameters.Add("meta", SqlDbType.NVarChar).Value            = JsonConvert.SerializeObject(@event.Meta);
                                cmd.Parameters.Add("data", SqlDbType.VarBinary).Value           = @event.Data;

                                cmd.ExecuteNonQuery();
                            }
                        }

                        tx.Commit();
                    }
                });
            }
            catch (SqlException sqlException)
            {
                if (sqlException.Errors.Cast <SqlError>().Any(e => e.Number == 2601))
                {
                    throw new ConcurrencyException(batchId, eventList, sqlException);
                }

                throw;
            }
        }