예제 #1
0
 /// <inheritdoc />
 public IQueueOutputMessage Send(IMessage messageToSend, IAdditionalMessageData data)
 {
     try
     {
         var id = _sendMessage.Handle(
             new SendMessageCommand(messageToSend, data));
         return(new QueueOutputMessage(_sentMessageFactory.Create(new MessageQueueId(id), data.CorrelationId)));
     }
     catch (Exception exception)
     {
         return(new QueueOutputMessage(_sentMessageFactory.Create(null, data.CorrelationId), exception));
     }
 }
예제 #2
0
        /// <inheritdoc />
        public long ClearMessages(CancellationToken cancelToken)
        {
            var counter = _commandReset.Handle(new ClearExpiredMessagesCommand());
            var total   = counter;

            while (counter > 0)
            {
                if (cancelToken.IsCancellationRequested)
                {
                    return(total);
                }
                counter = _commandReset.Handle(new ClearExpiredMessagesCommand());
                total  += counter;
            }
            return(total);
        }
예제 #3
0
        public QueueCreationResult Handle(CreateQueueTablesAndSaveConfigurationCommand <ITable> command)
        {
            if (!_databaseExists.Exists(_connectionInformation.ConnectionString))
            { //no db file, create
                var fileName = _getFileNameFromConnection.GetFileName(_connectionInformation.ConnectionString);
                using (File.Create(fileName.FileName))
                {
                }
            }

            try
            {
                return(_decorated.Handle(command));
            }
            //if the queue already exists, return that status; otherwise, bubble the error
            catch (SQLiteException error)
            {
                if (error.ResultCode == SQLiteErrorCode.Error && error.Message.Contains("table") && error.Message.Contains("already exists"))
                {
                    return(new QueueCreationResult(QueueCreationStatus.AttemptedToCreateAlreadyExists));
                }
                throw new DotNetWorkQueueException("Failed to create table",
                                                   error);
            }
        }
예제 #4
0
 /// <summary>
 /// Commits the processed message, by deleting the message
 /// </summary>
 /// <param name="context">The context.</param>
 public void Commit(IMessageContext context)
 {
     if (context.MessageId != null && context.MessageId.HasValue)
     {
         _deleteMessageCommand.Handle(new DeleteMessageCommand((long)context.MessageId.Id.Value));
     }
 }
 /// <inheritdoc />
 public long Handle(SendMessageCommand command)
 {
     using (IScope scope = _tracer.BuildSpan("SendMessage").StartActive(finishSpanOnDispose: true))
     {
         scope.Span.AddCommonTags(command.MessageData, _connectionInformation);
         scope.Span.Add(command);
         command.MessageToSend.Inject(_tracer, scope.Span.Context, _headers.StandardHeaders);
         try
         {
             var id = _handler.Handle(command);
             if (id == 0)
             {
                 Tags.Error.Set(scope.Span, true);
             }
             scope.Span.AddMessageIdTag(id);
             return(id);
         }
         catch (Exception e)
         {
             Tags.Error.Set(scope.Span, true);
             scope.Span.Log(e.ToString());
             throw;
         }
     }
 }
        /// <inheritdoc />
        public long Run(CancellationToken token)
        {
            var records = _moveRecords.Handle(new MoveDelayedRecordsCommand(token));
            var total   = records;

            while (records > 0)
            {
                if (token.IsCancellationRequested)
                {
                    return(total);
                }
                records = _moveRecords.Handle(new MoveDelayedRecordsCommand(token));
                total  += records;
            }
            return(total);
        }
 /// <inheritdoc />
 public long Handle(SendMessageCommand command)
 {
     using (var scope = _tracer.StartActivity("SendMessage"))
     {
         scope?.AddCommonTags(command.MessageData, _connectionInformation);
         scope?.Add(command);
         if (scope?.Context != null)
         {
             command.MessageToSend.Inject(_tracer, scope.Context, _headers.StandardHeaders);
         }
         try
         {
             var id = _handler.Handle(command);
             if (id == 0)
             {
                 scope?.SetStatus(Status.Error);
             }
             scope?.AddMessageIdTag(id);
             return(id);
         }
         catch (Exception e)
         {
             scope?.SetStatus(Status.Error);
             scope?.RecordException(e);
             throw;
         }
     }
 }
예제 #8
0
        /// <inheritdoc />
        public List <ResetHeartBeatOutput> Reset(CancellationToken cancelToken)
        {
            if (!_configuration.HeartBeat.Enabled)
            {
                return(new List <ResetHeartBeatOutput>(0));
            }

            if (string.IsNullOrEmpty(_configuration.TransportConfiguration.ConnectionInfo.ConnectionString))
            {
                return(new List <ResetHeartBeatOutput>(0));
            }

            List <ResetHeartBeatOutput> returnData = new List <ResetHeartBeatOutput>();
            var      query   = new FindMessagesToResetByHeartBeatQuery <T>(cancelToken);
            DateTime start   = _getTime.GetCurrentUtcDate();
            var      results = _queryHandler.Handle(query);
            DateTime end     = _getTime.GetCurrentUtcDate();

            foreach (var result in results)
            {
                var id          = new MessageQueueId <T>(result.QueueId);
                var command     = new ResetHeartBeatCommand <T>(result);
                var resetResult = _commandHandler.Handle(command);
                if (resetResult <= 0)
                {
                    continue;
                }
                var data = new ResetHeartBeatOutput(id, result.Headers, start, end);
                returnData.Add(data);
            }
            return(returnData);
        }
예제 #9
0
        /// <inheritdoc />
        public IHeartBeatStatus Send(IMessageContext context)
        {
            var command = new SendHeartBeatCommand((long)context.MessageId.Id.Value);
            var oDate   = _commandHandler.Handle(command);

            return(new HeartBeatStatus(new MessageQueueId(command.QueueId), oDate));
        }
예제 #10
0
        /// <inheritdoc />
        public RemoveMessageStatus Remove(IMessageId id, RemoveMessageReason reason)
        {
            if (_configuration.Options().EnableHoldTransactionUntilMessageCommitted&& reason == RemoveMessageReason.Complete)
            {
                throw new DotNetWorkQueueException("Cannot use a transaction without the message context");
            }

            if (id == null || !id.HasValue)
            {
                return(RemoveMessageStatus.NotFound);
            }

            var count = _deleteMessageCommand.Handle(new DeleteMessageCommand <long>((long)id.Id.Value));

            return(count > 0 ? RemoveMessageStatus.Removed : RemoveMessageStatus.NotFound);
        }
예제 #11
0
        /// <inheritdoc />
        public RemoveMessageStatus Remove(IMessageContext context, RemoveMessageReason reason)
        {
            if (!_configuration.Options().EnableHoldTransactionUntilMessageCommitted)
            {
                return(Remove(context.MessageId, reason));
            }

            var connection = context.Get(_headers.Connection);

            //if transaction held
            if (connection.Connection == null || connection.Transaction == null)
            {
                var counter = _deleteMessageCommand.Handle(new DeleteMessageCommand <long>((long)context.MessageId.Id.Value));
                return(counter > 0 ? RemoveMessageStatus.Removed : RemoveMessageStatus.NotFound);
            }

            //delete the message, and then commit the transaction
            var count = _deleteTransactionalMessageCommand.Handle(new DeleteTransactionalMessageCommand((long)context.MessageId.Id.Value, context));

            connection.Transaction.Commit();
            connection.Transaction = null;

            if (_configuration.Options().EnableStatusTable)
            {
                _deleteStatusCommandHandler.Handle(new DeleteStatusTableStatusCommand <long>((long)context.MessageId.Id.Value));
            }
            return(count > 0 ? RemoveMessageStatus.Removed : RemoveMessageStatus.NotFound);
        }
        /// <inheritdoc />
        public long ClearMessages(CancellationToken cancelToken)
        {
            var count = 0L;

            if (cancelToken.IsCancellationRequested)
            {
                return(count);
            }

            var messages = _getErrorMessages.Handle(new GetErrorRecordsToDeleteQuery());

            while (messages.Count > 0)
            {
                foreach (var message in messages)
                {
                    if (cancelToken.IsCancellationRequested)
                    {
                        return(count);
                    }

                    if (_deleteMessage.Handle(new DeleteMessageCommand <string>(message)))
                    {
                        count++;
                    }
                }

                messages = _getErrorMessages.Handle(new GetErrorRecordsToDeleteQuery());
            }

            return(count);
        }
        /// <summary>
        /// Used to find and reset work items that are out of the heart beat window
        /// </summary>
        /// <param name="cancelToken">The cancel token.</param>
        public long Reset(CancellationToken cancelToken)
        {
            var counter = _commandReset.Handle(new ResetHeartBeatCommand());
            var total   = counter;

            while (counter > 0)
            {
                if (cancelToken.IsCancellationRequested)
                {
                    return(total);
                }

                counter = _commandReset.Handle(new ResetHeartBeatCommand());
                total   = total + counter;
            }
            return(total);
        }
        /// <summary>
        /// Used to find and reset work items that are out of the heart beat window
        /// </summary>
        /// <param name="cancelToken">The cancel token.</param>
        public List <ResetHeartBeatOutput> Reset(CancellationToken cancelToken)
        {
            var counter = _commandReset.Handle(new ResetHeartBeatCommand <string>(new MessageToReset <string>(string.Empty, DateTime.MinValue, null)));
            var total   = new List <ResetHeartBeatOutput>(counter);

            while (counter.Count > 0)
            {
                if (cancelToken.IsCancellationRequested)
                {
                    return(total);
                }

                counter = _commandReset.Handle(new ResetHeartBeatCommand <string>(new MessageToReset <string>(string.Empty, DateTime.MinValue, null)));
                total.AddRange(counter);
            }
            return(total);
        }
예제 #15
0
 /// <summary>
 /// Commits the processed message, by deleting the message
 /// </summary>
 /// <param name="context">The context.</param>
 public void Commit(IMessageContext context)
 {
     if (context.MessageId == null || !context.MessageId.HasValue)
     {
         return;
     }
     _command.Handle(new CommitMessageCommand((RedisQueueId)context.MessageId));
 }
        /// <summary>
        /// Used to find and reset work items that are out of the heart beat window
        /// </summary>
        /// <param name="cancelToken">The cancel token.</param>
        public List <ResetHeartBeatOutput> Reset(CancellationToken cancelToken)
        {
            var counter = _commandReset.Handle(new ResetHeartBeatCommand());
            var total   = new List <ResetHeartBeatOutput>(counter);

            while (counter.Count > 0)
            {
                if (cancelToken.IsCancellationRequested)
                {
                    return(total);
                }

                counter = _commandReset.Handle(new ResetHeartBeatCommand());
                total.AddRange(counter);
            }
            return(total);
        }
예제 #17
0
 /// <inheritdoc />
 public long ClearMessages(CancellationToken cancelToken)
 {
     return(string.IsNullOrEmpty(_connectionInfo?.ConnectionString)
         ? 0
         : _findExpiredMessagesQueryHandler.Handle(new FindExpiredMessagesToDeleteQuery(cancelToken))
            .Aggregate <long, long>
                (0,
                (current, queueId) =>
                current + _deleteMessageCommandHandler.Handle(new DeleteMessageCommand(queueId))));
 }
        /// <summary>
        /// Updates the heart beat for a record.
        /// </summary>
        /// <param name="context">The context.</param>
        public IHeartBeatStatus Send(IMessageContext context)
        {
            if (context.MessageId == null || !context.MessageId.HasValue)
            {
                return(null);
            }
            var unixTime = _sendHeartBeat.Handle(new SendHeartBeatCommand <string>(context.MessageId.Id.Value.ToString()));

            return(new HeartBeatStatus(context.MessageId, _unixTimeFactory.Create().DateTimeFromUnixTimestampMilliseconds(unixTime))); //UTC
        }
        /// <inheritdoc />
        public TOutput Handle(TCommand command)
        {
            Guard.NotNull(() => command, command);

            if (_policy == null)
            {
                _policies.Registry.TryGet(TransportPolicyDefinitions.RetryCommandHandler, out _policy);
            }
            if (_policy == null)
            {
                return(_decorated.Handle(command));
            }
            var result = _policy.ExecuteAndCapture(() => _decorated.Handle(command));

            if (result.FinalException != null)
            {
                throw result.FinalException;
            }
            return(result.Result);
        }
예제 #20
0
        /// <inheritdoc />
        public RemoveMessageStatus Remove(IMessageId id, RemoveMessageReason reason)
        {
            if (id == null || !id.HasValue)
            {
                return(RemoveMessageStatus.NotFound);
            }

            var result = _deleteMessage.Handle(new DeleteMessageCommand((RedisQueueId)id));

            return(result ? RemoveMessageStatus.Removed : RemoveMessageStatus.NotFound);
        }
예제 #21
0
 /// <summary>
 /// Sends the messages async
 /// </summary>
 /// <param name="messages">The messages.</param>
 /// <returns></returns>
 /// <exception cref="DotNetWorkQueueException">An error occurred while sending a message</exception>
 public async Task <IQueueOutputMessages> SendAsync(List <QueueMessage <IMessage, IAdditionalMessageData> > messages)
 {
     try
     {
         return(await _sendMessageBatchAsync.Handle(new SendMessageCommandBatch(messages)).ConfigureAwait(false));
     }
     catch (Exception exception)
     {
         throw new DotNetWorkQueueException("An error occurred while sending a message", exception);
     }
 }
예제 #22
0
        /// <inheritdoc />
        public RemoveMessageStatus Remove(IMessageId id, RemoveMessageReason reason)
        {
            if (id == null || !id.HasValue)
            {
                return(RemoveMessageStatus.NotFound);
            }

            var result = _deleteMessage.Handle(new DeleteMessageCommand <string>(id.Id.Value.ToString()));

            return(result ? RemoveMessageStatus.Removed : RemoveMessageStatus.NotFound);
        }
예제 #23
0
 /// <summary>
 /// Sends the specified messages.
 /// </summary>
 /// <param name="messages">The messages.</param>
 /// <returns></returns>
 public IQueueOutputMessages Send(List <QueueMessage <IMessage, IAdditionalMessageData> > messages)
 {
     try
     {
         return(_sendMessageBatch.Handle(new SendMessageCommandBatch(messages)));
     }
     catch (Exception exception)
     {
         throw new DotNetWorkQueueException("An error occurred while sending a message", exception);
     }
 }
        /// <summary>
        /// Creates the queue.
        /// </summary>
        /// <returns></returns>
        private QueueCreationResult CreateQueueInternal()
        {
            var valid = Options.ValidConfiguration();

            if (valid.Valid)
            {
                return
                    (_createCommand.Handle(
                         new CreateQueueTablesAndSaveConfigurationCommand <ITable>(_createSchema.GetSchema())));
            }
            return(new QueueCreationResult(QueueCreationStatus.ConfigurationError, valid.ErrorMessage));
        }
예제 #25
0
        /// <inheritdoc />
        public RemoveMessageStatus Remove(IMessageId id, RemoveMessageReason reason)
        {
            if (id != null && id.HasValue)
            {
                var result = _deleteMessageCommandHandler.Handle(new DeleteMessageCommand((long)id.Id.Value));
                if (result > 0)
                {
                    return(RemoveMessageStatus.Removed);
                }
            }

            return(RemoveMessageStatus.NotFound);
        }
 public QueueCreationResult Handle(CreateJobTablesCommand <ITable> command)
 {
     try
     {
         return(_decorated.Handle(command));
     }
     //if the queue already exists, return that status; otherwise, bubble the error
     catch (SqlException error)
     {
         if (error.Number == 2714)
         {
             return(new QueueCreationResult(QueueCreationStatus.AttemptedToCreateAlreadyExists));
         }
         throw new DotNetWorkQueueException("Failed to create job table(s)",
                                            error);
     }
 }
예제 #27
0
 /// <inheritdoc />
 public QueueCreationResult Handle(CreateQueueTablesAndSaveConfigurationCommand <ITable> command)
 {
     try
     {
         return(_decorated.Handle(command));
     }
     //if the queue already exists, return that status; otherwise, bubble the error
     catch (PostgresException error)
     {
         if (error.SqlState == "42P07" || error.SqlState == "42710")
         {
             return(new QueueCreationResult(QueueCreationStatus.AttemptedToCreateAlreadyExists));
         }
         throw new DotNetWorkQueueException($"Failed to create job table(s). SQL script was {error.Statement}",
                                            error);
     }
 }
예제 #28
0
        /// <summary>
        /// Sends the specified message.
        /// </summary>
        /// <param name="messageToSend">The message to send.</param>
        /// <param name="data">The data.</param>
        /// <returns></returns>
        /// <exception cref="DotNetWorkQueueException">An error occurred while sending a message</exception>
        public IQueueOutputMessage Send(IMessage messageToSend, IAdditionalMessageData data)
        {
            try
            {
                //correlationID must be stored as a message header
                messageToSend.SetHeader(_headers.CorrelationId, new RedisQueueCorrelationIdSerialized((Guid)data.CorrelationId.Id.Value));

                var messageId = _sendMessage.Handle(new SendMessageCommand(messageToSend, data));
                if (messageId == "JobAlreadyExists")
                {
                    return(new QueueOutputMessage(_sentMessageFactory.Create(null, data.CorrelationId), new DotNetWorkQueueException("Failed to enqueue a record. The job already exists")));
                }
                return(new QueueOutputMessage(_sentMessageFactory.Create(new RedisQueueId(messageId), data.CorrelationId)));
            }
            catch (Exception exception)
            {
                return(new QueueOutputMessage(_sentMessageFactory.Create(null, data.CorrelationId), exception));
            }
        }
예제 #29
0
        /// <inheritdoc />
        public RemoveMessageStatus Remove(IMessageContext context, RemoveMessageReason reason)
        {
            if (!_configuration.Options().EnableHoldTransactionUntilMessageCommitted)
            {
                return(Remove(context.MessageId, reason));
            }

            var connection = context.Get(_headers.Connection);

            //if transaction held
            if (connection.Connection == null || connection.Transaction == null)
            {
                var counter = _deleteMessageCommand.Handle(new DeleteMessageCommand((long)context.MessageId.Id.Value));
                return(counter > 0 ? RemoveMessageStatus.Removed : RemoveMessageStatus.NotFound);
            }

            //delete the message, and then commit the transaction
            var count = _deleteTransactionalMessageCommand.Handle(new DeleteTransactionalMessageCommand((long)context.MessageId.Id.Value, context));

            try
            {
                connection.Transaction.Commit();
            }
            catch (Exception e)
            {
                _log.ErrorException("Failed to commit a transaction; this might be due to a DB timeout", e);

                //don't attempt to use the transaction again at this point.
                connection.Transaction = null;

                throw;
            }

            //ensure that transaction won't be used anymore
            connection.Transaction.Dispose();
            connection.Transaction = null;

            if (_configuration.Options().EnableStatusTable)
            {
                _deleteStatusCommandHandler.Handle(new DeleteStatusTableStatusCommand((long)context.MessageId.Id.Value));
            }
            return(count > 0 ? RemoveMessageStatus.Removed : RemoveMessageStatus.NotFound);
        }
예제 #30
0
        /// <summary>
        /// Commits the message, via the held transaction
        /// </summary>
        /// <param name="context">The context.</param>
        public void CommitForTransaction(IMessageContext context)
        {
            var connection = context.Get(_headers.Connection);

            //if transaction held
            if (connection.Connection == null || connection.Transaction == null)
            {
                return;
            }

            //delete the message, and then commit the transaction
            _deleteTransactionalMessageCommand.Handle(new DeleteTransactionalMessageCommand((long)context.MessageId.Id.Value, context));
            connection.Transaction.Commit();
            connection.Transaction = null;

            if (_configuration.Options().EnableStatusTable)
            {
                _deleteStatusCommandHandler.Handle(new DeleteStatusTableStatusCommand((long)context.MessageId.Id.Value));
            }
        }