Beware of TimerTrigger in Azure Functions

TimerTrigger is one of the easiest triggers in Azure Functions to handle. It has however an interesting "issue", which is described in the documentation - you should not use the same id property for different Function App. Why is that?

Just as planned

Let's assume you have two identical functions triggered using TimerTrigger:

/
[FunctionName("TimerTrigger")]
public static void Run([TimerTrigger("0 */1 * * * *")]TimerInfo myTimer, TraceWriter log)
{
	log.Info($"TIMER trigger function executed at: {DateTime.Now}");
}

Assuming our host.json file is empty, after we deploy two Function Apps, we'll get following results:

As you can see both are working correctly(I changed displayed text a little bit so you can see the difference). Now let's abuse things a little - I forced two Function Apps to work under the same id. To do so I changed my host.json file:

/
{
  "id": "9f4ea53c5136457d883d685e57164f08"
}

With this change something broke:

As we can read in documentation:

If you share a Storage account across multiple function apps, make sure that each function app has a different id in host.json. You can omit the id property or manually set each function app's id to a different value. The timer trigger uses a storage lock to ensure that there will be only one timer instance when a function app scales out to multiple instances. If two function apps share the same id and each uses a timer trigger, only one timer will run.

What is the cause of such behaviour?

Underlying functionality

If you check the underlying storage powering Azure Function, you'll find azure-webjobs-host container, which stores e.g. locks from TimerTrigger. Mine looks like this:

As you can see I have 3 different locks - timertriggertest come from the previous version of my functionality, where I didn't have id explicitely set. The very first folder is named using id property in host.json file.

We can find also in the source code. There's a class PrimaryHostCoordinator, which is used to determine which host instance is the primary one. It is initialized at the very beginning after functions has been loaded and tries to aquire a lock on a blob every 5 seconds. If it fails, a function won't be triggered. Remember not to set id if you don't have to and if you do, try to avoid using functions tiggered by TimerTrigger in different Function Apps.

Working with Azure Functions in Visual Studio Code like a boss

So after a while I decided to finally check Azure Functions extensions out in Visual Studio Code. I often want to check something really quickly and being forced to open Visual Studio each time makes me furious. I must say that initially I was a bit skeptical regarding Code functionality, but it turns out to be superb. Let's check what it offers for now.

Installing

Installing the extensions is super easy. Just go to the Extensions menu and search for Azure Functions:

Once extensions is installed you can easily disable or uninstall it

For now - that's really all!

Creating a function

With Azure Functions plugin installed you should be able to see available subscriptions in the Explorer area. If not left-click on the status bar where your username is displayed and select the ones you're interested in:

Workspace with only one subscription selected

 

Installing the extension gives you some more features. Now you're able to work with a project, create a function and publish it. Let's start with a function triggered by a HTTP request. Click on "Create New Project Button":

Now you're able to select a current location or create a new one where your project will be placed. Once you're satisfied you can select a language and... that's all, your workspace is ready to start working on a function.

Empty Functions project ready to rock!

Now let's create a function. You can create in in a similar way as a project. After providing all necessary data(like a name, a type of trigger, security level), a template will be created so you can start modyfing it as you wish.

A template, very similar to the one created in Visual Studio

Running a function

You can easily start testing your function by pressing F5. It'll start runtime and you'll be given an endpoint, which you can call anytime:

Publishing a function

Publishing a function from Visual Studio Code is as easy as other tasks. Once more go to the Azure Functions workspace and select "Deploy to Function App". You'll be asked about many different parameters like a subscription, resource group or storage account. Once everything's configured wait a second(or maybe two) until a function is published. You can start using it!

Function published along with a storage account and consumption plan

Summary

In the current shape VS Code will not replace full Visual Studio(at least for me personally), but I found Azure Functions extension extremely helpful in the smaller projects, which are developed fully in Code. If I don't have to switch between IDEs, I'm more than happy.