Fonction Azure avec Timer trigger

Dans le cadre de la remise à niveau d'une application SaaS que nous éditons, nous nous sommes aperçus qu'il restait une ressource Azure Mobile Services convertie entre-temps en Scheduler Job Collection.

Ce service nous permettait à l'origine de planifier des tâches CRON à moindre coût (gratuit). Le nouveau service permet la même chose mais avec un tarif moins intéressant.

Afin d'alléger le coût de fonctionnement de notre application et surtout pour jouer avec les dernières nouveautés Azure, nous avons converti ce Scheduled Job en Azure Function avec un timer trigger.

Ajoutons d'abord un projet Azure Functions dans notre solution :

Restons pour le moment sur la version 1 du runtime. Nous voulons donc un Timer trigger exécuté toutes les 15 minutes :

Après avoir mis à jour le package Nuget "Microsoft.NET.Sdk.Functions" et installé "System.Configuration.ConfigurationManager", nous pouvons commencer le code. Il s'agit dans notre cas d'appeler une API à chaque exécution de la fonction.

using System;
using System.Configuration;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;

namespace TestProject.Functions
{
    public static class ScheduleGetOrders
    {
        [FunctionName("ScheduleGetOrders")]
        public async static Task Run(
          [TimerTrigger("0 */15 * * * *", RunOnStartup = true)] TimerInfo myTimer,
          TraceWriter log)
        {
            log.Info($"C# Timer trigger function executed at: {DateTime.Now}");

            // Les paramètres de l'API (URL et token) sont stockés en variables
            // d'environnement pour ne pas les écrire en dur dans le code,
            // ni les envoyer sur notre gestionnaire de version (Git).
            var url = ConfigurationManager.AppSettings["API_URL"];
            var token = ConfigurationManager.AppSettings["API_TOKEN"];

            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Authorization
                  = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", token);
                var result = await client.GetAsync(url);

                if (result.IsSuccessStatusCode)
                {
                    log.Info($"Success {result.StatusCode}");
                }
                else
                {
                    log.Error($"Error {result.StatusCode} {result.ReasonPhrase}");
                }
            }
        }
    }
}

Il nous reste à ajouter la configuration dans le fichier "local.settings.json" :

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "AzureWebJobsDashboard": "UseDevelopmentStorage=true",
    "API_URL": "https://example.com/api/Job/Get?type=ScheduleGetOrders",
    "API_TOKEN": "sdfgSDfgSDFGsdfgSDFGsdfgSDFgDSFGdsfGSDFGsdfgsDFGSDFgsdFGSDfgsdfgsdf="
  }
}

Et à exécuter la fonction en local pour vérifier que tout fonctionne correctement :

Tout est OK, nous pouvons publier la fonction sur Azure comme une application Web ordinaire :

Une dernière étape avant de terminer, la configuration sur le portail Azure :

Et vérifier que la fonction tourne sur Azure :

C'est terminé, nous pouvons maintenant arrêter le Job Scheduler et le supprimer dans quelques jours après avoir vérifié que la fonction Azure a bien pris le relais.