7

I'm building a job to trigger at some regular interval (say 1 minute). I've successfully used triggered web jobs with time-span hard coded in the functions.

public void foo([TimerTrigger("00:01:00")] TimerInfo timer)

Now if I ever want to change the trigger time from 1-min to 2-min I've to redeploy the code. Instead is there a way to make the TimeTrigger Configurable, from a config file.

Note that replacing the string with a dynamically read value isn't possible as the TimerTrigger Attribute is a const string expression or a Type.

Manikanta Dornala
  • 951
  • 1
  • 9
  • 20

4 Answers4

10

After much digging, I've realized that this can be done with an SDK extension class TimerSchedule.

For it, you would need a base class that you'll be able to use for multiple triggers.

class CustomTimerTriggerBase: TimerSchedule
{
    TimeSpan timer;
    public CustomTimerTriggerBase(string triggerConfigKey)
    {
        timer=TimeSpan.Parse(ConfigurationManager.AppSettings[triggerConfigKey]);
    }

    public override DateTime GetNextOccurrence(DateTime now)
    {
        return now.Add(timer);
    }
}

Use this Base to generate your timers...

public sealed class FooTimer : CustomTimerTriggerBase
{
    public FooTimer() : base("FooTimerKey") {}
}

In your, App.config have a key for "FooTimer"

<add key="FooTimerKey" value="00:02:00" />

Use this FooTimer class in your webjob functions.

public void foo([TimerTrigger(typeof(FooTimer)] TimerInfo timer)

Now you can simply change the value in app config instead of redeploying the code. NOTE: Since you are using Timespan to parse, the string can be of any format you need as defined in TimeSpan formats.


UPDATE

As pointed by l--''''''---------'''''''''''' and Andy Dobedoe now (as of 2019) it is much simpler to achieve this.

public static async Task RunAsync([TimerTrigger("%MYCRON%")]TimerInfo myTimer

Finds the setting called MYCRON and uses the cron expression from there

Manikanta Dornala
  • 951
  • 1
  • 9
  • 20
  • This no longer works. If you put a `FunctionName` attribute on a function (needed for it to work) and a `TimerTrigger` that takes a `type` rather than a cron expression, it fails to compile with "System.NotImplementedException: Property 'ScheduleType' on attribute 'TimerTriggerAttribute' is not supported in Azure Functions." – Mason Wheeler Feb 24 '19 at 20:09
9

You can do this like so:

public static void Run([TimerTrigger("%MYSCHEDULE%")] TimerInfo myTimer, ILogger log)

where MYSCHEDULE is an environment variable which you can store in your local.settings.json file as well as in your application settings in the portal.

An example value for MYSCHEDULE would be:

"MYSCHEDULE": "0 */2 * * * *"
Alex Gordon
  • 51,480
  • 273
  • 609
  • 976
7

It turns out, this is pretty easy nowadays. Just put the app setting in as your cron schedule expression and it will look it up for you.

e.g.

public static async Task RunAsync([TimerTrigger("%MYCRON%")]TimerInfo myTimer

Finds the setting called MYCRON and uses the cron expression from there

Andy Dobedoe
  • 459
  • 1
  • 5
  • 8
1

AFAIK, you need to specific the scheduleExpression parameter for TimerTrigger in your code or implement your WeeklySchedule or DailySchedule described in this sample TimerSamples.cs. For changing the schedule without re-deploy your code, I assume that you could leverage Azure Scheduler to trigger your webjob on some schedule and you could change the schedule settings as you expected without re-deploy your webjob. For more details, you could refer to the section about adding a scheduler job in this tutorial.

Bruce Chen
  • 17,123
  • 2
  • 14
  • 27
  • 1
    Thanks for the answer. I was looking for a more configurable way, instead of just weekly or daily scheduling. I figured a way to do it with the inbuilt Azure SDK's `TimerSchedule` extension. It's basically the same as `WeeklyScedule` and `DailySchedule`, with more control. – Manikanta Dornala Sep 25 '17 at 05:11