Запуск задач по расписанию в Quartz.NET

Проект asp.net core 3.1 web-api. Возникла необходимость автоматической отправки с определенной периодичностью POST-запросов на сторонний сервис, получения с него данных и записи их в БД.

Реализацию пытаюсь делать через фреймверк Quartz.NET. Она получается следующая, не уверен что верная, поправьте пожалуйста где не верно:

public interface IRequestSender
    {
        Task<ResponseMessageDataQRCode> SendRequestAsync(string url, IEnumerable<KeyValuePair<string, string>> data, string str);
        public Task<ReportQrCodeExchange> RequestQRcodesReceiving(string url, Dictionary<string, string> requestDataDict);
    }

Класс реализующий интерфейс IRequestSender и отвечающий за всю работу (отправка запроса, получение ответа, обработка и запись ответа в БД через dbcontext):

public class RequestSender : IRequestSender
    {
        private readonly HttpClient httpClient;
        private ServicesQRcodes _servicesQRcodes;

        public RequestSender()
        {
            httpClient = new HttpClient();
            _servicesQRcodes = new ServicesQRcodes();
        }

        public async Task<ReportQrCodeExchange> RequestQRcodesReceiving(string url, Dictionary<string, string> requestDataDict)
        {
            ReportQrCodeExchange reportQrCodeExchange = new ReportQrCodeExchange();
            ResponseMessageDataQRCode responseData = null;
            try
            {
                responseData = await SendRequestAsync(url, requestDataDict, "");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            if (responseData != null)
            {
                if (responseData.status.Equals("200") || responseData.status.Equals("OK"))
                {
                    try
                    {
                        ResponseMessageDataQRCodeSuccessfully responseMessageDataQRCodeSuccessfully = (ResponseMessageDataQRCodeSuccessfully)responseData;
                        reportQrCodeExchange = _servicesQRcodes.CheckQrCodes(responseMessageDataQRCodeSuccessfully);
                    }
                    catch
                    {
                        ResponseMessageDataQRCodeError responseMessageDataQRCodeError = (ResponseMessageDataQRCodeError)responseData;

                        foreach (string str in responseMessageDataQRCodeError.items)
                        {
                            responseMessageDataQRCodeError.items.Append(str);
                        }
                        reportQrCodeExchange.error = responseData.error;
                        reportQrCodeExchange.status = responseData.status;
                        reportQrCodeExchange.dateTimeRequest = responseData.date;
                    }
                }
                else
                {
                    reportQrCodeExchange.error = responseData.error;
                    reportQrCodeExchange.status = responseData.status;
                    reportQrCodeExchange.dateTimeRequest = responseData.date;
                    return reportQrCodeExchange;
                }
            }

            return reportQrCodeExchange;
        }
        public async Task<ResponseMessageDataQRCode> SendRequestAsync(string url, IEnumerable<KeyValuePair<string, string>> data, string str)
        {
            ResponseMessageDataQRCode responseData = null;

            using var request = new HttpRequestMessage(HttpMethod.Post, url)
            {
                Content = new FormUrlEncodedContent(data)
            };
            request.Headers.Add("Application", "remoteData");
            var response = await httpClient.SendAsync(request).ConfigureAwait(false);
            string jsonResponseData = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            if (response.IsSuccessStatusCode)
            {

                if (FindItemsToken(jsonResponseData) == JsonTokenType.StartObject) //indxF==-1 && indxL==-1 && indxF>=indxL
                {
                    responseData = JsonSerializer.Deserialize<ResponseMessageDataQRCodeSuccessfully>(jsonResponseData);
                }
                else if (FindItemsToken(jsonResponseData) == JsonTokenType.StartArray)
                {
                    responseData = JsonSerializer.Deserialize<ResponseMessageDataQRCodeError>(jsonResponseData);
                }
            }
            else
            {
                responseData = JsonSerializer.Deserialize<ResponseMessageDataQRCodeError>(jsonResponseData);
            }
            return responseData;
        }

        //Проверка типа объекта в JSON после имени свойства "items"
        private static JsonTokenType FindItemsToken(string json)
        {
            var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json));
            while (reader.Read())
            {
                if (reader.TokenType == JsonTokenType.PropertyName && reader.GetString() == "items")
                    break;
            }
            if (!reader.Read()) return JsonTokenType.None;

            return reader.TokenType;
        }      

    }
}

Класс непосредственно запускающий экземпляр задачи/работы:

[DisallowConcurrentExecution]
    public class RequestJob : IJob
    {
        private readonly IRequestSender _requestSender;
        private readonly string url = "https://хххххх/app/api/barcodes/get.php";

        public RequestJob(IRequestSender requestSender)
        {
            this._requestSender = requestSender;
        }
        public Task Execute(IJobExecutionContext context)
        {
            string dateTimeRequestStr;
            DateTime dateTimeUTC = DateTime.UtcNow;
            dateTimeRequestStr = dateTimeUTC.AddHours(3).ToString("yyyy-MM-dd hh:mm:ss");

            Dictionary<string, string> requestMessageDict = new Dictionary<string, string>
            {
                ["token"] = "N2U1OThkZDZkZDliZGFiM/lAfhoRNk0D+iJh2Z1h1fpYEUWXkzsbvGg1",
                ["date"] = dateTimeRequestStr
            };
             _requestSender.RequestQRcodesReceiving(url,requestMessageDict);

            // отправили запрос, получили ответ, записали в БД данные ответа
            return Task.CompletedTask;
        }
    }

Класс фабрики управляющей запускам задач/работ:

public class SingletonJobFactory : IJobFactory
    {
        private readonly IServiceProvider _serviceProvider;
        public SingletonJobFactory(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
        {
            return _serviceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
        }

        public void ReturnJob(IJob job)
        {
        }
    }

Настройка всего этого в Startup.cs:

services.AddQuartz(q =>
            {
                q.UseMicrosoftDependencyInjectionScopedJobFactory();

                // Create a "key" for the job
                var jobKey = new JobKey("RequestJob");

                // Register the job with the DI container
                q.AddJob<RequestJob>(opts => opts.WithIdentity(jobKey));

                // Create a trigger for the job
                q.AddTrigger(opts => opts
                    .ForJob(jobKey) // link to the RequestJob
                    .WithIdentity("RequestJob-trigger") // give the trigger a unique name
                    .StartNow()
                    .WithSimpleSchedule(x =>
                        x.WithIntervalInMinutes(1)
                        .RepeatForever()));
            });
            services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);

Выставил интервал 1 минуту в настройках services.AddQuartz в Startup.cs, поставил точку остановы в классе RequestJob : IJob, запустил в режиме отладки, по идее если бы задача запустилась бы, тчк остановы должна была сработать, о она не сработала, значит где-то ошибка, не пойму где?


Ответы (0 шт):