コード例 #1
0
        public Task <OperateResult> DispatchAsync(MediumMessage message, CancellationToken cancellationToken)
        {
            var selector = _provider.GetService <MethodMatcherCache>();

            if (!selector.TryGetTopicExecutor(message.Origin.GetName(), message.Origin.GetGroup(), out var executor))
            {
                var error = $"Message (Name:{message.Origin.GetName()},Group:{message.Origin.GetGroup()}) can not be found subscriber." +
                            $"{Environment.NewLine} see: https://github.com/dotnetcore/CAP/issues/63";
                _logger.LogError(error);

                TracingError(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), message.Origin, null, new Exception(error));

                return(Task.FromResult(OperateResult.Failed(new SubscriberNotFoundException(error))));
            }

            return(DispatchAsync(message, executor, cancellationToken));
        }
コード例 #2
0
ファイル: IDataStorage.MySql.cs プロジェクト: wangronghua/CAP
        public MediumMessage StoreMessage(string name, Message content, object dbTransaction = null)
        {
            var sql = $"INSERT INTO `{_pubName}`(`Id`,`Version`,`Name`,`Content`,`Retries`,`Added`,`ExpiresAt`,`StatusName`)" +
                      $" VALUES(@Id,'{_options.Value.Version}',@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName);";

            var message = new MediumMessage
            {
                DbId      = content.GetId(),
                Origin    = content,
                Content   = _serializer.Serialize(content),
                Added     = DateTime.Now,
                ExpiresAt = null,
                Retries   = 0
            };

            object[] sqlParams =
            {
                new MySqlParameter("@Id",         message.DbId),
                new MySqlParameter("@Name",       name),
                new MySqlParameter("@Content",    message.Content),
                new MySqlParameter("@Retries",    message.Retries),
                new MySqlParameter("@Added",      message.Added),
                new MySqlParameter("@ExpiresAt",  message.ExpiresAt.HasValue ? (object)message.ExpiresAt.Value : DBNull.Value),
                new MySqlParameter("@StatusName", nameof(StatusName.Scheduled)),
            };

            if (dbTransaction == null)
            {
                using var connection = new MySqlConnection(_options.Value.ConnectionString);
                connection.ExecuteNonQuery(sql, sqlParams: sqlParams);
            }
            else
            {
                var dbTrans = dbTransaction as IDbTransaction;
                if (dbTrans == null && dbTransaction is IDbContextTransaction dbContextTrans)
                {
                    dbTrans = dbContextTrans.GetDbTransaction();
                }

                var conn = dbTrans?.Connection ?? new MySqlConnection(_options.Value.ConnectionString);
                conn.ExecuteNonQuery(sql, dbTrans, sqlParams);
            }

            return(message);
        }
コード例 #3
0
        public MediumMessage StoreMessage(string name, Message content, object dbTransaction = null)
        {
            var sql = $"INSERT INTO {_pubName} ([Id],[Version],[Name],[Content],[Retries],[Added],[ExpiresAt],[StatusName])" +
                      $"VALUES(@Id,'{_options.Value.Version}',@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName);";

            var message = new MediumMessage
            {
                DbId      = content.GetId(),
                Origin    = content,
                Content   = _serializer.Serialize(content),
                Added     = DateTime.Now,
                ExpiresAt = null,
                Retries   = 0
            };

            var po = new
            {
                Id   = message.DbId,
                Name = name,
                message.Content,
                message.Retries,
                message.Added,
                message.ExpiresAt,
                StatusName = nameof(StatusName.Scheduled)
            };

            if (dbTransaction == null)
            {
                var connection = this.DbConnection;
                connection.Execute(sql, po, DbTransaction);
            }
            else
            {
                var dbTrans = dbTransaction as IDbTransaction;
                if (dbTrans == null && dbTransaction is IDbContextTransaction dbContextTrans)
                {
                    dbTrans = dbContextTrans.GetDbTransaction();
                }

                var conn = dbTrans?.Connection;
                conn.Execute(sql, po, dbTrans);
            }

            return(message);
        }
コード例 #4
0
        public MediumMessage StoreMessage(string name, Message content, object dbTransaction = null)
        {
            var sql = $"INSERT INTO `{_initializer.GetPublishedTableName()}`(`Id`,`Version`,`Name`,`Content`,`Retries`,`Added`,`ExpiresAt`,`StatusName`) VALUES(@Id,'{_options.Value.Version}',@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName);";

            var message = new MediumMessage
            {
                DbId      = content.GetId(),
                Origin    = content,
                Content   = StringSerializer.Serialize(content),
                Added     = DateTime.Now,
                ExpiresAt = null,
                Retries   = 0
            };

            var po = new
            {
                Id   = message.DbId,
                Name = name,
                message.Content,
                message.Retries,
                message.Added,
                message.ExpiresAt,
                StatusName = nameof(StatusName.Scheduled)
            };

            if (dbTransaction == null)
            {
                using var connection = new MySqlConnection(_options.Value.ConnectionString);
                connection.Execute(sql, po);
            }
            else
            {
                var dbTrans = dbTransaction as IDbTransaction;

                if (dbTransaction is IUnitOfWork unitOfWork)
                {
                    dbTrans = unitOfWork.GetOrBeginTransaction();
                }

                var conn = dbTrans?.Connection;
                conn.Execute(sql, po, dbTrans);
            }

            return(message);
        }
コード例 #5
0
        public MediumMessage StoreMessage(string name, Message content, object dbTransaction = null)
        {
            var sql =
                $"INSERT INTO {_pubName} (\"Id\",\"Version\",\"Name\",\"Content\",\"Retries\",\"Added\",\"ExpiresAt\",\"StatusName\")" +
                $"VALUES(@Id,'{_options.Value.Version}',@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName);";

            var message = new MediumMessage
            {
                DbId      = content.GetId(),
                Origin    = content,
                Content   = StringSerializer.Serialize(content),
                Added     = DateTime.Now,
                ExpiresAt = null,
                Retries   = 0
            };

            var po = new
            {
                Id   = long.Parse(message.DbId),
                Name = name,
                message.Content,
                message.Retries,
                message.Added,
                message.ExpiresAt,
                StatusName = nameof(StatusName.Scheduled)
            };

            if (dbTransaction == null)
            {
                this.DbConnection.Execute(sql, po, transaction: DbTransaction);
            }
            else
            {
                var dbTrans = dbTransaction as IDbTransaction;
                if (dbTrans == null && dbTransaction is IDbContextTransaction dbContextTrans)
                {
                    dbTrans = dbContextTrans.GetDbTransaction();
                }

                var conn = dbTrans?.Connection;
                conn.Execute(sql, po, dbTrans);
            }

            return(message);
        }
コード例 #6
0
        public MediumMessage StoreMessage(string name, Message content, object dbTransaction = null)
        {
            var message = new MediumMessage
            {
                DbId      = content.GetId(),
                Origin    = content,
                Content   = System.Text.Json.JsonSerializer.Serialize(content),
                Added     = DateTime.Now,
                ExpiresAt = null,
                Retries   = 0
            };

            var sql = $"INSERT INTO \"{_pubName}\"(\"Id\",\"Version\",\"Name\",\"Content\",\"Retries\",\"Added\",\"ExpiresAt\",\"StatusName\")" +
                      $" VALUES(:P_Id,'{_options.Value.Version}',:P_Name,:P_Content,:P_Retries,:P_Added,:P_ExpiresAt,:P_StatusName)";

            object[] sqlParams =
            {
                new OracleParameter(":P_Id",         message.DbId),
                new OracleParameter(":P_Name",       name),
                new OracleParameter(":P_Content",    message.Content),
                new OracleParameter(":P_Retries",    message.Retries),
                new OracleParameter(":P_Added",      message.Added),
                new OracleParameter(":P_ExpiresAt",  message.ExpiresAt.HasValue ? (object)message.ExpiresAt.Value : DBNull.Value),
                new OracleParameter(":P_StatusName", nameof(StatusName.Scheduled)),
            };

            if (dbTransaction == null)
            {
                using var connection = new OracleConnection(_options.Value.ConnectionString);
                connection.ExecuteNonQuery(sql, sqlParams: sqlParams);
            }
            else
            {
                var dbTrans = dbTransaction as IDbTransaction;
                if (dbTrans == null && dbTransaction is IDbContextTransaction dbContextTrans)
                {
                    dbTrans = dbContextTrans.GetDbTransaction();
                }

                var conn = dbTrans?.Connection;
                conn.ExecuteNonQuery(sql, dbTrans, sqlParams);
            }

            return(message);
        }
コード例 #7
0
        private async Task <bool> SetFailedState(MediumMessage message, Exception ex)
        {
            if (ex is SubscriberNotFoundException)
            {
                message.Retries = _options.FailedRetryCount; // not retry if SubscriberNotFoundException
            }

            //TODO: Add exception to content
            // AddErrorReasonToContent(message, ex);

            var needRetry = UpdateMessageForRetry(message);

            message.ExpiresAt = message.Added.AddDays(15);

            await _dataStorage.ChangeReceiveStateAsync(message, StatusName.Failed);

            return(needRetry);
        }
コード例 #8
0
        private async Task ChangeMessageStateAsync(string tableName, MediumMessage message, StatusName state)
        {
            var sql =
                $"UPDATE {tableName} SET \"Retries\"=@Retries,\"ExpiresAt\"=@ExpiresAt,\"StatusName\"=@StatusName WHERE \"Id\"=@Id";

            object[] sqlParams =
            {
                new NpgsqlParameter("@Id",         long.Parse(message.DbId)),
                new NpgsqlParameter("@Retries",    message.Retries),
                new NpgsqlParameter("@ExpiresAt",  message.ExpiresAt),
                new NpgsqlParameter("@StatusName", state.ToString("G"))
            };

            await using var connection = new NpgsqlConnection(_options.Value.ConnectionString);
            connection.ExecuteNonQuery(sql, sqlParams: sqlParams);

            await Task.CompletedTask;
        }
コード例 #9
0
        public async Task <OperateResult> SendAsync(MediumMessage message)
        {
            bool          retry;
            OperateResult result;

            do
            {
                var executedResult = await SendWithoutRetryAsync(message);

                result = executedResult.Item2;
                if (result == OperateResult.Success)
                {
                    return(result);
                }
                retry = executedResult.Item1;
            } while (retry);

            return(result);
        }
コード例 #10
0
        private async Task ChangeMessageStateAsync(string tableName, MediumMessage message, StatusName state)
        {
            var sql = $"UPDATE `{tableName}` SET `Retries`=@Retries,`ExpiresAt`=@ExpiresAt,`StatusName`=@StatusName WHERE `Id`=@Id";

            object[] sqlParams =
            {
                new SqliteParameter("@Retries",    message.Retries),
                new SqliteParameter("@ExpiresAt",  message.ExpiresAt.HasValue?(object)message.ExpiresAt:DBNull.Value),
                new SqliteParameter("@StatusName", state.ToString("G")),
                new SqliteParameter("@Id",         long.Parse(message.DbId))
            };

            using var connection        = SqliteFactory.Instance.CreateConnection();
            connection.ConnectionString = _options.Value.ConnectionString;

            connection.ExecuteNonQuery(sql, sqlParams: sqlParams);

            await Task.CompletedTask;
        }
コード例 #11
0
        private async Task ChangeMessageStateAsync(string tableName, MediumMessage message, StatusName state)
        {
            var sql =
                $"UPDATE {tableName} SET Content=@Content, Retries=@Retries,ExpiresAt=@ExpiresAt,StatusName=@StatusName WHERE Id=@Id";

            object[] sqlParams =
            {
                new SqlParameter("@Id",         message.DbId),
                new SqlParameter("@Content",    _serializer.Serialize(message.Origin)),
                new SqlParameter("@Retries",    message.Retries),
                new SqlParameter("@ExpiresAt",  message.ExpiresAt),
                new SqlParameter("@StatusName", state.ToString("G"))
            };

            using var connection = new SqlConnection(_options.Value.ConnectionString);
            connection.ExecuteNonQuery(sql, sqlParams: sqlParams);

            await Task.CompletedTask;
        }
コード例 #12
0
        public async Task <OperateResult> DispatchAsync(MediumMessage message, ConsumerExecutorDescriptor descriptor, CancellationToken cancellationToken)
        {
            bool          retry;
            OperateResult result;

            do
            {
                var executedResult = await ExecuteWithoutRetryAsync(message, descriptor, cancellationToken);

                result = executedResult.Item2;
                if (result == OperateResult.Success)
                {
                    return(result);
                }
                retry = executedResult.Item1;
            } while (retry);

            return(result);
        }
コード例 #13
0
        public MediumMessage StoreMessage(string name, Message content, object dbTransaction = null)
        {
            var insertOptions = new InsertOneOptions {
                BypassDocumentValidation = false
            };

            var message = new MediumMessage
            {
                DbId      = content.GetId(),
                Origin    = content,
                Content   = _serializer.Serialize(content),
                Added     = DateTime.Now,
                ExpiresAt = null,
                Retries   = 0
            };

            var collection = _database.GetCollection <PublishedMessage>(_options.Value.PublishedCollection);

            var store = new PublishedMessage
            {
                Id         = long.Parse(message.DbId),
                Name       = name,
                Content    = message.Content,
                Added      = message.Added,
                StatusName = nameof(StatusName.Scheduled),
                ExpiresAt  = message.ExpiresAt,
                Retries    = message.Retries,
                Version    = _options.Value.Version
            };

            if (dbTransaction == null)
            {
                collection.InsertOne(store, insertOptions);
            }
            else
            {
                var dbTrans = dbTransaction as IClientSessionHandle;
                collection.InsertOne(dbTrans, store, insertOptions);
            }

            return(message);
        }
コード例 #14
0
        protected override void AddToSent(MediumMessage msg)
        {
            if (DbTransaction is NoopTransaction)
            {
                base.AddToSent(msg);
                return;
            }

            var dbTransaction = DbTransaction as IDbTransaction;

            if (dbTransaction == null)
            {
                if (DbTransaction is IDbContextTransaction dbContextTransaction)
                {
                    dbTransaction = dbContextTransaction.GetDbTransaction();
                }

                if (dbTransaction == null)
                {
                    throw new ArgumentNullException(nameof(DbTransaction));
                }
            }

            var transactionKey = ((SqlConnection)dbTransaction.Connection).ClientConnectionId;

            if (_diagnosticProcessor.BufferList.TryGetValue(transactionKey, out var list))
            {
                list.Add(msg);
            }
            else
            {
                var msgList = new List <MediumMessage>(1)
                {
                    msg
                };
                _diagnosticProcessor.BufferList.TryAdd(transactionKey, msgList);
            }
        }
コード例 #15
0
        /// <summary>
        /// 新增消息记录
        /// </summary>
        /// <param name="message"></param>
        /// <param name="dbTransaction"></param>
        public void StoreMessage(MediumMessage message, object dbTransaction = null)
        {
            object[] sqlParams =
            {
                new SqlParameter("@Id",          message.Id),
                new SqlParameter("@Version",     message.Version),
                new SqlParameter("@MessageType", message.MessageType),
                new SqlParameter("@MessageData", message.MessageData),
                new SqlParameter("@CreateTime",  message.CreateTime),
                new SqlParameter("@UtcTime",     message.UtcTime)
            };

            var sql = $@"INSERT INTO {GetTableName()} ([Id],[Version],[MessageType],[MessageData],[CreateTime],[UtcTime]) 
VALUES (@id,@Version,@MessageType,@MessageData,@CreateTime,@UtcTime);";

            if (dbTransaction == null)
            {
                using var connection = new SqlConnection(_options.Value.DbConnection);
                connection.ExecuteNonQuery(sql, sqlParams: sqlParams);
                _logger.LogInformation($"insert message in {GetTableName()} table successfully. messageId={message.Id}");
            }
            else
            {
                IDbTransaction dbTrans = null;
                switch (dbTransaction)
                {
                case IDbTransaction dbTran:
                    dbTrans = dbTran;
                    break;

                case IDbContextTransaction dbContextTransaction:
                    dbTrans = dbContextTransaction.GetDbTransaction();
                    break;
                }
                var conn = dbTrans?.Connection;
                conn?.ExecuteNonQuery(sql, dbTrans, sqlParams);
            }
        }
コード例 #16
0
ファイル: IDataStorage.LiteDB.cs プロジェクト: maikebing/CAP
        public MediumMessage StoreMessage(string name, Message content, object dbTransaction = null)
        {
            var message = new MediumMessage
            {
                DbId      = content.GetId(),
                Origin    = content,
                Content   = StringSerializer.Serialize(content),
                Added     = DateTime.Now,
                ExpiresAt = null,
                Retries   = 0
            };

            PublishedMessages.Insert(new LiteDBMessage()
            {
                Id         = message.DbId,
                Name       = name,
                Content    = message.Content,
                Retries    = message.Retries,
                Added      = message.Added,
                ExpiresAt  = message.ExpiresAt,
                StatusName = StatusName.Scheduled
            });
            return(message);
        }
コード例 #17
0
ファイル: IDataStorage.LiteDB.cs プロジェクト: maikebing/CAP
        public MediumMessage StoreReceivedMessage(string name, string @group, Message message)
        {
            var mdMessage = new MediumMessage
            {
                DbId      = SnowflakeId.Default().NextId().ToString(),
                Origin    = message,
                Added     = DateTime.Now,
                ExpiresAt = null,
                Retries   = 0
            };

            ReceivedMessages.Insert(new LiteDBMessage(mdMessage.Origin)
            {
                Id         = mdMessage.DbId,
                Group      = group,
                Name       = name,
                Content    = StringSerializer.Serialize(mdMessage.Origin),
                Retries    = mdMessage.Retries,
                Added      = mdMessage.Added,
                ExpiresAt  = mdMessage.ExpiresAt,
                StatusName = StatusName.Scheduled
            });
            return(mdMessage);
        }
コード例 #18
0
 public void EnqueueToExecute(MediumMessage message, ConsumerExecutorDescriptor descriptor)
 {
 }
コード例 #19
0
 public async Task ChangePublishStateAsync(MediumMessage message, StatusName state) =>
 await _capRepository.ChangeMessageStateAsync(_pubName, message.DbId, message.Retries, message.ExpiresAt,
                                              state.ToString("G"));
コード例 #20
0
ファイル: ICapTransaction.Base.cs プロジェクト: zcf7822/CAP
 protected internal virtual void AddToSent(MediumMessage msg)
 {
     _bufferList.Enqueue(msg);
 }
コード例 #21
0
 public async Task ChangeReceiveStateAsync(MediumMessage message, StatusName state) =>
 await _capRepository.ChangeMessageStateAsync(_recName, message.DbId, message.Retries, message.ExpiresAt,
                                              state.ToString("G"), _serializer.Serialize(message.Origin));
コード例 #22
0
 public LiteDBMessage(MediumMessage message)
 {
     _message = message;
 }
コード例 #23
0
 private async Task SetSuccessfulState(MediumMessage message)
 {
     message.ExpiresAt = DateTime.Now.AddSeconds(_options.Value.SucceedMessageExpiredAfter);
     await _dataStorage.ChangePublishStateAsync(message, StatusName.Succeeded);
 }
コード例 #24
0
        private void RegisterMessageProcessor(IConsumerClient client)
        {
            client.OnMessageReceived += async delegate(object sender, TransportMessage transportMessage)
            {
                long?tracingTimestamp = null;
                try
                {
                    tracingTimestamp = TracingBefore(transportMessage, _serverAddress);
                    string name  = transportMessage.GetName();
                    string group = transportMessage.GetGroup();
                    ConsumerExecutorDescriptor executor;
                    bool    canFindSubscriber = _selector.TryGetTopicExecutor(name, group, out executor);
                    Message message;
                    try
                    {
                        if (!canFindSubscriber)
                        {
                            SubscriberNotFoundException ex = new SubscriberNotFoundException("Message can not be found subscriber. Name:" + name + ", Group:" + group + ". " + " see: https://github.com/dotnetcore/CAP/issues/63");
                            TracingError(tracingTimestamp, transportMessage, client.BrokerAddress, ex);
                            throw ex;
                        }
                        Type type = Enumerable.FirstOrDefault <ParameterDescriptor>((IEnumerable <ParameterDescriptor>)executor.Parameters, (Func <ParameterDescriptor, bool>)((ParameterDescriptor x) => !x.IsFromCap))?.ParameterType;
                        message = await _serializer.DeserializeAsync(transportMessage, type);

                        message.RemoveException();
                    }
                    catch (Exception e3)
                    {
                        transportMessage.Headers.Add("cap-exception", "SerializationException-->" + e3.Message);
                        if (transportMessage.Headers.TryGetValue("cap-msg-type", out var val))
                        {
                            string dataUri2 = "data:" + val + ";base64," + Convert.ToBase64String(transportMessage.Body);
                            message = new Message(transportMessage.Headers, dataUri2);
                        }
                        else
                        {
                            string dataUri = "data:UnknownType;base64," + Convert.ToBase64String(transportMessage.Body);
                            message = new Message(transportMessage.Headers, dataUri);
                        }
                    }
                    if (message.HasException())
                    {
                        string content = _serializer.Serialize(message);
                        _storage.StoreReceivedExceptionMessage(name, group, content);
                        client.Commit(sender);
                        try
                        {
                            _options.FailedThresholdCallback?.Invoke(new FailedInfo
                            {
                                ServiceProvider = _serviceProvider,
                                MessageType     = MessageType.Subscribe,
                                Message         = message
                            });
                        }
                        catch (Exception e2)
                        {
                        }
                        TracingAfter(tracingTimestamp, transportMessage, _serverAddress);
                    }
                    else
                    {
                        MediumMessage mediumMessage = _storage.StoreReceivedMessage(name, group, message);
                        mediumMessage.Origin = message;

                        TracingAfter(tracingTimestamp, transportMessage, _serverAddress);
                        _dispatcher.EnqueueToExecute(mediumMessage, executor);
                        client.Commit(sender);
                    }
                }
                catch (Exception e)
                {
                    _logger.LogError(e, "An exception occurred when process received message. Message:'{0}'.", transportMessage);
                    client.Reject(sender);
                    TracingError(tracingTimestamp, transportMessage, client.BrokerAddress, e);
                }
            };
            client.OnLog += WriteLog;
        }
コード例 #25
0
 public LiteDBMessage()
 {
     _message        = new MediumMessage();
     _message.Origin = null;
 }
コード例 #26
0
 private Task SetSuccessfulState(MediumMessage message)
 {
     message.ExpiresAt = DateTime.Now.AddSeconds(_options.SucceedMessageExpiredAfter);
     return(_dataStorage.ChangeReceiveStateAsync(message, StatusName.Succeeded));
 }
コード例 #27
0
 public Task ChangeReceiveStateAsync(MediumMessage message, StatusName state)
 {
     ReceivedMessages[message.DbId].StatusName = state;
     ReceivedMessages[message.DbId].ExpiresAt  = message.ExpiresAt;
     return(Task.CompletedTask);
 }
コード例 #28
0
 public async Task ChangePublishStateAsync(MediumMessage message, StatusName state) =>
 await ChangeMessageStateAsync(_pubName, message, state);
コード例 #29
0
 public async Task ChangeReceiveStateAsync(MediumMessage message, StatusName state) =>
 await ChangeMessageStateAsync(_recName, message, state);
コード例 #30
0
 public void EnqueueToPublish(MediumMessage message)
 {
 }