Comment mettre en queue des tâches en arrière-plan dans l’API Web ASP.NET

J’ai un site Web conçu pour traiter les rapports en queue. Les étapes à suivre par l’application sont les suivantes:

  • Recevoir du contenu
  • Mappez le contenu sur un object et placez-le dans la queue
  • Interroger les éléments en attente dans la queue
  • Traiter les éléments en queue un à la fois

Je pensais utiliser Entity Framework pour créer une firebase database d’éléments en queue, tels que:

public class EFBatchItem { [Key] public ssortingng BatchId { get; set; } public DateTime DateCreated { get; set; } public DateTime DateCompleted { get; set; } public ssortingng BatchItem { get; set; } public BatchStatus Status { get; set; } } 

Ma question – Existe-t-il un moyen plus efficace, à l’aide de NServiceBus, BlockingCollection ou ConcurrentQeueue, que d’interroger en permanence la firebase database et d’extraire les éléments en attente un par un? Je n’ai pas utilisé les files d’attente avant.

Une solution consiste à créer une queue de tâches et à traiter, sur un thread séparé, toutes les tâches en attente. Quelque peu similaire à La manière la plus efficace de traiter une queue avec des threads, mais je veux m’assurer que mon itinéraire est le plus efficace.

EDIT: Une grande question que j’ai ici est la meilleure façon d’afficher les progrès à l’utilisateur. Une fois que l’utilisateur a soumis le contenu, il est redirigé vers une nouvelle page et peut afficher le statut à l’aide de l’identificateur de lot. MSMQ ou NServiceBus sont-ils nécessaires pour informer l’utilisateur? Cela semble être une variante du paradigme Demande / Reconnaissance / Pousser?

IMHO, votre application API Web ASP.NET ne doit pas exécuter ces tâches en arrière-plan par elle-même. Il ne devrait être responsable que de recevoir la demande, de la coller dans la queue (comme vous l’avez indiqué) et de renvoyer la réponse indiquant le succès ou l’échec du message reçu. Vous pouvez utiliser divers systèmes de messagerie tels que RabbitMQ pour cette approche.

En ce qui concerne la notification, vous avez quelques options. Vous pouvez avoir un noeud final sur lequel le client peut vérifier si le traitement est terminé ou non. Vous pouvez également fournir un sharepoint terminaison d’API de diffusion auquel votre client peut s’abonner. De cette façon, le client n’a pas à interroger le serveur; le serveur peut notifier les clients connectés. L’API Web ASP.NET est un excellent moyen de le faire. Le blog suivant explique comment:

  • Notifications push natives HTML5 avec API Web ASP.NET et Knockout.js

Vous pouvez également envisager SignalR pour ce type de notifications serveur à client.

La raison pour laquelle les tâches en arrière-plan sont difficiles pour l’application API Web ASP.NET est qu’il vous incombe de maintenir l’AppDomain en vie. C’est un problème surtout lorsque vous hébergez sous IIS. Les articles de blog suivants expliquent vraiment bien ce que je veux dire:

  • Retour anticipé à partir de demandes ASP.NET
  • Les dangers de la mise en œuvre de tâches d’arrière-plan récurrentes dans ASP.NET

C’est un paquet NuGet appelé HangFire – https://github.com/HangfireIO/Hangfire . Les tâches persistent même au-delà du recyclage de l’apppool.

J’aime la solution de @ Todd. Juste pour être complet, mais il y a une autre option qui n’a pas encore été mentionnée:

 HostingEnvironment.QueueBackgroundWorkItem(cancellationToken => { // Some long-running job }); 

Remarque:

“Lorsque ASP.NET doit recycler, il avertit le travail d’arrière-plan (en définissant un CancellationToken) et attend ensuite 30 secondes pour que le travail soit terminé. Si le travail d’arrière-plan ne s’achève pas dans ce laps de temps, le travail disparaîtra mystérieusement. ”

Et évitez d’utiliser des méthodes de service avec un DbContext injecté ici car cela ne fonctionnera pas.

Sources: MariusSchulz et StephenCleary

Si vous utilisez Asp.net Core, vous pouvez utiliser IHostService .