private static void Main(string[] args)
        {
            Task.Run(() =>
            {
                try
                {
                    // initialize settings
                    Init();

                    Console.WriteLine($"Processor is now running...");

                    ConnectionFactory factory = new ConnectionFactory();
                    factory.UserName          = ApplicationSettings.RabbitMQUsername;
                    factory.Password          = ApplicationSettings.RabbitMQPassword;
                    factory.HostName          = ApplicationSettings.RabbitMQHostname;
                    factory.Port = ApplicationSettings.RabbitMQPort;
                    factory.RequestedHeartbeat     = 60;
                    factory.DispatchConsumersAsync = true;

                    var connection = factory.CreateConnection();
                    var channel    = connection.CreateModel();

                    channel.QueueDeclare(queue: ApplicationSettings.DispatchQueueName,
                                         durable: true,
                                         exclusive: false,
                                         autoDelete: false,
                                         arguments: null);

                    channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);

                    var consumer       = new AsyncEventingBasicConsumer(channel);
                    consumer.Received += async(model, ea) =>
                    {
                        DispatchResponse response = new DispatchResponse
                        {
                            IsSucceded = true,
                            ResultId   = (int)DispatchResponseEnum.Success
                        };

                        // forced-to-disposal
                        Report report                 = null;
                        PDFHelper pdfHelper           = null;
                        MongoDBHelper mongoDBHelper   = null;
                        SendGridHelper sendGridHelper = null;

                        try
                        {
                            byte[] body = ea.Body;
                            var message = Encoding.UTF8.GetString(body);

                            var decrypted = string.Empty;
                            decrypted     = NETCore.Encrypt.EncryptProvider.AESDecrypt(message, secret);

                            var obj_decrypted = JsonConvert.DeserializeObject <DispatchMessage>(decrypted);

                            //operation id
                            string guid = Guid.NewGuid().ToString();

                            // PDF
                            string pdf = string.Empty;
                            pdfHelper  = new PDFHelper();
                            pdf        = pdfHelper.Create(guid, converter, obj_decrypted);
                            Console.WriteLine($">> PDF generated successfully");

                            // MongoDB
                            report          = new Report();
                            report.fullname = obj_decrypted.Fullname;
                            report.email    = obj_decrypted.Email;

                            mongoDBHelper = new MongoDBHelper(mongoDBConnectionInfo);
                            await mongoDBHelper.RegisterReportAsync(report);
                            Console.WriteLine($">> Record saved successfully");

                            // SendGrid
                            sendGridHelper = new SendGridHelper();
                            await sendGridHelper.SendReportEmailAsync(obj_decrypted.Email, obj_decrypted.Fullname, pdf);
                            Console.WriteLine($">> Email: {obj_decrypted.Email} sent successfully");

                            channel.BasicAck(ea.DeliveryTag, false);
                            Console.WriteLine($">> Acknowledgement completed, delivery tag: {ea.DeliveryTag}");
                        }
                        catch (Exception ex)
                        {
                            if (ex is BusinessException)
                            {
                                response.IsSucceded = false;
                                response.ResultId   = ((BusinessException)ex).ResultId;

                                string message = EnumDescription.GetEnumDescription((DispatchResponseEnum)response.ResultId);
                                Console.WriteLine($">> Message information: {message}");
                            }
                            else
                            {
                                Console.WriteLine($">> Exception: {ex.Message}, StackTrace: {ex.StackTrace}");

                                if (ex.InnerException != null)
                                {
                                    Console.WriteLine($">> Inner Exception Message: {ex.InnerException.Message}, Inner Exception StackTrace: {ex.InnerException.StackTrace}");
                                }
                            }
                        }
                        finally
                        {
                            report = null;
                            pdfHelper.Dispose();
                            mongoDBHelper.Dispose();
                            sendGridHelper.Dispose();
                        }
                    };

                    string consumerTag = channel.BasicConsume(ApplicationSettings.DispatchQueueName, false, consumer);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($">> Exception: {ex.Message}, StackTrace: {ex.StackTrace}");

                    if (ex.InnerException != null)
                    {
                        Console.WriteLine($">> Inner Exception Message: {ex.InnerException.Message}, Inner Exception StackTrace: {ex.InnerException.StackTrace}");
                    }
                }
            });

            // handle Control+C or Control+Break
            Console.CancelKeyPress += (o, e) =>
            {
                Console.WriteLine("Exit");

                // allow the manin thread to continue and exit...
                waitHandle.Set();
            };

            // wait
            waitHandle.WaitOne();
        }