Синглтонские зависимости в канале фоновой задачи / размещенная фоновая службаC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Синглтонские зависимости в канале фоновой задачи / размещенная фоновая служба

Сообщение Anonymous »

Я работаю над созданием некоторых конечных точек Webapi .net/C# 8.0. Будет более 100 конечных точек в 40-50 репозиториях, которые являются частью той же экосистемы платформы; На данный момент это не вариант для реструктуризации коллекции. Существует также ряд задач, которые необходимо обработать асинхронно, не ожидая их выполнения перед отправкой ответа API. Чтобы сделать это, я настраиваю фоновый канал задач и размещенную фоновую службу. Цель состоит в том, чтобы установить его общим способом, где я могу создавать экземпляр службы и канала для каждого репо отдельно, функции Enqueue, которые содержат все фоновые задачи, и обрабатывать их как услуга. />

Код: Выделить всё

namespace My.Namespace.BackgroundTaskQueue
{
public interface IBackgroundTaskQueue
{
ValueTask QueueBackgroundWorkItemAsync(Func workItem);
ValueTask DequeueAsync(CancellationToken cancellationToken);
}
}
backgroundtaskqueue.cs

Код: Выделить всё

namespace My.Namespace.BackgroundTaskQueue
{
using System.Threading.Channels;

public class BackgroundTaskQueue : IBackgroundTaskQueue
{
private readonly Channel _queue;

public BackgroundTaskQueue(int capacity) {
var options = new BoundedChannelOptions(capacity) {
FullMode = BoundedChannelFullMode.Wait
};
_queue = Channel.CreateBounded(options);
}

public async ValueTask QueueBackgroundWorkItemAsync(Func workItem) {
if (workItem == null)
{
throw new ArgumentNullException(nameof(workItem));
}

await _queue.Writer.WriteAsync(workItem);
}

public async ValueTask DequeueAsync(CancellationToken cancellationToken) {
var workItem = await _queue.Reader.ReadAsync(cancellationToken);

return workItem;
}
}
}
backgroundtaskqueuehostedservice.cs
namespace My.Namespace.BackgroundTaskQueue
{
using Microsoft.Extensions.Hosting;

public class BackgroundTaskQueueHostedService : BackgroundService
{
public IBackgroundTaskQueue TaskQueue { get; }

public BackgroundTaskQueueHostedService(IBackgroundTaskQueue taskQueue)
{
TaskQueue = taskQueue;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await BackgroundProcessing(stoppingToken);
}

private async Task BackgroundProcessing(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var workItem =
await TaskQueue.DequeueAsync(stoppingToken);

try
{
await workItem(stoppingToken);
}
catch (Exception ex)
{
// Error Handling
}
}
}

public override async Task StopAsync(CancellationToken stoppingToken)
{
await base.StopAsync(stoppingToken);
}
}
}
< /code>
План состоит в том, чтобы затем создать экземпляр этого класса /очередь в startup.cs, и мои контроллеры включают асинхронную функцию, которая содержит все задачи, которые я хочу обрабатывать в фоновом режиме. Проблема заключается в том, что эти фоновые задачи полагаются на различные зависимости от обслуживания в одиночном возрасте, которые вводят в контроллеры. Но я не хочу вводить все синглтонские зависимости в фоновый сервис, поскольку цель состоит в том, чтобы иметь его достаточно общего для использования с любым из 40-50 репо, без создания специализированных реализаций класса фоновых услуг для каждого.namespace My.Repo.Namespace.BL.ControllerServices.Custom
{
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using My.Namespace.BackgroundTaskQueue;
using My.Repo.Other.Namespace.Services;

public CustomControllerService : ICustomControllerService
{
private readonly IBackgroundTaskQueue _backgroundTaskQueue;
private readonly CancellationToken _ct;
private readonly IService1 _service1;
private readonly IService2 _service2;

public CustomControllerService(IBackgroundTaskQueue backgroundTaskQueue,
IHostApplicationLifetime applicationLifetime,
IService1 service1,
IService2 service2) {
_backgroundTaskQueue = backgroundTaskQueue;
_ct = applicationLifetime.ApplicationStopping;
_service1 = service1;
_service2 = service2;
}

#region [Http Request Execution]

public async Task ProcessRequest(HttpRequest httpRequest) {
ApiRequestContext apiRequestContext = new ApiRequestContext();
CustomRequestBody customRequestBody;

try {
// Ingest the event and deserialize it to a data object dedicated to this endpoint
customRequestBody = await DeserializeRequestBody(httpRequest, apiRequestContext);
if (apiRequestContext?.ApiResponse?.HttpStatusCode == 200) {
// Deserialization successful, process data
await ProcessRequestData(customRequestBody, apiRequestContext);
apiRequestContext.ApiResponse.Content = CreateResponseBody(apiRequestContext);
}
} catch (Exception ex){
} finally {
}

// Return the current ApiResponse object contained in the ApiRequestContext
return apiRequestContext.ApiResponse;
}

#endregion

#region [Private Methods]

private async Task DeserializeRequestBody(HttpRequest httpRequest, ApiRequestContext apiRequestContext) {
// Logic to deserialize request body into my custom object
return new CustomRequestBody;
}

private CustomResponseBody CreateResponseBody(ApiRequestContext apiRequestContext) {
// Some logic to build API response
return new CustomResponseBody;
}

private async Task ProcessRequestData(CustomRequestBody customRequestBody, ApiRequestContext apiRequestContext) {
try {
await ProcessAwaitedTasks(customRequestBody, apiRequestContext);
await _backgroundTaskQueue.QueueBackgroundWorkItemAsync(
_ct => ProcessUnawaitedTasks(customRequestBody, _ct)
);
} catch (Exception ex) {
} finally {

}
}

private async Task ProcessAwaitedTasks(CustomRequestBody customRequestBody, ApiRequestContext apiRequestContext) {
try {
// Some synchronoous sequence of async / await Tasks
} catch (Exception e) {
} finally {
}
}

private async ValueTask ProcessUnawaitedTasks(CustomRequestBody customRequestBody, CancellationToken ct) {
try {
// Some background async Tasks that I need executed, but not awaited for the api response
_ = _service1.Function1(customRequestBody);
_ = _service2.Function2(customRequestBody);
} catch (Exception e) {
} finally {
}
}

#endregion

}
}
< /code>
Служба контроллера (упрощенная для краткости) сделает некоторые вещи с входящим запросом, а затем выполняет обработку ожидаемых задач, а затем внедрение асинхронной функции, которая содержит некоторые неотъемлемые задачи в фоновую каркасную кожу (канал), прежде чем немедленно возвращать ответ API. Но эти неприемлемые задачи полагаются на зависимости в службе контроллера, таких как iService1 и iService2. Я не хочу напрямую вводить эти зависимости в фоновый класс службы. В этой ситуации я видел обширную документацию о службах обселений, но я ничего не могу найти в управлении синглтонами. Спасибо!

Подробнее здесь: https://stackoverflow.com/questions/795 ... nd-service
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»