// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using Microsoft.Agents.AI.Purview.Models.Jobs;
using Microsoft.Extensions.Logging;
namespace Microsoft.Agents.AI.Purview;
///
/// Service that runs jobs in background threads.
///
internal sealed class BackgroundJobRunner : IBackgroundJobRunner
{
private readonly IChannelHandler _channelHandler;
private readonly IPurviewClient _purviewClient;
private readonly ILogger _logger;
///
/// Initializes a new instance of the class.
///
/// The channel handler used to manage job channels.
/// The Purview client used to send requests to Purview.
/// The logger used to log information about background jobs.
/// The settings used to configure Purview client behavior.
public BackgroundJobRunner(IChannelHandler channelHandler, IPurviewClient purviewClient, ILogger logger, PurviewSettings purviewSettings)
{
this._channelHandler = channelHandler;
this._purviewClient = purviewClient;
this._logger = logger;
for (int i = 0; i < purviewSettings.MaxConcurrentJobConsumers; i++)
{
this._channelHandler.AddRunner(async (Channel channel) =>
{
await foreach (BackgroundJobBase job in channel.Reader.ReadAllAsync().ConfigureAwait(false))
{
try
{
await this.RunJobAsync(job).ConfigureAwait(false);
}
catch (Exception e) when (e is not OperationCanceledException and not SystemException)
{
if (this._logger.IsEnabled(LogLevel.Error))
{
this._logger.LogError(e, "Error running background job {BackgroundJobError}.", e.Message);
}
}
}
});
}
}
///
/// Runs a job.
///
/// The job to run.
/// A task representing the job.
private async Task RunJobAsync(BackgroundJobBase job)
{
switch (job)
{
case ProcessContentJob processContentJob:
_ = await this._purviewClient.ProcessContentAsync(processContentJob.Request, CancellationToken.None).ConfigureAwait(false);
break;
case ContentActivityJob contentActivityJob:
_ = await this._purviewClient.SendContentActivitiesAsync(contentActivityJob.Request, CancellationToken.None).ConfigureAwait(false);
break;
}
}
///
/// Shutdown the job runners.
///
public async Task ShutdownAsync()
{
await this._channelHandler.StopAndWaitForCompletionAsync().ConfigureAwait(false);
}
}