Exemple #1
0
        public void UpdateMessage(CapPublishedMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var sql =
                $"UPDATE [{_schema}].[Published] SET [Retries] = @Retries,[Content] = @Content,[ExpiresAt] = @ExpiresAt,[StatusName]=@StatusName WHERE Id=@Id;";

            _dbConnection.Execute(sql, message);
        }
Exemple #2
0
        public void UpdateMessage(CapPublishedMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var sql =
                $@"UPDATE ""{_schema}"".""published"" SET ""Retries""=@Retries,""Content""= @Content,""ExpiresAt""=@ExpiresAt,""StatusName""=@StatusName WHERE ""Id""=@Id;";

            _dbConnection.Execute(sql, message, _dbTransaction);
        }
Exemple #3
0
        public void Publish <T>(string name, T contentObj, string callbackName = null)
        {
            var message = new CapPublishedMessage
            {
                Id         = SnowflakeId.Default().NextId(),
                Name       = name,
                Content    = Serialize(contentObj, callbackName),
                StatusName = StatusName.Scheduled
            };

            PublishAsyncInternal(message).GetAwaiter().GetResult();
        }
        public void UpdateMessage(CapPublishedMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var sql =
                $"UPDATE `{_prefix}.published` SET `Retries` = @Retries,`Content`= @Content,`ExpiresAt` = @ExpiresAt,`StatusName`=@StatusName WHERE `Id`=@Id;";

            _dbConnection.Execute(sql, message);
        }
Exemple #5
0
        public async Task PublishAsync <T>(string name, T contentObj, string callbackName = null,
                                           CancellationToken cancellationToken            = default(CancellationToken))
        {
            var message = new CapPublishedMessage
            {
                Id         = SnowflakeId.Default().NextId(),
                Name       = name,
                Content    = Serialize(contentObj, callbackName),
                StatusName = StatusName.Scheduled
            };

            await PublishAsyncInternal(message);
        }
        public void EnqueueMessage(CapPublishedMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var sql = $"INSERT INTO `{_prefix}.queue` values(@MessageId,@MessageType);";

            _dbConnection.Execute(sql, new CapQueue {
                MessageId = message.Id, MessageType = MessageType.Publish
            }, _dbTransaction);
        }
Exemple #7
0
        private void PublishWithTrans <T>(string name, T contentObj, string callbackName = null) where T : FlowContext
        {
            Guid operationId = default(Guid);

            var content   = Serialize(contentObj, callbackName);
            var eventName = name;

            if (contentObj.Direction == FlowDirection.Backward)
            {
                eventName = QueryRollbackEventName(DbConnection, DbTransaction, contentObj.CorrelationId, contentObj.Step).GetAwaiter().GetResult();
                if (string.IsNullOrEmpty(eventName) && contentObj.Step > 1)
                {
                    throw new Exception();
                }
                eventName += ".Completed";
            }


            var message = new CapPublishedMessage
            {
                Name          = eventName,
                Content       = content,
                StatusName    = StatusName.Scheduled,
                CorrelationId = contentObj.CorrelationId,
                Step          = contentObj.Step
            };

            try
            {
                operationId = s_diagnosticListener.WritePublishMessageStoreBefore(message);

                var id = Execute(DbConnection, DbTransaction, message);

                ClosedCap();

                if (id > 0)
                {
                    _logger.LogInformation($"message [{message}] has been persisted in the database.");
                    s_diagnosticListener.WritePublishMessageStoreAfter(operationId, message);
                    message.Id = id;
                    Enqueue(message);
                }
            }
            catch (Exception e)
            {
                _logger.LogError("An exception was occurred when publish message. exception message:" + e.Message, e);
                s_diagnosticListener.WritePublishMessageStoreError(operationId, message, e);
                Console.WriteLine(e);
                throw;
            }
        }
Exemple #8
0
        private async Task PublishWithTrans(string name, string content, IDbConnection dbConnection, IDbTransaction dbTransaction)
        {
            var message = new CapPublishedMessage
            {
                Name       = name,
                Content    = content,
                StatusName = StatusName.Scheduled
            };

            var sql = $"INSERT INTO {_options.Schema}.[Published] ([Name],[Content],[Retries],[Added],[ExpiresAt],[StatusName])VALUES(@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName)";
            await dbConnection.ExecuteAsync(sql, message, transaction : dbTransaction);

            PublishQueuer.PulseEvent.Set();
        }
Exemple #9
0
        private async Task PublishWithTransAsync(string name, string content)
        {
            var message = new CapPublishedMessage
            {
                Name       = name,
                Content    = content,
                StatusName = StatusName.Scheduled
            };

            await ExecuteAsync(DbConnection, DbTransaction, message);

            ClosedCap();

            PublishQueuer.PulseEvent.Set();
        }
Exemple #10
0
        private void PublishWithTrans(string name, string content)
        {
            var message = new CapPublishedMessage
            {
                Name       = name,
                Content    = content,
                StatusName = StatusName.Scheduled
            };

            Execute(DbConnection, DbTranasaction, message);

            ClosedCap();

            PublishQueuer.PulseEvent.Set();
        }
Exemple #11
0
        private Task SetFailedState(CapPublishedMessage message, Exception ex, out bool stillRetry)
        {
            IState newState = new FailedState();

            stillRetry = UpdateMessageForRetryAsync(message);
            if (stillRetry)
            {
                _logger.ConsumerExecutionFailedWillRetry(ex);
                return(Task.CompletedTask);
            }

            AddErrorReasonToContent(message, ex);

            return(_stateChanger.ChangeStateAsync(message, newState, _connection));
        }
Exemple #12
0
        public void UpdateMessage(CapPublishedMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

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

            var updateDef = Builders <CapPublishedMessage> .Update
                            .Set(x => x.Retries, message.Retries)
                            .Set(x => x.Content, message.Content)
                            .Set(x => x.ExpiresAt, message.ExpiresAt)
                            .Set(x => x.StatusName, message.StatusName);

            collection.FindOneAndUpdate(_session, x => x.Id == message.Id, updateDef);
        }
        public void ChangeState(CapPublishedMessage message, IState state, IStorageTransaction transaction)
        {
            var now = DateTime.Now;

            if (state.ExpiresAfter != null)
            {
                message.ExpiresAt = now.Add(state.ExpiresAfter.Value);
            }
            else
            {
                message.ExpiresAt = null;
            }

            message.StatusName = state.Name;
            state.Apply(message, transaction);
            transaction.UpdateMessage(message);
        }
Exemple #14
0
        private static bool UpdateMessageForRetryAsync(CapPublishedMessage message)
        {
            var retryBehavior = RetryBehavior.DefaultRetry;

            var retries = ++message.Retries;

            if (retries >= retryBehavior.RetryCount)
            {
                return(false);
            }

            var due = message.Added.AddSeconds(retryBehavior.RetryIn(retries));

            message.ExpiresAt = due;

            return(true);
        }
        public void UpdateMessage(CapPublishedMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var msg = _connection.PublishedMessages.FirstOrDefault(x => message.Id == x.Id);

            if (msg == null)
            {
                return;
            }
            msg.Retries    = message.Retries;
            msg.Content    = message.Content;
            msg.ExpiresAt  = message.ExpiresAt;
            msg.StatusName = message.StatusName;
        }
        private void TracingError(Guid operationId, CapPublishedMessage message, OperateResult result, DateTimeOffset startTime, TimeSpan du)
        {
            var ex = new PublisherSentFailedException(result.ToString(), result.Exception);

            _logger.MessagePublishException(message.Id, result.ToString(), ex);

            var eventData = new BrokerPublishErrorEventData(
                operationId,
                "",
                ServersAddress,
                message.Name,
                message.Content,
                ex,
                startTime,
                du);

            s_diagnosticListener.WritePublishError(eventData);
        }
 public static void WritePublishMessageStoreAfter(this DiagnosticListener @this,
                                                  Guid operationId,
                                                  CapPublishedMessage message,
                                                  [CallerMemberName] string operation = "")
 {
     if (@this.IsEnabled(CapAfterPublishMessageStore))
     {
         @this.Write(CapAfterPublishMessageStore, new
         {
             OperationId    = operationId,
             Operation      = operation,
             MessageId      = message.Id,
             MessageName    = message.Name,
             MessageContent = message.Content,
             Timestamp      = Stopwatch.GetTimestamp()
         });
     }
 }
Exemple #18
0
        protected async Task PublishAsyncInternal(CapPublishedMessage message)
        {
            var operationId = default(Guid);

            try
            {
                var tracingResult = TracingBefore(message.Name, message.Content);
                operationId = tracingResult.Item1;

                message.Content = tracingResult.Item2 != null
                    ? Helper.AddTracingHeaderProperty(message.Content, tracingResult.Item2)
                    : message.Content;

                if (Transaction.Value?.DbTransaction == null)
                {
                    await ExecuteAsync(message);

                    s_diagnosticListener.WritePublishMessageStoreAfter(operationId, message);

                    _dispatcher.EnqueueToPublish(message);
                }
                else
                {
                    var transaction = (CapTransactionBase)Transaction.Value;

                    await ExecuteAsync(message, transaction);

                    s_diagnosticListener.WritePublishMessageStoreAfter(operationId, message);

                    transaction.AddToSent(message);
                    if (transaction.AutoCommit)
                    {
                        transaction.Commit();
                    }
                }
            }
            catch (Exception e)
            {
                s_diagnosticListener.WritePublishMessageStoreError(operationId, message, e);

                throw;
            }
        }
        public async Task <OperateResult> SendAsync(CapPublishedMessage 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);
        }
        protected override async Task ExecuteAsync(CapPublishedMessage message,
                                                   ICapTransaction transaction = null,
                                                   CancellationToken cancel    = default(CancellationToken))
        {
            if (transaction == null)
            {
                using (var connection = new MySqlConnection(_options.ConnectionString))
                {
                    await connection.ExecuteAsync(PrepareSql(), message);

                    return;
                }
            }

            var dbTrans = transaction.DbTransaction as IDbTransaction;

            var conn = dbTrans?.Connection;
            await conn.ExecuteAsync(PrepareSql(), message, dbTrans);
        }
        protected override Task ExecuteAsync(CapPublishedMessage message, ICapTransaction transaction,
                                             CancellationToken cancel = default(CancellationToken))
        {
            var insertOptions = new InsertOneOptions {
                BypassDocumentValidation = false
            };

            var collection = _client
                             .GetDatabase(_options.DatabaseName)
                             .GetCollection <CapPublishedMessage>(_options.PublishedCollection);

            if (NotUseTransaction)
            {
                return(collection.InsertOneAsync(message, insertOptions, cancel));
            }

            var dbTrans = (IClientSessionHandle)transaction.DbTransaction;

            return(collection.InsertOneAsync(dbTrans, message, insertOptions, cancel));
        }
Exemple #22
0
        public void ChangeState_ExpiresAfter()
        {
            // Arrange
            var fixture = Create();
            var message = new CapPublishedMessage
            {
                StatusName = StatusName.Enqueued
            };
            var state           = Mock.Of <IState>(s => s.Name == "s" && s.ExpiresAfter == TimeSpan.FromHours(1));
            var mockTransaction = new Mock <IStorageTransaction>();

            // Act
            fixture.ChangeState(message, state, mockTransaction.Object);

            // Assert
            Assert.Equal(message.StatusName, "s");
            Assert.NotNull(message.ExpiresAt);
            mockTransaction.Verify(t => t.UpdateMessage(message), Times.Once);
            mockTransaction.Verify(t => t.CommitAsync(), Times.Never);
        }
Exemple #23
0
        private void PublishWithTrans(string name, string content, IDbConnection dbConnection, IDbTransaction dbTransaction)
        {
            var message = new CapPublishedMessage
            {
                Name       = name,
                Content    = content,
                StatusName = StatusName.Scheduled
            };
            var count = dbConnection.Execute(PrepareSql(), message, transaction: dbTransaction);

            _logger.LogInformation("Message has been persisted in the database. name:" + name);

            if (IsCapOpenedTrans)
            {
                dbTransaction.Commit();
                dbTransaction.Dispose();
                dbConnection.Dispose();
            }
            PublishQueuer.PulseEvent.Set();
        }
        public async Task GetPublishedMessageAsync_Test()
        {
            var sql            = "INSERT INTO [Cap].[Published]([Name],[Content],[Retries],[Added],[ExpiresAt],[StatusName]) OUTPUT INSERTED.Id VALUES(@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName);";
            var publishMessage = new CapPublishedMessage
            {
                Name       = "SqlServerStorageConnectionTest",
                Content    = "",
                StatusName = StatusName.Scheduled
            };
            var insertedId = default(int);

            using (var connection = ConnectionUtil.CreateConnection())
            {
                insertedId = connection.QueryFirst <int>(sql, publishMessage);
            }
            var message = await _storage.GetPublishedMessageAsync(insertedId);

            Assert.NotNull(message);
            Assert.Equal("SqlServerStorageConnectionTest", message.Name);
            Assert.Equal(StatusName.Scheduled, message.StatusName);
        }
        //============================================================================
        //====================  Before publish store message      ====================
        //============================================================================
        public static Guid WritePublishMessageStoreBefore(this DiagnosticListener @this,
                                                          CapPublishedMessage message,
                                                          [CallerMemberName] string operation = "")
        {
            if (@this.IsEnabled(CapBeforePublishMessageStore))
            {
                var operationId = Guid.NewGuid();

                @this.Write(CapBeforePublishMessageStore, new
                {
                    OperationId    = operationId,
                    Operation      = operation,
                    MessageName    = message.Name,
                    MessageContent = message.Content
                });

                return(operationId);
            }

            return(Guid.Empty);
        }
Exemple #26
0
        public async Task GetPublishedMessageAsync_Test()
        {
            var sql            = @"INSERT INTO ""cap"".""published""(""Name"",""Content"",""Retries"",""Added"",""ExpiresAt"",""StatusName"") VALUES(@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName) RETURNING ""Id"";";
            var publishMessage = new CapPublishedMessage
            {
                Name       = "PostgreSqlStorageConnectionTest",
                Content    = "",
                StatusName = StatusName.Scheduled
            };
            var insertedId = default(int);

            using (var connection = ConnectionUtil.CreateConnection())
            {
                insertedId = connection.QueryFirst <int>(sql, publishMessage);
            }
            var message = await _storage.GetPublishedMessageAsync(insertedId);

            Assert.NotNull(message);
            Assert.Equal("PostgreSqlStorageConnectionTest", message.Name);
            Assert.Equal(StatusName.Scheduled, message.StatusName);
        }
Exemple #27
0
        public void ChangeState()
        {
            // Arrange
            var fixture = Create();
            var message = new CapPublishedMessage
            {
                StatusName = StatusName.Scheduled
            };
            var state           = Mock.Of <IState>(s => s.Name == "s" && s.ExpiresAfter == null);
            var mockTransaction = new Mock <IStorageTransaction>();

            // Act
            fixture.ChangeState(message, state, mockTransaction.Object);

            // Assert
            Assert.Equal("s", message.StatusName);
            Assert.Null(message.ExpiresAt);
            Mock.Get(state).Verify(s => s.Apply(message, mockTransaction.Object), Times.Once);
            mockTransaction.Verify(t => t.UpdateMessage(message), Times.Once);
            mockTransaction.Verify(t => t.CommitAsync(), Times.Never);
        }
Exemple #28
0
        public async Task GetPublishedMessageAsync_Test()
        {
            var sql            = "INSERT INTO `cap.published`(`Name`,`Content`,`Retries`,`Added`,`ExpiresAt`,`StatusName`) VALUES(@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName);SELECT @@IDENTITY;";
            var publishMessage = new CapPublishedMessage
            {
                Name       = "MySqlStorageConnectionTest",
                Content    = "",
                StatusName = StatusName.Scheduled
            };
            var insertedId = default(int);

            using (var connection = ConnectionUtil.CreateConnection())
            {
                insertedId = connection.QueryFirst <int>(sql, publishMessage);
            }
            var message = await _storage.GetPublishedMessageAsync(insertedId);

            Assert.NotNull(message);
            Assert.Equal("MySqlStorageConnectionTest", message.Name);
            Assert.Equal(StatusName.Scheduled, message.StatusName);
        }
        public async Task <OperateResult> SendAsync(CapPublishedMessage message)
        {
            var startTime = DateTimeOffset.UtcNow;
            var stopwatch = Stopwatch.StartNew();

            var tracingResult = TracingBefore(message.Name, message.Content);
            var operationId   = tracingResult.Item1;

            var sendValues = tracingResult.Item2 != null
                ? Helper.AddTracingHeaderProperty(message.Content, tracingResult.Item2)
                : message.Content;

            var result = await PublishAsync(message.Name, sendValues);

            stopwatch.Stop();
            if (result.Succeeded)
            {
                await SetSuccessfulState(message);

                TracingAfter(operationId, message.Name, sendValues, startTime, stopwatch.Elapsed);

                return(OperateResult.Success);
            }
            else
            {
                TracingError(operationId, message.Name, sendValues, result.Exception, startTime, stopwatch.Elapsed);

                _logger.MessagePublishException(message.Id, result.Exception);

                await SetFailedState(message, result.Exception, out bool stillRetry);

                if (stillRetry)
                {
                    _logger.SenderRetrying(3);

                    await SendAsync(message);
                }
                return(OperateResult.Failed(result.Exception));
            }
        }
Exemple #30
0
        private async Task <bool> UpdateMessageForRetryAsync(CapPublishedMessage message, IStorageConnection connection)
        {
            var retryBehavior = RetryBehavior.DefaultRetry;

            var now     = DateTime.Now;
            var retries = ++message.Retries;

            if (retries >= retryBehavior.RetryCount)
            {
                return(false);
            }

            var due = message.Added.AddSeconds(retryBehavior.RetryIn(retries));

            message.ExpiresAt = due;
            using (var transaction = connection.CreateTransaction())
            {
                transaction.UpdateMessage(message);
                await transaction.CommitAsync();
            }
            return(true);
        }