Пример #1
0
        private async ValueTask FlowProcess()
        {
            var start     = DateTime.UtcNow;
            var wrapList  = new List <EventBytesTransactionWrap <K> >();
            var documents = new List <MongoEvent <K> >();

            while (EventSaveFlowChannel.TryReceive(out var evt))
            {
                wrapList.Add(evt);
                documents.Add(new MongoEvent <K>
                {
                    Id       = new ObjectId(),
                    StateId  = evt.Value.StateId,
                    Version  = evt.Value.Version,
                    TypeCode = evt.Value.GetType().FullName,
                    Data     = evt.Bytes,
                    UniqueId = string.IsNullOrEmpty(evt.UniqueId) ? evt.Value.Version.ToString() : evt.UniqueId
                });
                if ((DateTime.UtcNow - start).TotalMilliseconds > 100)
                {
                    break;                                                   //保证批量延时不超过100ms
                }
            }
            var collectionTask = grainConfig.GetCollection(DateTime.UtcNow);

            if (!collectionTask.IsCompleted)
            {
                await collectionTask;
            }
            var collection = grainConfig.Storage.GetCollection <MongoEvent <K> >(grainConfig.DataBase, collectionTask.Result.Name);

            wrapList.ForEach(wrap => wrap.TaskSource.TrySetResult(true));
            try
            {
                await collection.InsertManyAsync(documents);

                wrapList.ForEach(wrap => wrap.TaskSource.TrySetResult(true));
            }
            catch
            {
                foreach (var w in wrapList)
                {
                    try
                    {
                        await collection.InsertOneAsync(new MongoEvent <K>
                        {
                            Id       = new ObjectId(),
                            StateId  = w.Value.StateId,
                            Version  = w.Value.Version,
                            TypeCode = w.Value.GetType().FullName,
                            Data     = w.Bytes,
                            UniqueId = string.IsNullOrEmpty(w.UniqueId) ? w.Value.Version.ToString() : w.UniqueId
                        });

                        w.TaskSource.TrySetResult(true);
                    }
                    catch (MongoWriteException ex)
                    {
                        if (ex.WriteError.Category != ServerErrorCategory.DuplicateKey)
                        {
                            w.TaskSource.TrySetException(ex);
                        }
                        else
                        {
                            w.TaskSource.TrySetResult(false);
                        }
                    }
                }
            }
        }
Пример #2
0
        public async Task <bool> SaveAsync(IEventBase <K> data, byte[] bytes, string uniqueId = null)
        {
            var mEvent = new MongoEvent <K>
            {
                StateId  = data.StateId,
                Version  = data.Version,
                TypeCode = data.TypeCode,
                Data     = bytes
            };

            mEvent.Id = data.Id;
            if (string.IsNullOrEmpty(uniqueId))
            {
                mEvent.MsgId = mEvent.Id;
            }
            else
            {
                mEvent.MsgId = uniqueId;
            }
            try
            {
                await mongoStorage.GetCollection <MongoEvent <K> >(grainConfig.EventDataBase, grainConfig.GetCollection(mongoStorage, mongoStorage.Config.SysStartTime, data.Timestamp).Name).InsertOneAsync(mEvent);

                return(true);
            }
            catch (MongoWriteException ex)
            {
                if (ex.WriteError.Category != ServerErrorCategory.DuplicateKey)
                {
                    throw ex;
                }
                else
                {
                    logger.LogError(ex, $"事件重复插入,Event:{Newtonsoft.Json.JsonConvert.SerializeObject(data)}");
                }
            }
            return(false);
        }