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); }
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); }
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); }
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); }
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; } }
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(); }
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(); }
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(); }
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)); }
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); }
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() }); } }
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)); }
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); }
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); }
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); }
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); }
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)); } }
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); }