Description
🩹 Workaround
Tip
In my case it helped to delete everything named "TestHub*" or "testhub*" from my local Azurite instance.
With everything I mean Blob Containers, Queues and Tables.
You can do this via Microsoft Azure Storage Explorer.
Warning
While I haven't lost any important data by deleting the testhub stuff from azurite, your mileage may vary.
Version
Core Tools Version: 4.0.7030
Function Runtime Version: 4.1037.0.23568
Description
I have 30 timer triggered functions that I generate with a template, that is, they are identical apart from a number in their names and the timer trigger. All the timer triggers look like this:
[TimerTrigger("0 * * * *", RunOnStartup = true)] TimerInfo timer
[TimerTrigger("2 * * * *", RunOnStartup = true)] TimerInfo timer
[TimerTrigger("4 * * * *", RunOnStartup = true)] TimerInfo timer
and so on (that is there's a function being triggered for every other minute of the hour - not that they don't do the exact same thing, so having a function that runs every minute would not achieve my goal,here).
For most of the functions I get an error like:
The listener for function 'Functions.Easee-StartImportPartition44' was unable to start. System.Private.CoreLib: The UTC time represented when the offset is applied must be between year 0 and 10,000. (Parameter 'offset').
And they are never executed.
For a few functions I don't, get an error. Example:
The next 5 occurrences of the 'Easee-StartImportPartition48' schedule (Cron: '48 * * * *') will be:
04/01/2025 17:48:00+02:00 (04/01/2025 15:48:00Z)
04/01/2025 18:48:00+02:00 (04/01/2025 16:48:00Z)
04/01/2025 19:48:00+02:00 (04/01/2025 17:48:00Z)
etc.
These are executed.
It's only the functions for minutes 48, 50, 52 that work. 00-46 and 54-58 don't.
If I retry the same thing 10 minutes later, it's the same behavior (the same 3 functions that get executed).
Steps to Reproduce
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask.Client;
public static partial class TimedTriggerStartPartitionImportFunctions
{
[Function("Easee-StartImportPartition0")]
public static Task StartImportPartition0(
[TimerTrigger("0 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition0));
return StartImportPartition(
0,
starter,
logger);
}
[Function("Easee-StartImportPartition2")]
public static Task StartImportPartition2(
[TimerTrigger("2 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition2));
return StartImportPartition(
2,
starter,
logger);
}
[Function("Easee-StartImportPartition4")]
public static Task StartImportPartition4(
[TimerTrigger("4 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition4));
return StartImportPartition(
4,
starter,
logger);
}
[Function("Easee-StartImportPartition6")]
public static Task StartImportPartition6(
[TimerTrigger("6 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition6));
return StartImportPartition(
6,
starter,
logger);
}
[Function("Easee-StartImportPartition8")]
public static Task StartImportPartition8(
[TimerTrigger("8 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition8));
return StartImportPartition(
8,
starter,
logger);
}
[Function("Easee-StartImportPartition10")]
public static Task StartImportPartition10(
[TimerTrigger("10 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition10));
return StartImportPartition(
10,
starter,
logger);
}
[Function("Easee-StartImportPartition12")]
public static Task StartImportPartition12(
[TimerTrigger("12 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition12));
return StartImportPartition(
12,
starter,
logger);
}
[Function("Easee-StartImportPartition14")]
public static Task StartImportPartition14(
[TimerTrigger("14 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition14));
return StartImportPartition(
14,
starter,
logger);
}
[Function("Easee-StartImportPartition16")]
public static Task StartImportPartition16(
[TimerTrigger("16 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition16));
return StartImportPartition(
16,
starter,
logger);
}
[Function("Easee-StartImportPartition18")]
public static Task StartImportPartition18(
[TimerTrigger("18 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition18));
return StartImportPartition(
18,
starter,
logger);
}
[Function("Easee-StartImportPartition20")]
public static Task StartImportPartition20(
[TimerTrigger("20 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition20));
return StartImportPartition(
20,
starter,
logger);
}
[Function("Easee-StartImportPartition22")]
public static Task StartImportPartition22(
[TimerTrigger("22 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition22));
return StartImportPartition(
22,
starter,
logger);
}
[Function("Easee-StartImportPartition24")]
public static Task StartImportPartition24(
[TimerTrigger("24 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition24));
return StartImportPartition(
24,
starter,
logger);
}
[Function("Easee-StartImportPartition26")]
public static Task StartImportPartition26(
[TimerTrigger("26 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition26));
return StartImportPartition(
26,
starter,
logger);
}
[Function("Easee-StartImportPartition28")]
public static Task StartImportPartition28(
[TimerTrigger("28 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition28));
return StartImportPartition(
28,
starter,
logger);
}
[Function("Easee-StartImportPartition30")]
public static Task StartImportPartition30(
[TimerTrigger("30 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition30));
return StartImportPartition(
30,
starter,
logger);
}
[Function("Easee-StartImportPartition32")]
public static Task StartImportPartition32(
[TimerTrigger("32 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition32));
return StartImportPartition(
32,
starter,
logger);
}
[Function("Easee-StartImportPartition34")]
public static Task StartImportPartition34(
[TimerTrigger("34 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition34));
return StartImportPartition(
34,
starter,
logger);
}
[Function("Easee-StartImportPartition36")]
public static Task StartImportPartition36(
[TimerTrigger("36 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition36));
return StartImportPartition(
36,
starter,
logger);
}
[Function("Easee-StartImportPartition38")]
public static Task StartImportPartition38(
[TimerTrigger("38 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition38));
return StartImportPartition(
38,
starter,
logger);
}
[Function("Easee-StartImportPartition40")]
public static Task StartImportPartition40(
[TimerTrigger("40 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition40));
return StartImportPartition(
40,
starter,
logger);
}
[Function("Easee-StartImportPartition42")]
public static Task StartImportPartition42(
[TimerTrigger("42 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition42));
return StartImportPartition(
42,
starter,
logger);
}
[Function("Easee-StartImportPartition44")]
public static Task StartImportPartition44(
[TimerTrigger("44 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition44));
return StartImportPartition(
44,
starter,
logger);
}
[Function("Easee-StartImportPartition46")]
public static Task StartImportPartition46(
[TimerTrigger("46 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition46));
return StartImportPartition(
46,
starter,
logger);
}
[Function("Easee-StartImportPartition48")]
public static Task StartImportPartition48(
[TimerTrigger("48 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition48));
return StartImportPartition(
48,
starter,
logger);
}
[Function("Easee-StartImportPartition50")]
public static Task StartImportPartition50(
[TimerTrigger("50 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition50));
return StartImportPartition(
50,
starter,
logger);
}
[Function("Easee-StartImportPartition52")]
public static Task StartImportPartition52(
[TimerTrigger("52 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition52));
return StartImportPartition(
52,
starter,
logger);
}
[Function("Easee-StartImportPartition54")]
public static Task StartImportPartition54(
[TimerTrigger("54 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition54));
return StartImportPartition(
54,
starter,
logger);
}
[Function("Easee-StartImportPartition56")]
public static Task StartImportPartition56(
[TimerTrigger("56 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition56));
return StartImportPartition(
56,
starter,
logger);
}
[Function("Easee-StartImportPartition58")]
public static Task StartImportPartition58(
[TimerTrigger("58 * * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition58));
return StartImportPartition(
58,
starter,
logger);
}
}
#>
using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask.Client;
public static partial class TimedTriggerStartPartitionImportFunctions
{
<#
for(var i = 0; i < PartitionSize; i+=2)
{
#>
[Function("Easee-StartImportPartition<#= i #>")]
public static Task StartImportPartition<#= i #>(
[TimerTrigger("<#= CreateCronExpressionForPartition(i) #>", RunOnStartup = true)] TimerInfo timer,
[DurableClient] DurableTaskClient starter,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(
nameof(StartImportPartition<#= i #>));
return StartImportPartition(
<#= i #>,
starter,
logger);
}
<#
}
#>
}
Alongside with that, use the following c# code:
public static partial class TimedTriggerStartPartitionImportFunctions
{
private static Task StartImportPartition(
int partition,
DurableTaskClient starter,
ILogger log)
{
var instanceId = FormattableString.Invariant($"Part{partition}");
return DurableOrchestrationFunctionStarter.StartNewIfNotStartedAsync(
functionName: OrchestrationFunction.FunctionName,
argument: partition,
instanceId: instanceId,
starter,
log);
}
}
public class OrchestrationFunction
{
public const string FunctionName = nameof(OrchestrationFunction);
[Function(FunctionName)]
public Task OrchestrateImportPartition(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
var log = context.CreateReplaySafeLogger(FunctionName);
var partitionNumber = context.GetInput<int>();
log.LogTrace("done partition {0}", partitionNumber);
}
}
public static class DurableOrchestrationFunctionStarter
{
public static async Task StartNewIfNotStartedAsync<TArg>(
string functionName,
TArg argument,
string instanceId,
DurableTaskClient starter,
ILogger log)
{
var status = await starter
.GetInstanceAsync(instanceId)
.ConfigureAwait(false);
if (status != null
&& DurableFunctionIsRunningDeterminer.IsRunning(status.RuntimeStatus))
{
log.LogError(
"Durable function '{0}' of partition '{1}' is still running. Status: {2}. Waiting for next cycle.",
functionName,
instanceId,
status.RuntimeStatus);
}
else
{
var assignedInstanceId = await starter.ScheduleNewOrchestrationInstanceAsync(
functionName,
argument,
new StartOrchestrationOptions
{
InstanceId = instanceId,
});
if (assignedInstanceId != instanceId)
{
log.LogCritical(
$"When starting the function '{0}' system overrode the manually assigned instance id '{1}' with '{2}'. Functions could be executed in parallel.",
functionName,
instanceId,
assignedInstanceId);
}
else
{
log.LogTrace(
"Started {0} with instance id '{1}'",
functionName,
instanceId);
}
}
}
}
Debug this locally.
Other Things Tried
From what I read, it's possible that similar errors occur depending on the timezone setting. I have tried setting the timezone to
"WEBSITE_TIME_ZONE": "UTC"
and to"WEBSITE_TIME_ZONE": "SE Asia Standard Time"
to no avail in:
- host.json
- local.settings.json (root level and under
"Values":
- appsettings.json