/// <summary> /// Handles the specified query. /// </summary> /// <param name="query">The query.</param> /// <returns></returns> /// <exception cref="PoisonMessageException">An error has occured trying to re-assemble a message de-queued from SQLite</exception> /// <exception cref="MessageQueueId"></exception> public async Task <IReceivedMessageInternal> Handle(ReceiveMessageQueryAsync <IDbConnection, IDbTransaction> query) { if (!_databaseExists.Exists(_connectionInformation.ConnectionString)) { return(null); } using (var connection = _dbFactory.CreateConnection(_connectionInformation.ConnectionString, false)) { connection.Open(); using (var transaction = _dbFactory.CreateTransaction(connection).BeginTransaction()) { using (var selectCommand = connection.CreateCommand()) { selectCommand.Transaction = transaction; CommandString commandString = GetDeQueueCommand(_tableNameHelper.MetaDataName, _tableNameHelper.QueueName, _tableNameHelper.StatusName, query.Routes); if (commandString == null) { throw new DotNetWorkQueueException("Failed to generate command text for de-queue of messages"); } _buildDequeueCommand.BuildCommand(selectCommand, commandString, _options.Value, query.Routes); using (var reader = await _readerAsync.ExecuteReaderAsync(selectCommand).ConfigureAwait(false)) { return(_messageDeQueue.HandleMessage(connection, transaction, reader, commandString)); } } } } }
/// <summary> /// Handles the specified query. /// </summary> /// <param name="query">The query.</param> /// <returns></returns> public async Task <IReceivedMessageInternal> Handle(ReceiveMessageQueryAsync <SqlConnection, SqlTransaction> query) { using (var selectCommand = query.Connection.CreateCommand()) { _buildDequeueCommand.BuildCommand(selectCommand, query); using (var reader = await selectCommand.ExecuteReaderAsync().ConfigureAwait(false)) { return(_readMessage.Read(reader)); } } }
/// <inheritdoc /> public async Task <RedisMessage> Handle(ReceiveMessageQueryAsync query) { byte[] message = null; byte[] headers = null; string messageId; var poisonMessage = false; RedisQueueCorrelationIdSerialized correlationId = null; try { var unixTimestamp = _unixTimeFactory.Create().GetCurrentUnixTimestampMilliseconds(); RedisValue[] result; if (query.MessageId != null && query.MessageId.HasValue) { result = await _dequeueRpcLua.ExecuteAsync(query.MessageId.Id.Value.ToString(), unixTimestamp).ConfigureAwait(false); } else { result = await _dequeueLua.ExecuteAsync(unixTimestamp).ConfigureAwait(false); } if (result == null || result.Length == 1 && !result[0].HasValue || !result[0].HasValue) { return(null); } if (!result[1].HasValue) { //at this point, the record has been de-queued, but it can't be processed. poisonMessage = true; } messageId = result[0]; var id = new RedisQueueId(messageId); query.MessageContext.MessageId = id; if (!poisonMessage) { message = result[1]; headers = result[2]; if (result[3].HasValue) { if (result[3].TryParse(out long messageExpiration)) { if (messageExpiration - unixTimestamp < 0) { //message has expired _deleteMessage.Handle(new DeleteMessageCommand(new RedisQueueId(messageId))); return(new RedisMessage(messageId, null, true)); } } } } } catch (Exception error) { throw new ReceiveMessageException("Failed to dequeue a message", error); } if (poisonMessage) { //at this point, the record has been de-queued, but it can't be processed. throw new PoisonMessageException( "An error has occurred trying to re-assemble a message de-queued from redis; a messageId was returned, but the LUA script returned a null message. The message payload has most likely been lost.", null, new RedisQueueId(messageId), new RedisQueueCorrelationId(Guid.Empty), null, null); } try { var allHeaders = _serializer.InternalSerializer.ConvertBytesTo <IDictionary <string, object> >(headers); correlationId = (RedisQueueCorrelationIdSerialized)allHeaders[_redisHeaders.CorrelationId.Name]; var messageGraph = (MessageInterceptorsGraph) allHeaders[_redisHeaders.Headers.StandardHeaders.MessageInterceptorGraph.Name]; var messageData = _serializer.Serializer.BytesToMessage <MessageBody>(message, messageGraph); var newMessage = _messageFactory.Create(messageData.Body, allHeaders); return(new RedisMessage( messageId, _receivedMessageFactory.Create( newMessage, new RedisQueueId(messageId), new RedisQueueCorrelationId(correlationId.Id)), false)); } catch (Exception error) { //at this point, the record has been de-queued, but it can't be processed. throw new PoisonMessageException( "An error has occurred trying to re-assemble a message de-queued from redis", error, new RedisQueueId(messageId), new RedisQueueCorrelationId(correlationId), message, headers); } }
public void BuildCommand(SqlCommand selectCommand, ReceiveMessageQueryAsync <SqlConnection, SqlTransaction> query) { BuildCommandInternal(selectCommand, query.Transaction, query.MessageId, query.Routes); }
/// <inheritdoc /> public async Task <IReceivedMessageInternal> Handle(ReceiveMessageQueryAsync <NpgsqlConnection, NpgsqlTransaction> query) { using (var selectCommand = query.Connection.CreateCommand()) { selectCommand.Transaction = query.Transaction; if (query.MessageId != null && query.MessageId.HasValue) { selectCommand.CommandText = ReceiveMessage.GetDeQueueCommand(_commandCache, _tableNameHelper, _options.Value, true, query.Routes); selectCommand.Parameters.Add("@QueueID", NpgsqlDbType.Bigint); selectCommand.Parameters["@QueueID"].Value = query.MessageId.Id.Value; } else { selectCommand.CommandText = ReceiveMessage.GetDeQueueCommand(_commandCache, _tableNameHelper, _options.Value, false, query.Routes); } selectCommand.Parameters.Add("@CurrentDate", NpgsqlDbType.Bigint); selectCommand.Parameters["@CurrentDate"].Value = _getTime.GetCurrentUtcDate().Ticks; if (_options.Value.EnableRoute && query.Routes != null && query.Routes.Count > 0) { var routeCounter = 1; foreach (var route in query.Routes) { selectCommand.Parameters.Add("@Route" + routeCounter, NpgsqlDbType.Varchar); selectCommand.Parameters["@Route" + routeCounter].Value = route; routeCounter++; } } using (var reader = await selectCommand.ExecuteReaderAsync().ConfigureAwait(false)) { if (!reader.Read()) { return(null); } //load up the message from the DB long id = 0; var correlationId = Guid.Empty; byte[] headerPayload = null; byte[] messagePayload = null; try { id = (long)reader["queueid"]; correlationId = (Guid)reader["CorrelationID"]; headerPayload = (byte[])reader["Headers"]; messagePayload = (byte[])reader["body"]; var headers = _serialization.InternalSerializer.ConvertBytesTo <IDictionary <string, object> >(headerPayload); var messageGraph = (MessageInterceptorsGraph)headers[_headers.StandardHeaders.MessageInterceptorGraph.Name]; var message = _serialization.Serializer.BytesToMessage <MessageBody>(messagePayload, messageGraph).Body; var newMessage = _messageFactory.Create(message, headers); return(_receivedMessageFactory.Create(newMessage, new MessageQueueId(id), new MessageCorrelationId(correlationId))); } catch (Exception error) { //at this point, the record has been de-queued, but it can't be processed. throw new PoisonMessageException( "An error has occurred trying to re-assemble a message de-queued from the server", error, new MessageQueueId(id), new MessageCorrelationId(correlationId), messagePayload, headerPayload); } } } }