Как отправить dbcontext/единицу работы в фильтр заданий Hangfire

Мы используем Hangfire для некоторых ночных и длительных заданий и отслеживаем дополнительные связанные сведения/метаданные для каждого задания в отдельной базе данных, чтобы избежать проблем с обновлением Hangfire в будущем. Фильтр вакансий (https://docs.hangfire.io/en/latest/extensibility/using-job-filters.html) поможет нам гораздо проще отслеживать статус каждого задания, но я не могу найти пример того, как отправлять зависимости в задание фильтр.

Мы используем ASP.NET Core с внедрением зависимостей (DI) и шаблонами репозиторий + единица работы.

Как я могу получить доступ к контексту базы данных (или единице работы или любым другим элементам, доступным через DI) из фильтра заданий?

Спасибо

EDIT Я создал репозиторий с небольшим примером проекта, в котором показано, что я пытаюсь здесь сделать: https://github.com/joelpereira/hfjobfilter/tree/master./HFJobFilter

Он компилируется, но в строке есть ошибка: .UseFilter(new TypeFilterAttribute(typeof(LogToDbAttribute)))


person ssvyper    schedule 26.04.2019    source источник


Ответы (1)


По моему мнению, вы можете попробовать добавить JobFilter как TypeFilter, и он автоматически вставит зависимости, если таковые имеются, в конструктор вашего LogEverythingAttribute, поэтому изменив пример из предоставленной вами ссылки:

public class EmailService
{
    [TypeFilter(typeof(LogEverything))]
    public static void Send() { }
}

GlobalJobFilters.Filters.Add(new TypeFilterAttribute(typeof(LogEverythingAttribute())));

Отказ от ответственности: я не проверял вышеуказанное самостоятельно, поэтому, пожалуйста, дайте мне знать, если это сработает.

Отредактировано

Попробуйте настроить Hangfire, как показано ниже в ConfigureServices, и посмотрите, работает ли это.

services.AddHangfire(config =>
{
    config.UseFilter(new TypeFilterAttribute(typeof(LogToDbAttribute)));

    // if you are using the sqlserverstorage, uncomment the line and provie
    // the required prameters
    // config.UseSqlServerStorage(connectionString, sqlServerStorageOptions);
});

ОБНОВЛЕННЫЙ ОТВЕТ

Пожалуйста, ознакомьтесь с изменениями, которые я внес в предоставленный вами код. Я протестировал его, и он работает. Несколько моментов, на которые следует обратить внимание ниже.

Посмотрите, как я зарегистрировал HttpClient, используя метод AddHttpClient, который использует HttpClientFactory и Typed Clients. Это рекомендуемый способ использования HttpClient. Подробнее об этом можно прочитать здесь

services.AddHttpClient<HfHttpClient>(client =>
{
    client.BaseAddress = new Uri("http://localhost:44303");

    // you can set other options for HttpClient as well, such as
    //client.DefaultRequestHeaders;
    //client.Timeout
    //...
});

Кроме того, вам потребуется зарегистрировать LogDbAttribute, а затем разрешить его в вызове UseFilter, используя IServiceProvider

// register the LogToDbAttribute
services.AddSingleton<LogToDbAttribute>();
// build the service provider to inject the dependencies in LogDbAttribute
var serviceProvider = services.BuildServiceProvider();
services.AddHangfire(config => config
.UseSqlServerStorage(Configuration.GetConnectionString("HangfireDBConnection"))
.UseFilter(serviceProvider.GetRequiredService<LogToDbAttribute>()));

Я также внедрил ILogger, чтобы продемонстрировать, что он работает. По какой-то причине, если вы попытаетесь что-то сделать с HttpClient, он зависнет. Возможно, причина в том, что это фоновая работа, и все вызовы HttpClient асинхронны, поэтому он не возвращается, и два процесса пытаются дождаться друг друга.

Если вы планируете внедрить HttpClient, возможно, вам придется изучить его. Тем не менее, регистратор работает нормально.

Кроме того, вам не нужно наследовать LogDbAttribute от TypeFilterAttribute. Решение TypeFilterAttribute не работает, как я первоначально предполагал.

person Shahzad Hassan    schedule 26.04.2019
comment
Получение ошибок компилятора. Класс атрибута LogToDB: public class LogToDB : Microsoft.AspNetCore.Mvc.TypeFilterAttribute, IClientFilter, IServerFilter, IElectStateFilter, IApplyStateFilter { Ошибка в этой строке конструктора: public LogToDB(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; } ошибка: не указан аргумент, соответствующий требуемому формальному параметру «тип» «TypeFilterAttribute.TypeFilterAttribute(Type)». Спасибо за столь быстрый ответ. - person ssvyper; 26.04.2019
comment
о, я думаю, что я сделал ошибку там. Должно быть new TypeFilterAttribute(typeof(LogToDB)). Также не уверен, используете ли вы класс GlobalConfiguration для настройки HangFire и GlobalJobFilters для добавления фильтров или используете метод расширения AddHangfire для IServicesCollection. Посмотрите мой отредактированный ответ и посмотрите, работает ли он. - person Shahzad Hassan; 27.04.2019
comment
Хорошо, позвольте мне взглянуть. Я вернусь к вам по этому поводу. Я думаю, вам может понадобиться реализовать собственный JobActivator. - person Shahzad Hassan; 27.04.2019
comment
@ssvyper Пожалуйста, взгляните на обновленный ответ. Я протестировал его, и он работает. надеюсь, это поможет - person Shahzad Hassan; 28.04.2019