Wednesday, 14 October, 2020 UTC


Summary

Timer-triggered Azure functions allow you to run a function on a configurable schedule. Unlike HTTP-triggered Azure functions, timing info is stored in an Azure storage account and then passed to the function on execution. As a result, once you add in a timer-triggered function for the first time, there may be some additional steps for running your function app project locally.
Basic Setup
Timer-triggered functions can be configured using a CRON expression. In C#, this schedule is set in your function’s TimerTrigger attribute:

[FunctionName("SendDailyEmail")]
public async Task SendDailyEmail([TimerTrigger("0 0 0 * * *")] TimerInfo timerInfo)
{
    await SendDailyEmail();
}
Once that is set up, you may need to make a few changes to your local.settings.json file before running your function app locally.
Changes to the AzureWebJobsStorage Field
First, make sure that the AzureWebJobsStorage field is set. Any non-HTTP-triggered function requires this and will not build if it’s not provided.
You could set the connection string for an actual Azure storage account (assuming you already have one set up):

{
  "Values": {
    "AzureWebJobsStorage": "<connection-string>"
  }
}
Or you could run an Azure storage account emulator and configure your local.settings.json to use local development storage:

{
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true"
  }
}
My personal preference for running Azurite is the VS Code extension; you can also install and run it using NPM or Docker.
Disabling the Function
A recurring function execution can be somewhat disruptive when trying to test or debug an unrelated issue, so it can also be helpful to disable your timer-triggered function. To disable the function, update local.setting.json with a new key for AzureWebJobs.{FunctionName}.Disabled set to “true” as a default:

{
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "AzureWebJobs.SendDailyEmail.Disabled": "true"
  }
}
Where to Configure the CRON Expression
Optionally, you could store the CRON expression for the timer-triggered function’s schedule in your settings file. This allows for different schedules across different environments and makes it easier to set it to a specific schedule to assist with manual debugging. Update your local.settings.json with a new key/value, and then reference this field in your timer-triggered function setup:

{
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "AzureWebJobs.SendDailyEmail.Disabled": "false",
    "DailyEmailSchedule": "0 0 0 * * *"
  }
}

[FunctionName("SendDailyEmail")]
public async Task SendDailyEmail([TimerTrigger("%DailyEmailSchedule%")] TimerInfo timerInfo)
{
    await SendDailyEmail();
}
Testing the Function (on Your Own Schedule)
Although you could technically just fire up your project and sit there waiting for the function to execute, it’s probably easiest to trigger the function manually. Luckily, you can still do this with a POST to an admin URL that includes the function name.
When testing locally, an Azure storage account should be connected, or a storage account emulator should be running. The function must not be disabled. Using VS Code’s REST Client extension, the request will look something like this:
###
# @name sendDailyEmailManualTrigger
POST http://localhost:7075/admin/functions/SendDailyEmail
Content-Type: application/json
{
}
To manually test against a deployed environment, you will need to include the function app’s master key.
Conclusion
These are the major changes we had to make to our local development environment to get our timer-triggered Azure functions running locally. Non-HTTP-triggered Azure functions require a bit of additional set up and a slightly different local environment configuration. Hopefully, following these steps will help speed up that process for your team.
The post Working with Timer-Triggered Azure Functions in C# appeared first on Atomic Spin.