Вызов функции Azure Durable без вызова HttpTrigger (автозапуск)

Я смотрю на этот пример для запуска долговременной функции Activity после установленного времени ожидания.

https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-eternal-orchestrations

Это позволит моей функции выполнить обработку данных, а затем подождать ровно 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}'.");
}

Думаю, по крайней мере для моих целей это будет безопасно. Любые действия, которые выполняются, когда вы завершаете, все равно будут выполняться до завершения (это то, что я хочу в моем случае), поэтому вы просто убьете его и перезапустите по расписанию.

Другие вопросы по тегам