web-dev-qa-db-fra.com

Hangfire tâches récurrentes sous minute

Existe-t-il un moyen de définir des tâches récurrentes à plusieurs reprises toutes les quelques secondes? Je ne cherche pas de solution dans laquelle feu et oubli tâche crée un autre feu et oublie tâche, et si non, quelles sont les alternatives suggérées?

12
Robert

Hangfire ne prend pas en charge des intervalles inférieurs à une minute pour les travaux récurrents. 

Pourquoi? Imaginez s’ils laissaient moins d’une minute: disons 1 seconde. À quelle fréquence Hangfire vérifierait-il les travaux récurrents dans la base de données? Cela causerait beaucoup d'E/S de base de données. 

Voir cette discussion sur Hangfire pour plus d'informations.

4
jtabuloc

Je pense que quiconque s'oppose à ce que l'on autorise un déclencheur récurrent de moins d'une minute est à courte vue. Après tout, est-ce que 55 secondes sont moins efficaces qu'une minute? Cela semble tellement arbitraire! Même si j'adore Hangfire, j'ai rencontré des situations dans lesquelles je devais diriger un client vers Quartz.net simplement parce qu'il était nécessaire pour un poste de s'exécuter toutes les 55 secondes ou plus.

Quiconque fait valoir que si le système était configuré pour s'exécuter toutes les 1 s, l'impact sur les performances serait grave, c'est encore une fois avoir une vision fermée des choses. Bien sûr, un déclencheur avec un intervalle de 1 seconde n'est probablement pas une bonne idée, mais dissalowons-nous 55 ou 45 secondes pour la situation improbable dans laquelle une personne choisira 1 seconde? 

Dans tous les cas, les performances sont à la fois subjectives et dépendantes de la plate-forme et du matériel de l'hôte. L’API n’a pas à imposer son opinion en matière de performances. Il suffit de configurer l’intervalle d’interrogation et la périodicité de déclenchement. De cette façon, l'utilisateur peut déterminer le meilleur résultat pour lui-même.

Bien qu'un processus en arrière-plan orchestrant l'exécution d'une tâche toutes les 55 secondes puisse être une option, il n'est pas très satisfaisant. Dans ce cas, le processus n'est pas visible via l'interface utilisateur Hangfire, il est donc masqué par l'administrateur. Je pense que cette approche contourne l’un des principaux avantages de Hangfire.

Si Hangfire était un concurrent sérieux de Quartz.net, il correspondrait au moins à ses fonctionnalités de base. Si Quartz peut supporter les déclencheurs avec un intervalle inférieur à 1 min, pourquoi pas Hangfire!

17
PatrickNolan

Bien que Hangfire ne vous permette pas de planifier des tâches pendant moins d'une minute, vous pouvez y parvenir en programmant la fonction de manière récursive. Par exemple, supposons que vous vouliez qu'une méthode soit utilisée toutes les 2 secondes, vous pouvez planifier un travail en arrière-plan qui appelle la méthode au démarrage;

BackgroundJob.Schedule(() => PublishMessage(), TimeSpan.FromMilliseconds(2000));

Et ensuite, dans votre méthode PublishMessage, faites votre travail, puis programmez un travail pour appeler la même méthode;

public void PublishMessage()
    {
        /* do your stuff */

        //then schedule a job to exec the same method
        BackgroundJob.Schedule(() => PublishMessage(), TimeSpan.FromMilliseconds(2000));
    }

L'autre chose que vous devez remplacer est la valeur par défaut SchedulePollingInterval de 15 secondes, sinon votre méthode ne sera utilisée que toutes les 15 secondes. Pour ce faire, il suffit de passer une instance de BackgroundJobServerOptions to UseHangfireServer dans votre démarrage, comme suit;

var options = new BackgroundJobServerOptions
        {
            SchedulePollingInterval = TimeSpan.FromMilliseconds(2000)
        };

        app.UseHangfireServer(options);

Je ne sais pas à quel point ma solution est "infaillible", mais j'ai réussi à atteindre mon objectif avec elle et tout est "heureux" en production.

4
takaz

J'ai affronté le même problème, et voici ma solution:

private void TimingExecuteWrapper(Action action, int sleepSeconds, int intervalSeconds)
{
    DateTime beginTime = DateTime.UtcNow, endTime;
    var interval = TimeSpan.FromSeconds(intervalSeconds);
    while (true)
    {
        action();
        Thread.Sleep(TimeSpan.FromSeconds(sleepSeconds));
        endTime = DateTime.UtcNow;
        if (endTime - beginTime >= interval)
            break;
    }
}

intervalSeconds est l'intervalle NCRON minimal. C’est une minute. Action est notre code de travail. Je suggère également d’utiliser DisableConcurrentExecution pour éviter certaines collisions de concurrence.

0
daniil_

J'avais une exigence similaire, en ce sens que j'avais un travail récurrent qui devait être exécuté toutes les 15 secondes. Pour contourner ce problème, j'ai simplement retardé la création des travaux planifiés (défini sur 1 minute Cependant, ce que j’ai découvert, c’est que, compte tenu des intervalles de scrutation (définir l’intervalle de planification à ma fréquence) et des retards dans la reprise des nouveaux travaux, cela n’est pas toujours le cas. aussi précis que cela devrait être, mais fait le tour pour le moment. Cependant, une solution meilleure/appropriée serait bonne.

je me sens un peu sale de devoir adopter l’approche ci-dessous, mais cela m’a aidé… . En résumé, j’ai créé 4 emplois faisant la même chose, à 15 secondes d’écart l'un de l'autre. de:

...

new Thread(() =>
{
    //loop from {id=1 through 4}
    //   create job here with {id} in the name at interval of 1 minute
    //   sleep 15 seconds
    //end loop
}).Start();    
...
0
Francois