// 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); } }