web-dev-qa-db-fra.com

Quelle est la manière la plus simple d'exécuter localement une fonction Azure déclenchée par une minuterie?

J'ai quelques fonctions Azure C # qui s'exécutent selon un calendrier utilisant déclencheurs de minuterie . Je les ai configurés comme ça, où %TimerSchedule% Fait référence à une expression cron dans les paramètres de l'application:

public static void Run([TimerTrigger("%TimerSchedule%")]TimerInfo myTimer, TraceWriter log)

Pendant le développement, je souhaite souvent exécuter les fonctions localement à l'aide des outils Azure Functions pour Visual Studio + Azure Functions Core Tools. Mais lorsque j'appuie sur F5 pour déboguer la fonction localement, elle ne s'exécute pas (généralement) immédiatement. Au lieu de cela, il commence à attendre la prochaine occurrence selon le calendrier du minuteur. Ainsi, par exemple, si mon expression cron dit de s'exécuter quotidiennement à 20 heures, je devrais attendre jusqu'à 20 heures pour que la fonction s'exécute réellement sur ma machine.

Donc ma question est: Quelle est la façon la plus simple et la meilleure de faire exécuter une fonction localement une fois?

Choses que j'ai essayées ou envisagées:

  1. Utilisez un horaire plus fréquent uniquement pour le développement local
    • C'est correct mais pas parfait - vous devez encore attendre un peu, sauf si c'est très fréquent, et si c'est très fréquent, la fonction peut s'exécuter plusieurs fois. Voilà ce que je fais maintenant.
  2. Écrivez une application console ou un test unitaire qui appelle directement la méthode Run() de la fonction
    • Ce n'est pas simple à 100% car vous devez fournir des arguments TimerInfo et TraceWriter à Run() - et j'ai trouvé étonnamment peu de documentation pour cela.

La page Stratégies pour tester votre code dans Azure Functions de Microsoft n'est pas très utile sur ce sujet - elle mentionne uniquement les déclencheurs de minuterie comme moyen de tester les types de déclencheurs autre.

Dans un monde parfait, je toucherais F5 et la fonction s'exécuterait immédiatement une fois - tout comme le développement d'une application .NET "normale".

35
ripley_

Vous pouvez peut-être utiliser l'indicateur RunOnStartup comme indiqué ici . Il ne répond pas tout à fait à votre mémoire concernant le fait qu'il ne fonctionne qu'une seule fois, mais il devrait au moins l'exécuter localement une fois que l'application a démarré.

/// Gets or sets a value indicating whether the function should be invoked
/// immediately on startup. After the initial startup run, the function will
/// be run on schedule thereafter.

Exemple utilisant la liaison d'attribut:

[TimerTrigger("%TimerSchedule%", RunOnStartup = true)]TimerInfo myTimer

53
Wah Yuen

J'ai eu la même question et utilisé le drapeau DEBUG pour avoir RunOnStartup uniquement lors du débogage:

        public static void Run(
            [TimerTrigger("* 0 7 * * 1-5"
#if DEBUG
            , RunOnStartup=true
#endif
            )]TimerInfo myTimer, TraceWriter log)
        {
33
BerDev

J'avais la même question. Je l'ai réparé avec un Unittest. En effet, vous devez supprimer le TraceWriter et le TimerInfo.

Voici un peu de code sur la façon dont j'ai fait cela.

TimerInfo:

public class ScheduleStub : TimerInfo
{
    public ScheduleStub(TimerSchedule schedule, ScheduleStatus status, bool isPastDue = false) : base(schedule, status, isPastDue)
    {
    }
}

Et le TraceWriter:

 public class TraceWriterStub : TraceWriter
{
    protected TraceLevel _level;
    protected List<TraceEvent> _traces;

    public TraceWriterStub(TraceLevel level) : base(level)
    {
        _level = level;
        _traces = new List<TraceEvent>();
    }

    public override void Trace(TraceEvent traceEvent)
    {
        _traces.Add(traceEvent);
    }

    public List<TraceEvent> Traces => _traces;
}
4
StefanHa

Ajoutez simplement une autre fonction avec le type de déclencheur HTTP dans la même classe, ajoutez votre code ou appelez votre méthode Run à partir de cette fonction et appelez-la à partir de votre navigateur.

Assurez-vous de commenter/supprimer cette fonction lors du déploiement sur prod, ou vous aurez la possibilité de déclencher la fonction via des appels HTTP dans prod.

0
Mike Cardona