Ejemplo n.º 1
0
 public virtual void Consumer_ReceiveMessage(IBasicGetResult message)
 {
     ContinueProcessing = false;
     if (message == null)
     {
         return;                  // queue is empty
     }
     Message       = CustomJsonSerializer.BytesToMessage <T>(message.Body);
     CorrelationId = message.BasicProperties.CorrelationId;
     RoutingKey    = message.RoutingKey;
     if (message.Body.Count() == 0)
     {
         Log.Error(
             "SubscriberBase: Consumer_ReceiveMessage(message) - message.Body contains no data for message id {0}",
             message.BasicProperties.MessageId);
     }
     if (Message != null)
     {
         ContinueProcessing = true;
         return;
     }
     if (message.Body.Count() > 0)
     {
         Log.Error("SubscriberBase: Consumer_ReceiveMessage(message) - message.Body contains data which is not compatible with {0} for message id {1}", typeof(T).ToString(), message.BasicProperties.MessageId);
     }
     InvalidExchange.SendMessage(message.Body, InvalidRoutingKey, "");
 }
Ejemplo n.º 2
0
        protected void OnReceiveMessage(IBasicGetResult message)
        {
            var receiveMessage = ReceiveMessage;

            if (receiveMessage != null)
            {
                receiveMessage(message);
            }
        }
Ejemplo n.º 3
0
        public static void Consumer_ReceiveMessage(IBasicGetResult message)
        {
            // Process Message from queue
            if (message == null) return;// queue is empty
            var batch = CustomJsonSerializer.BytesToMessage<RecogniseBatchCourtesyAmountRequest>(message.Body);
            //var batch = message;

            if (message.Body.Count() == 0)
                Log.Error(
                    "ProcessingService: Queue_MessageRecieved(message) - message.Body contains no data for message id {0}",
                    message.BasicProperties.MessageId);
            if (batch == null)
            {
                if (message.Body.Count() > 0)
                    Log.Error(
                        "ProcessingService: Queue_MessageRecieved(message) - message.Body contains data which is not compatible with RecogniseBatchCourtesyAmountRequest for message id {0}",
                        message.BasicProperties.MessageId);
                // need to re-route message to CAR.Invalid queue
                if (!string.IsNullOrEmpty(InvalidQueueName))
                    InvalidExchange.SendMessage(message.Body, InvalidRoutingKey, "");
                return; // acknowledge message to remove from queue;
            }
            RoutingKey = message.RoutingKey;
            if (batch.voucher == null || batch.voucher.Length == 0)
            {
                Log.Error(
                    "ProcessingService: Queue_MessageRecieved(message) - there are no vouchers present for message id {0}",
                    message.BasicProperties.MessageId);
                // need to re-route message to CAR.Invalid queue
                if (!string.IsNullOrEmpty(InvalidQueueName))
                    InvalidExchange.SendMessage(message.Body, InvalidRoutingKey, "");
                return; // acknowledge message to remove from queue;
            }
            var ocrBatch = new OcrBatch
            {
                JobIdentifier = batch.jobIdentifier,
                Vouchers = batch.voucher.Select(v => new OcrVoucher
                {
                    Id = v.documentReferenceNumber,
                    ImagePath = Path.Combine(ImageFilePath, batch.jobIdentifier, string.Format(ImageFileNameTemplate, v.processingDate, v.documentReferenceNumber)),
                    VoucherType = ParseTransactionCode(v.transactionCode)
                }).ToList()
            };
            // Validate the file path
            if (!ValidateImageFiles(ocrBatch)) return;// probably should send to an error queue
            Log.Information("Batch {0} received from message queue containing {1} vouchers", ocrBatch.JobIdentifier, ocrBatch.Vouchers.Count());
            OcrService.ProcessBatch(ocrBatch);
        }
        public async Task Publisher_Publish_MessageMustBeSerializedAndCorrectlyRouted()
        {
            //prepare
            IConfiguration configuration = ConfigurationHelper.ProvideConfiguration();
            var            exchangeName  = "Publisher_Publish_MessageMustBeSerializedAndCorrectlyRouted.exchangename";

            configuration["rabbitmq:exchangename"] = exchangeName;

            IContainer container = ConfigurationHelper.ConfigureContainer(configuration);

            var publisher = container.Resolve <IPublisher>();

            string routingKey = "changetracker.entity.create.booking";

            var       bus      = container.Resolve <IAdvancedBus>();
            IExchange exchange = bus.ExchangeDeclare(exchangeName, ExchangeType.Topic);

            var queue   = bus.QueueDeclare("Publisher_Publish_MessageMustBeSentAndCorrectlyRouted.subscriberqueue");
            var binding = bus.Bind(exchange, queue, "changetracker.entity.create.booking");

            //act
            BookingCreated bookingCreated =
                new BookingCreated()
            {
                BookingName = string.Concat("Microsoft Sale", Guid.NewGuid().ToString())
            };

            var bookingCreatedIntegrationEvent = new IntegrationEvent <BookingCreated>()
            {
                Content   = bookingCreated,
                EventType = "bookingcreated"
            };

            await publisher.PublishEventAsync(bookingCreatedIntegrationEvent, routingKey);

            await Task.Delay(300);

            //check

            IBasicGetResult result = bus.Get(queue);

            var message = Encoding.UTF8.GetString(result.Body);
            IntegrationEvent <BookingCreated> eventToCheck = JsonConvert.DeserializeObject <IntegrationEvent <BookingCreated> >(message);

            eventToCheck.ShouldBeEquivalentTo(bookingCreatedIntegrationEvent);
            container.Dispose();
        }
Ejemplo n.º 5
0
 protected void OnReceiveMessage(IBasicGetResult message)
 {
     var receiveMessage = ReceiveMessage;
     if (receiveMessage != null) receiveMessage(message);
 }
Ejemplo n.º 6
0
        public override void Consumer_ReceiveMessage(IBasicGetResult message)
        {
            base.Consumer_ReceiveMessage(message);
            if (!ContinueProcessing)
            {
                return;
            }
            var request = Message;

            Log.Information("Processing GenerateCorrespondingVoucherRequest '{@request}', '{@correlationId}'", request, CorrelationId);

            try
            {
                //Mapping queue table
                var queue = QueueMapper.Map(request);
                queue.CorrelationId = CorrelationId;
                queue.RoutingKey    = RoutingKey;

                //Mapping voucher fields
                var vouchers      = VoucherMapper.Map(request).ToList();
                var jobIdentifier = CorrelationId;
                var batchNumber   = string.Empty;

                //Mapping index fields
                var dbIndexes = DbIndexMapper.Map(request);

                using (var dbConnection = new SqlConnection(Configuration.SqlConnectionString))
                    using (var dBContext = new DipsDbContext(dbConnection))
                    {
                        using (var tx = dBContext.BeginTransaction())
                        {
                            try
                            {
                                //Adding to queue table
                                dBContext.Queues.Add(queue);
                                Log.Verbose("Adding new queue {@batchNumber} to the database", queue.S_BATCH);

                                dBContext.SaveChanges();

                                //Adding to voucher table
                                foreach (var voucher in vouchers)
                                {
                                    dBContext.NabChqPods.Add(voucher);
                                    Log.Verbose(
                                        "Adding new voucher {@batchNumber} - {@sequenceNumber} to the database",
                                        voucher.S_BATCH,
                                        voucher.S_SEQUENCE);
                                }

                                dBContext.SaveChanges();

                                //Adding to index table
                                foreach (var dbIndex in dbIndexes)
                                {
                                    dBContext.DbIndexes.Add(dbIndex);
                                    Log.Verbose("Adding new db index {@batchNumber} - {@sequenceNumber} to the database", dbIndex.BATCH, dbIndex.SEQUENCE);
                                }

                                dBContext.SaveChanges();

                                tx.Commit();

                                Log.Information("Successfully processed CorrectCodelineRequest '{@batchNumber}', '{@jobIdentifier}'", batchNumber, jobIdentifier);
                            }
                            catch (OptimisticConcurrencyException)
                            {
                                //this is to handle the race condition where more than instance of this service is running at the same time and tries to update the row.

                                //basically ignore the message by loggin a warning and rolling back.
                                //if this row was not included by mistake (e.g. it should be included), it will just come in in the next batch run.
                                Log.Warning(
                                    "Could not create a CorrectCodelineRequest '{@GenerateCorrespondingVoucherRequest}', '{@jobIdentifier}' because the DIPS database row was updated by another connection",
                                    request, jobIdentifier);

                                tx.Rollback();
                                InvalidExchange.SendMessage(message.Body, RecoverableRoutingKey, CorrelationId);
                            }
                            catch (Exception ex)
                            {
                                Log.Error(
                                    ex,
                                    "Could not complete and create a CorrectCodelineRequest '{@GenerateCorrespondingVoucherRequest}', '{@jobIdentifier}'",
                                    request, jobIdentifier);
                                tx.Rollback();
                                InvalidExchange.SendMessage(message.Body, RecoverableRoutingKey, CorrelationId);
                            }
                        }
                    }

                Log.Information("Successfully processed GenerateCorrespondingVoucherRequest {@CorrelationId}", CorrelationId);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error processing GenerateCorrespondingVoucherRequest {@GenerateCorrespondingVoucherRequest}", request);
                InvalidExchange.SendMessage(message.Body, InvalidRoutingKey, CorrelationId);
            }
        }
        public async Task Subscriber_MalformedMessage_MessageMustBeMovedToGlobalDeadLetterQueue(string caseName, string messageBody)
        {
            var testName = $"{nameof(Subscriber_MalformedMessage_MessageMustBeMovedToGlobalDeadLetterQueue)}_{caseName}";
            //prepare
            IConfiguration configuration = ConfigurationHelper.ProvideConfiguration();
            var            exchangeName  =
                $"{testName}.exchangename";

            configuration["rabbitmq:exchangename"]     = exchangeName;
            configuration["rabbitmq:waitexchangename"] = exchangeName.Replace("exchangename", "waitexchangename");

            var maxretrycount = 2;

            IContainer container = ConfigurationHelper.ConfigureContainer(configuration);

            //create Subscriber
            var         bookingCreatedSubscriberFactory = container.Resolve <ISubscriberFactory>();
            ISubscriber typedSubscriber =
                await bookingCreatedSubscriberFactory
                .CreateSubscriberAsync(testName +
                                       ".stubconsumer", new List <string> {
                "*.entity.create.booking"
            },
                                       maxretrycount);

            var consumer = new StubConsumer();

            typedSubscriber.Subscribe(SubscriptionBuilder.Create().AddDefaultSubscription(() => consumer).Build());

            //create Bus
            var    bus        = container.Resolve <IAdvancedBus>();
            string routingKey = "changetracker.entity.create.booking";

            //act
            var body       = Encoding.UTF8.GetBytes(messageBody);
            var properties = new MessageProperties
            {
                DeliveryMode = 2//persistent
            };
            await bus.PublishAsync(await bus.ExchangeDeclareAsync(exchangeName, ExchangeType.Topic), routingKey, false, properties, body);

            await Task.Delay(3000);

            //check
            var             deadleterqueue = bus.QueueDeclare($"{exchangeName}.defaultTombQueue");
            IBasicGetResult result         = bus.Get(deadleterqueue);

            var     message    = Encoding.UTF8.GetString(result.Body);
            JObject errorEvent = JObject.Parse(message);

            errorEvent["RoutingKey"].Value <string>().Should().Be("changetracker.entity.create.booking");
            errorEvent["Exchange"]
            .Value <string>().Should().Be(exchangeName);
            errorEvent["Queue"]
            .Value <string>().Should().Be($"{exchangeName}.{testName}.stubconsumer");

            //check bindings
            var managementClient = new ManagementClient(configuration["rabbitmqmanagement:hostUrl"], configuration["rabbitmqmanagement:username"], configuration["rabbitmqmanagement:password"], configuration.GetValue <int>("rabbitmqmanagement:portNumber"));
            var virtualHostName  = new ConnectionStringParser().Parse(configuration["rabbitmq:connectionstring"]).VirtualHost;
            var virtualhost      = await managementClient.GetVhostAsync(virtualHostName);

            var deadleterq = await managementClient.GetQueueAsync(deadleterqueue.Name, virtualhost);

            var deadleterqbindings = (await managementClient.GetBindingsForQueueAsync(deadleterq)).ToList();

            deadleterqbindings.Should().HaveCount(2);//one is default
            deadleterqbindings.Where(x => x.Source == $"{exchangeName}_error" && x.RoutingKey == routingKey).Should().HaveCount(1);

            container.Dispose();
        }
        public async Task Subscriber_DiscardException_MessageMustBeMovedToGlobalDeadLetterQueue()
        {
            //prepare
            IConfiguration configuration = ConfigurationHelper.ProvideConfiguration();
            var            exchangeName  =
                "Subscriber_DiscardException_MessageMustBeMovedToGlobalDeadLetterQueue.exchangename";

            configuration["rabbitmq:exchangename"]     = exchangeName;
            configuration["rabbitmq:waitexchangename"] = exchangeName.Replace("exchangename", "waitexchangename");

            var maxretrycount = 2;

            IContainer container = ConfigurationHelper.ConfigureContainer(configuration);

            //create Subscriber
            var         bookingCreatedSubscriberFactory = container.Resolve <ISubscriberFactory>();
            ISubscriber typedSubscriber =
                await bookingCreatedSubscriberFactory
                .CreateSubscriberAsync("Subscriber_DiscardException_MessageMustBeMovedToGlobalDeadLetterQueue" +
                                       ".typedbookingcreatedconsumer", new List <string> {
                "*.entity.create.booking"
            },
                                       maxretrycount);

            DiscardConsumer discardConsumer = new DiscardConsumer();

            typedSubscriber.Subscribe(SubscriptionBuilder.Create().AddDefaultSubscription(() => discardConsumer).Build());

            //create Publisher

            var publisher = container.Resolve <IPublisher>();

            string routingKey = "changetracker.entity.create.booking";

            //act
            BookingCreated bookingCreated =
                new BookingCreated()
            {
                BookingName = string.Concat("Microsoft Sale", Guid.NewGuid().ToString())
            };

            var bookingCreatedIntegrationEvent = new IntegrationEvent <BookingCreated>()
            {
                Content       = bookingCreated,
                EventType     = "bookingcreated",
                CorrelationId = Guid.NewGuid()
            };
            await publisher.PublishEventAsync(bookingCreatedIntegrationEvent, routingKey);

            await Task.Delay(3000);

            //check
            var             bus            = container.Resolve <IAdvancedBus>();
            var             deadleterqueue = bus.QueueDeclare($"{exchangeName}.defaultTombQueue");
            IBasicGetResult result         = bus.Get(deadleterqueue);

            var     message    = Encoding.UTF8.GetString(result.Body);
            JObject errorEvent = JObject.Parse(message);

            errorEvent["RoutingKey"].Value <string>().Should().Be("changetracker.entity.create.booking");
            errorEvent["Exchange"]
            .Value <string>().Should().Be("Subscriber_DiscardException_MessageMustBeMovedToGlobalDeadLetterQueue.exchangename");
            errorEvent["Queue"]
            .Value <string>().Should().Be($"{exchangeName}.Subscriber_DiscardException_MessageMustBeMovedToGlobalDeadLetterQueue.typedbookingcreatedconsumer");

            //check bindings
            var managementClient = new ManagementClient(configuration["rabbitmqmanagement:hostUrl"], configuration["rabbitmqmanagement:username"], configuration["rabbitmqmanagement:password"], configuration.GetValue <int>("rabbitmqmanagement:portNumber"));
            var virtualHostName  = new ConnectionStringParser().Parse(configuration["rabbitmq:connectionstring"]).VirtualHost;
            var virtualhost      = await managementClient.GetVhostAsync(virtualHostName);

            var deadleterq = await managementClient.GetQueueAsync(deadleterqueue.Name, virtualhost);

            var deadleterqbindings = (await managementClient.GetBindingsForQueueAsync(deadleterq)).ToList();

            deadleterqbindings.Should().HaveCount(2);//one is default
            deadleterqbindings.Where(x => x.Source == $"{exchangeName}_error" && x.RoutingKey == routingKey).Should().HaveCount(1);

            container.Dispose();
        }
        public async Task Subscriber_ExceededCountOfAttempts_MessageMustBeMovedToSpecificDeadLetterQueue()
        {
            //prepare
            IConfiguration configuration = ConfigurationHelper.ProvideConfiguration();
            var            exchangeName  =
                "Subscriber_ExceededCountOfAttempts_MessageMustBeMovedToDeadLetterQueue.exchangename";

            configuration["rabbitmq:exchangename"]     = exchangeName;
            configuration["rabbitmq:waitexchangename"] = exchangeName.Replace("exchangename", "waitexchangename");
            configuration["rabbitmq:retryfactor"]      = 100.ToString();

            var maxretrycount = 2;

            IContainer container = ConfigurationHelper.ConfigureContainer(configuration);

            //create Subscriber
            var         bookingCreatedSubscriberFactory = container.Resolve <ISubscriberFactory>();
            ISubscriber typedSubscriber =
                await bookingCreatedSubscriberFactory
                .CreateSubscriberAsync("Subscriber_ExceededCountOfAttempts_MessageMustBeMovedToDeadLetterQueue" +
                                       ".typedbookingcreatedconsumer", new List <string> {
                "*.entity.create.booking"
            },
                                       maxretrycount);

            BookingTypedConsumer typedConsumer = new BookingTypedConsumer(3);

            IntegrationEvent <BookingCreated> actualDeadLetterCallbackIntegrationEvent = null;
            Exception actualDeadLetterCallbackException = null;

            typedSubscriber.Subscribe(SubscriptionBuilder.Create().AddDefaultSubscription(() => typedConsumer, (integrationEvent, exception) =>
            {
                actualDeadLetterCallbackIntegrationEvent = integrationEvent;
                actualDeadLetterCallbackException        = exception;
                return(Task.CompletedTask);
            }).Build());

            //create Publisher

            var publisher = container.Resolve <IPublisher>();

            string routingKey = "changetracker.entity.create.booking";

            //act
            BookingCreated bookingCreated =
                new BookingCreated()
            {
                BookingName = string.Concat("Microsoft Sale", Guid.NewGuid().ToString())
            };

            var bookingCreatedIntegrationEvent = new IntegrationEvent <BookingCreated>()
            {
                Content       = bookingCreated,
                EventType     = "bookingcreated",
                CorrelationId = Guid.NewGuid()
            };
            await publisher.PublishEventAsync(bookingCreatedIntegrationEvent, routingKey);

            //wait 1 second
            await Task.Delay(1000);

            //check
            var bus            = container.Resolve <IAdvancedBus>();
            var deadleterqueue = bus.QueueDeclare($"{exchangeName}.deadletter" +
                                                  ".Subscriber_ExceededCountOfAttempts_MessageMustBeMovedToDeadLetterQueue." +
                                                  "typedbookingcreatedconsumer");
            IBasicGetResult result = bus.Get(deadleterqueue);

            var message = Encoding.UTF8.GetString(result.Body);
            var actualDeadLetterQueueIntergrationEvent = JsonConvert.
                                                         DeserializeObject <IntegrationEvent <DeadLetterEventDescriptor <BookingCreated> > >(message);

            result.Info.RoutingKey.Should().Be("deadletter" +
                                               ".Subscriber_ExceededCountOfAttempts_MessageMustBeMovedToDeadLetterQueue" +
                                               ".typedbookingcreatedconsumer");

            actualDeadLetterQueueIntergrationEvent.Content.Original
            .ShouldBeEquivalentTo(bookingCreatedIntegrationEvent);
            actualDeadLetterQueueIntergrationEvent.CorrelationId
            .ShouldBeEquivalentTo(bookingCreatedIntegrationEvent.CorrelationId);
            actualDeadLetterQueueIntergrationEvent.EventType.Should()
            .BeEquivalentTo(string.Concat("deadletter.", bookingCreatedIntegrationEvent.EventType));

            actualDeadLetterCallbackException.Message.Should().Be("ExceptionHasBeenThrown");
            actualDeadLetterCallbackException.Should().BeOfType <Exception>();
            actualDeadLetterCallbackIntegrationEvent.ShouldBeEquivalentTo(bookingCreatedIntegrationEvent);


            typedConsumer.ProcessedIntegrationEvent.Should().BeNull();
            typedConsumer.CountOfAttempts.Should().Be(3);
            container.Dispose();
        }
Ejemplo n.º 10
0
        public static void Consumer_ReceiveMessage(IBasicGetResult message)
        {
            // Process Message from queue
            if (message == null)
            {
                return;                 // queue is empty
            }
            var batch = CustomJsonSerializer.BytesToMessage <RecogniseBatchCourtesyAmountRequest>(message.Body);

            //var batch = message;

            if (message.Body.Count() == 0)
            {
                Log.Error(
                    "ProcessingService: Queue_MessageRecieved(message) - message.Body contains no data for message id {0}",
                    message.BasicProperties.MessageId);
            }
            if (batch == null)
            {
                if (message.Body.Count() > 0)
                {
                    Log.Error(
                        "ProcessingService: Queue_MessageRecieved(message) - message.Body contains data which is not compatible with RecogniseBatchCourtesyAmountRequest for message id {0}",
                        message.BasicProperties.MessageId);
                }
                // need to re-route message to CAR.Invalid queue
                if (!string.IsNullOrEmpty(InvalidQueueName))
                {
                    InvalidExchange.SendMessage(message.Body, InvalidRoutingKey, "");
                }
                return; // acknowledge message to remove from queue;
            }
            RoutingKey = message.RoutingKey;
            if (batch.voucher == null || batch.voucher.Length == 0)
            {
                Log.Error(
                    "ProcessingService: Queue_MessageRecieved(message) - there are no vouchers present for message id {0}",
                    message.BasicProperties.MessageId);
                // need to re-route message to CAR.Invalid queue
                if (!string.IsNullOrEmpty(InvalidQueueName))
                {
                    InvalidExchange.SendMessage(message.Body, InvalidRoutingKey, "");
                }
                return; // acknowledge message to remove from queue;
            }
            var ocrBatch = new OcrBatch
            {
                JobIdentifier = batch.jobIdentifier,
                Vouchers      = batch.voucher.Select(v => new OcrVoucher
                {
                    Id          = v.documentReferenceNumber,
                    ImagePath   = Path.Combine(ImageFilePath, batch.jobIdentifier, string.Format(ImageFileNameTemplate, v.processingDate, v.documentReferenceNumber)),
                    VoucherType = ParseTransactionCode(v.transactionCode)
                }).ToList()
            };

            // Validate the file path
            if (!ValidateImageFiles(ocrBatch))
            {
                return;                               // probably should send to an error queue
            }
            Log.Information("Batch {0} received from message queue containing {1} vouchers", ocrBatch.JobIdentifier, ocrBatch.Vouchers.Count());
            OcrService.ProcessBatch(ocrBatch);
        }
        public override void Consumer_ReceiveMessage(IBasicGetResult message)
        {
            base.Consumer_ReceiveMessage(message);
            if (!ContinueProcessing)
            {
                return;
            }

            var request = Message;

            Log.Information("Processing GetVouchersInformationResponse '{@request}', '{@correlationId}'", request, CorrelationId);

            try
            {
                var jobIdentifier = CorrelationId;
                var batchNumber   = string.Empty;

                if (request.voucherInformation.Length == 0)
                {
                    Log.Information("No matching vouchers found GetVouchersInformationResponse '{@batchNumber}', '{@jobIdentifier}'", batchNumber, jobIdentifier);

                    //Mapping responseDone fields
                    var responseDoneOutput = new DipsResponseDone
                    {
                        guid_name         = CorrelationId,
                        response_time     = DateTime.Now,
                        number_of_results = 0
                    };

                    using (var dbConnection = new SqlConnection(Configuration.SqlConnectionString))
                        using (var dipsDbContext = new DipsDbContext(dbConnection))
                        {
                            using (var tx = dipsDbContext.BeginTransaction())
                            {
                                try
                                {
                                    //Adding to DipsResponseDone table
                                    dipsDbContext.DipsResponseDone.Add(responseDoneOutput);
                                    dipsDbContext.SaveChanges();

                                    tx.Commit();

                                    Log.Information("Successfully processed GetVouchersInformationResponse '{@batchNumber}', '{@jobIdentifier}'", batchNumber, jobIdentifier);
                                }
                                catch (OptimisticConcurrencyException)
                                {
                                    //this is to handle the race condition where more than instance of this service is running at the same time and tries to update the row.

                                    //basically ignore the message by loggin a warning and rolling back.
                                    //if this row was not included by mistake (e.g. it should be included), it will just come in in the next batch run.
                                    Log.Warning(
                                        "Could not create a GetVouchersInformationResponse '{@GetVouchersInformationResponse}', '{@jobIdentifier}' because the DIPS database row was updated by another connection",
                                        request, jobIdentifier);

                                    tx.Rollback();
                                }
                                catch (Exception ex)
                                {
                                    Log.Error(
                                        ex,
                                        "Could not complete and create a GetVouchersInformationResponse '{@GetVouchersInformationResponse}', '{@jobIdentifier}'",
                                        request, jobIdentifier);
                                    tx.Rollback();
                                }
                            }
                        }
                }
                else
                {
                    //Mapping criteria fields
                    var firstVoucher = request.voucherInformation.First();
                    var criterias    = MapToCriterias(firstVoucher);
                    var jsonPayload  = JsonConvert.SerializeObject(criterias);

                    //Mapping responseDone fields
                    var responseDoneOutput = new DipsResponseDone
                    {
                        guid_name         = CorrelationId,
                        response_time     = DateTime.Now,
                        number_of_results = 1
                    };

                    //Mapping responsData fields
                    var responseDataOutput = new DipsResponseData
                    {
                        doc_ref_number = firstVoucher.voucher.documentReferenceNumber,
                        guid_name      = CorrelationId,
                        payload        = jsonPayload,
                        front_image    = System.Text.Encoding.Default.GetString(firstVoucher.voucherImage[0].content),
                        rear_image     = System.Text.Encoding.Default.GetString(firstVoucher.voucherImage[1].content)
                    };

                    using (var dbConnection = new SqlConnection(Configuration.SqlConnectionString))
                        using (var dipsDbContext = new DipsDbContext(dbConnection))
                        {
                            using (var tx = dipsDbContext.BeginTransaction())
                            {
                                try
                                {
                                    //Adding to DipsResponseData table
                                    dipsDbContext.DipsResponseData.Add(responseDataOutput);
                                    Log.Verbose("Adding new response data {@drn} to the database", request.voucherInformation.First().voucher.documentReferenceNumber);

                                    dipsDbContext.SaveChanges();

                                    //Adding to DipsResponseDone table
                                    dipsDbContext.DipsResponseDone.Add(responseDoneOutput);
                                    Log.Verbose("Adding new response data done row to the database");

                                    dipsDbContext.SaveChanges();

                                    tx.Commit();

                                    Log.Information("Successfully processed GetVouchersInformationResponse '{@batchNumber}', '{@jobIdentifier}'", batchNumber, jobIdentifier);
                                }
                                catch (OptimisticConcurrencyException)
                                {
                                    //this is to handle the race condition where more than instance of this service is running at the same time and tries to update the row.

                                    //basically ignore the message by loggin a warning and rolling back.
                                    //if this row was not included by mistake (e.g. it should be included), it will just come in in the next batch run.
                                    Log.Warning(
                                        "Could not create a GetVouchersInformationResponse '{@GetVouchersInformationResponse}', '{@jobIdentifier}' because the DIPS database row was updated by another connection",
                                        request, jobIdentifier);

                                    tx.Rollback();
                                    InvalidExchange.SendMessage(message.Body, RecoverableRoutingKey, CorrelationId);
                                }
                                catch (Exception ex)
                                {
                                    Log.Error(
                                        ex,
                                        "Could not complete and create a GetVouchersInformationResponse '{@GetVouchersInformationResponse}', '{@jobIdentifier}'",
                                        request, jobIdentifier);
                                    tx.Rollback();
                                    InvalidExchange.SendMessage(message.Body, RecoverableRoutingKey, CorrelationId);
                                }
                            }
                        }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error processing GetVouchersInformationResponse {@GetVouchersInformationResponse}", request);
                InvalidExchange.SendMessage(message.Body, InvalidRoutingKey, CorrelationId);
            }
        }