Как дождаться, пока другая служба завершит задачу в фоновом режиме без ожидания?

#c# #asp.net-core #entity-framework-core #asp.net-core-webapi #autodesk-forge

#c# #asp.net-core #entity-framework-core #asp.net-core-webapi #autodesk-forge

Вопрос:

Я создаю ASP.NET Core WebAPI, который использует Autodesk Model Derivative API для преобразования файла Revit в другой формат файла. После того, как я загрузил файл, Autodesk API начинает работать в фоновом режиме, и для завершения его работы может потребоваться несколько минут.

Я хочу отслеживать состояние API Autodesk, знать, завершено ли преобразование, и уведомлять пользователя. Я ищу лучший способ отслеживать статус задания без «ожидания» и позволять запросу зависать в течение нескольких минут.

Я попытался просто запустить задачу асинхронно, не ожидая результата. Это работало до того момента, когда я захотел обновить значение в контексте моей базы данных, потому что оно было удалено из-за завершения запроса.

Я также исследовал несколько вариантов реализации фоновых служб, но не нашел четкого способа сделать это.

 public async Task<ActionResult<Response<JobResponse>>> UploadFile(string bucketKey, IFormFile file)
{
    // ....
    // File has been uploaded 
    Response<JobResponse> response
        = await NetworkManager.PostAsync<JobResponse>(URI.Job.Url, JsonConvert.SerializeObject(jobData));

    // The job has been created in the Autodesk API, so I create a record in my own database
    var job = new Job(urn, file.FileName);
    context.Jobs.Add(job);
    await context.SaveChangesAsync();

    // This method is what I want to do in the background 
    MonitorStatus(job);

    return Respond(response);
}

private async Task MonitorStatus(Job job)
{
    bool isDone = false;

    while (!isDone)
    {
        isDone = await IsDone(job.Urn);

        if (!isDone)
            await Task.Delay(10000);
    }

    string guid = await new JobRepository(job).GetGuid();

    // The line underneath throws an error because the context has been disposed
    (await context.Jobs.FindAsync(job.Id)).Finish(guid);
    await context.SaveChangesAsync();

    // ...
    // Notify the user
}
  

Комментарии:

1. Предлагает ли Autodesk API веб-ссылки ?

2.ДА: forge.autodesk.com/en/docs/webhooks/v1/reference/http.

3. Блестяще! forge.autodesk.com/en/docs/webhooks/v1/tutorials/… Собираюсь разобраться в этом. Спасибо!

4. Вероятно, вы также захотите заглянуть в SignalR, чтобы вы могли уведомлять пользователя о попадании в ваш webhook.

5. Выглядит хорошо, я обязательно это использую. В целях разработки я настроил Slack webhook, чтобы я мог получать сообщения внутри, но SignalR удовлетворит мои потребности в выпуске 🙂

Ответ №1:

Перевод файлов в Model Derivative API сводится к двум основным конечным точкам:

  • POST job для запуска перевода и
  • ПОЛУЧИТЬ манифест для получения манифеста перевода (вкл. его состояние, пока перевод все еще выполняется)

Если вы сами выполняете HTTP-запросы, вы можете просто опрашивать манифест, пока не увидите, что перевод завершен.

Если вы используете Forge .NET SDK, вы можете запустить перевод с помощью метода Translate и опросить результаты с помощью метода GetManifest.

Комментарии:

1. Я уже реализовал POST job и GET manifest. bool isDone = false; while (!isDone) { isDone = await IsDone(job.Urn); if (!isDone) await Task.Delay(10000); } Эта часть опрашивает манифест, как вы говорите. Но мой вопрос в том, как запустить это в фоновом режиме, чтобы пользователь мог вернуться к своим делам и получить уведомление, когда манифест будет выполнен.

2. Глядя на ваш код, похоже, что вы отвечаете на запрос вашего пользователя сразу после запуска мониторинга состояния. Это хорошо. Если вы хотите предоставить своим пользователям какой-либо механизм обратной связи, вы могли бы попросить их предоставить необязательный URL («webhook»), который вы могли бы вызвать, когда перевод будет завершен.

3. Что касается проблемы с context удалением в MonitorStatus методе, это ASP.NET Основной вопрос, на который кто-то другой, вероятно, сможет ответить лучше меня, но я бы предположил, что вам действительно не нужно сохранять статус перевода, потому что эта информация уже сохранена в манифесте. Надеюсь, это поможет, ура!

4. Это хороший момент. Я могу предотвратить необходимость использования контекста в этот момент. Но сейчас я работаю над внедрением webhook, так что это избавит меня от необходимости самостоятельно отслеживать статус. Спасибо за ваши предложения!

Ответ №2:

В итоге я использовал веб-справочник Autodesk Forge, который вызывает конечную точку, уведомляющую пользователя о завершении преобразования. Этот веб-справочник содержит тело с информацией о том, какое задание было завершено, поэтому я могу соответствующим образом обновить базу данных.

Этот веб-крючок устраняет необходимость в моем MonitorStatus(job) методе.

https://forge.autodesk.com/en/docs/webhooks/v1/tutorials/create-a-hook-model-derivative/