I have a time triggered Azure Function deployed in multiple regions and I want to have singleton behavior across them. For example, if the regions are west US and central Europe, I want only one of them to run each time. Can this be achieved?
As the documentation says, TimeTrigger uses the Singleton attribute implicitly to ensure only one instance of a function is run per host, so that aspect is covered.
In order to have the same behavior in all regions, I tried using Singleton with the following parameters:
[Singleton(Account = "myAccount", Mode = SingletonMode.Listener)]
I tested it locally by copying my C# solution and running both projects. The following error was shown:
The listener for function 'MyFunction' was unable to start.
Microsoft.Azure.WebJobs.Host.Storage: Must replace singleton lease manager to
support multiple accounts.
I did not find information about the Account
property more than from the metadata of the Singleton class, that says Gets the name of the Azure Storage account that the blob lease should be created in
. I don't know how the function knows how to connect to the Storage and where to configure the connection.
I believe the
Account
property of the[Singleton]
attribute refers to the name of an app setting, not actually the name of your storage account. If not specified, it assumes the storage account specified by theAzureWebJobsStorage
app setting. The app setting that you reference here will need to contain the full storage connection string.Note that if you want cross-region singleton behavior, all copies of your app will need to use the same storage account (which obviously could live in some other region). I expect there will be some egress charges related to this, but hopefully not enough to have much impact. Something to be aware of, though.
UPDATE:
Regarding the error message you encountered, it turns out there's actually an issue with this feature in Functions 2.0. A new GitHub issue was recently opened which tracks the problem: https://github.com/Azure/azure-webjobs-sdk/issues/2214. It also points to a temporary workaround, which is that you can register your own
IDistributedLockManager
implementation, as shown in the test code.