Вызов функции Azure Durable без вызова HttpTrigger (автозапуск)
Я смотрю на этот пример для запуска долговременной функции Activity после установленного времени ожидания.
Это позволит моей функции выполнить обработку данных, а затем подождать ровно 1 час, прежде чем попытаться загрузить снова. Это будет продолжаться вечно. Отлично.
Однако при публикации функции в Azure мне не нужно вручную вызывать / запускать функцию через связанный HTTP-триггер. Я просто хочу, чтобы долговечная функция автоматически запускалась и начинала обработку.
Это возможно? Если нет, то что такое предложенное решение?
Спасибо!
3 ответа
Как обсуждалось в комментариях, один из способов сделать это - добавить новую задачу в ваш конвейер выпуска.
Вот что я понял о вашей настройке из вашего вопроса:
[FunctionName("ClientFunction")]
public static async Task<HttpResponseMessage> OnHttpTriggerAsync([HttpTrigger(AuthorizationLevel.Anonymous, "post")]
HttpRequestMessage request, [OrchestrationClient] DurableOrchestrationClient starter, ILogger logger)
{
// Triggers the orchestrator.
string instanceId = await starter.StartNewAsync("OrchestratorFunction", null);
return new HttpResponseMessage(HttpStatusCode.OK);
}
[FunctionName("OrchestratorFunction")]
public static async Task DoOrchestrationThingsAsync([OrchestrationTrigger] DurableOrchestrationContext context, ILogger logger)
{
DateTime deadline = context.CurrentUtcDateTime.Add(TimeSpan.FromHours(1));
await context.CreateTimer(deadline, CancellationToken.None);
// Triggers some yout activity.
await context.CallActivityAsync("ActivityFunction", null);
}
[FunctionName("ActivityFunction")]
public static Task DoAnAwesomeActivity([ActivityTrigger] DurableActivityContext context)
{
}
Теперь каждый раз, когда вы развертываете новую версию приложения-функции, вам необходимо запустить оркестратор. Однако я не думаю, что это может быть начато само по себе.
Я предлагаю иметь простой скрипт bash (используя curl
или что-то еще), что бы назвать ClientFunction
по соответствующему URL.
Вдобавок ко всему, одна из приятных особенностей этого решения заключается в том, что вы можете сделать развертывание неудачным, если функция Azure не отвечает.
Кажется, это тоже работает.
[FunctionName("AutoStart")]
public static async Task Run([TimerTrigger("*/5 * * * * *", RunOnStartup = true, UseMonitor = false)]TimerInfo myStartTimer,
[DurableClient] IDurableClient orchestrationClient, ILogger log)
{
string instanceId = await orchestrationClient.StartNewAsync("Start_Orchestrator", null);
}
Я не знаю, есть ли в этом скрытые проблемы, но сейчас я экспериментирую с запуском при запуске, а также один раз в день в полночь (или по любому другому расписанию, которое вы хотите). Что
private const string MyOrchestrationName = "MyOrchestration";
[FunctionName("MyOrchestration_Trigger")]
public async Task MyOrchestrationr_Trigger(
[TimerTrigger("0 0 0 * * *", RunOnStartup = true)] TimerInfo timer,
[DurableClient] IDurableOrchestrationClient starter,
ILogger log,
CancellationToken cancellationToken)
{
// Get all the instances currently running that have a status of Pending, Running, ContinuedAsNew
var instances = await starter.ListInstancesAsync(new OrchestrationStatusQueryCondition()
{
ShowInput = false,
RuntimeStatus = new List<OrchestrationRuntimeStatus>() { OrchestrationRuntimeStatus.Suspended, OrchestrationRuntimeStatus.Pending, OrchestrationRuntimeStatus.Running, OrchestrationRuntimeStatus.ContinuedAsNew }
}, cancellationToken);
// Find any instances of the current orchestration that are running.
var myInstances = instances.DurableOrchestrationState.Where(inst => inst.Name == MyOrchestrationName);
List<Task> terminateTasks = new List<Task>();
foreach (var instance in myInstances )
{
// Delete any instances that are currently running.
terminateTasks.Add(starter.TerminateAsync(instance.InstanceId, $"Restarting eternal orchestration"));
}
await Task.WhenAll(terminateTasks);
// Start the new task now that other instances have been terminated.
string instanceId = await starter.StartNewAsync(MyOrchestrationName, null);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
}
Думаю, по крайней мере для моих целей это будет безопасно. Любые действия, которые выполняются, когда вы завершаете, все равно будут выполняться до завершения (это то, что я хочу в моем случае), поэтому вы просто убьете его и перезапустите по расписанию.