From c06f06c6ce6dd9a28dd0d44f1776f61aa09fe1b9 Mon Sep 17 00:00:00 2001 From: Nickk888 Date: Sat, 10 Oct 2026 01:35:56 +0200 Subject: [PATCH] Jobs and services --- Bodies/NewPaperlessDocumentBody.cs | 2 - Jobs/CheckDocumentsToProcessJob.cs | 40 +++++++++++++++ Models/PaperlessDocument.cs | 5 ++ Program.cs | 5 ++ Services/DocumentProcessingService.cs | 74 +++++++++++++++++++++++++++ Services/LLMAgentService.cs | 8 +++ appsettings.Template.json | 13 +++-- 7 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 Jobs/CheckDocumentsToProcessJob.cs create mode 100644 Services/DocumentProcessingService.cs create mode 100644 Services/LLMAgentService.cs diff --git a/Bodies/NewPaperlessDocumentBody.cs b/Bodies/NewPaperlessDocumentBody.cs index f9ee651..e6f5b2f 100644 --- a/Bodies/NewPaperlessDocumentBody.cs +++ b/Bodies/NewPaperlessDocumentBody.cs @@ -1,11 +1,9 @@ -using System; using Newtonsoft.Json; namespace PaperlessAI.Bodies; public class NewPaperlessDocumentBody { - [JsonProperty("document_id")] public long DocumentId { get; set; } public override string ToString() diff --git a/Jobs/CheckDocumentsToProcessJob.cs b/Jobs/CheckDocumentsToProcessJob.cs new file mode 100644 index 0000000..e001954 --- /dev/null +++ b/Jobs/CheckDocumentsToProcessJob.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Frozen; +using Microsoft.EntityFrameworkCore; +using PaperlessAI.Context; +using PaperlessAI.Repositories; +using PaperlessAI.Services; + +namespace PaperlessAI.Jobs; + +public class CheckDocumentsToProcessJob(ILogger logger, IServiceScopeFactory scopeFactory) : BackgroundService +{ + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + using var timer = new PeriodicTimer(TimeSpan.FromSeconds(5)); + + do + { + await DoWork(stoppingToken); + } + while(await timer.WaitForNextTickAsync(stoppingToken)); + } + + private async Task DoWork(CancellationToken stoppingToken) + { + logger.LogInformation("Working"); + + await using var scope = scopeFactory.CreateAsyncScope(); + var context = scope.ServiceProvider.GetRequiredService(); + var documentProcessingService = scope.ServiceProvider.GetRequiredService(); + + var docsToProcess = await context + .PaperlessDocuments + .Where(x => x.DocumentState == Enums.EOperationState.Created) + .OrderBy(x => x.CreatedAt) + .ToListAsync(); + + documentProcessingService.Enqueue(docsToProcess); + documentProcessingService.Process(); + } +} diff --git a/Models/PaperlessDocument.cs b/Models/PaperlessDocument.cs index 84b5d82..70713ec 100644 --- a/Models/PaperlessDocument.cs +++ b/Models/PaperlessDocument.cs @@ -21,4 +21,9 @@ public class PaperlessDocument return paperlessDocument; } + public override string ToString() + { + return $"Id: {Id}, DocumentId: {DocumentId}"; + } + } diff --git a/Program.cs b/Program.cs index ebbbdd1..d3abc6c 100644 --- a/Program.cs +++ b/Program.cs @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using PaperlessAI.Context; +using PaperlessAI.Jobs; using PaperlessAI.Repositories; using PaperlessAI.Services; using Serilog; @@ -8,6 +9,7 @@ var builder = WebApplication.CreateBuilder(args); // Services builder.Services.AddScoped(); +builder.Services.AddSingleton(); // Repositories builder.Services.AddScoped(); @@ -39,6 +41,9 @@ Log.Logger = new LoggerConfiguration() builder.Host.UseSerilog(); +// Jobs +builder.Services.AddHostedService(); + // App var app = builder.Build(); diff --git a/Services/DocumentProcessingService.cs b/Services/DocumentProcessingService.cs new file mode 100644 index 0000000..f17177d --- /dev/null +++ b/Services/DocumentProcessingService.cs @@ -0,0 +1,74 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using PaperlessAI.Models; + +namespace PaperlessAI.Services; + +public class DocumentProcessingService(ILogger logger) +{ + private Queue paperlessDocumentsQueue = new Queue(); + private bool isWorking = false; + + public void Enqueue(List paperlessDocuments) + { + if(paperlessDocumentsQueue.Count != 0) + return; + + foreach(var doc in paperlessDocuments) + { + Enqueue(doc); + } + } + + public void Enqueue(PaperlessDocument paperlessDocument) + { + if(paperlessDocumentsQueue.Contains(paperlessDocument, new PaperlessDocumentSameDocument())) + return; + + paperlessDocumentsQueue.Enqueue(paperlessDocument); + + logger.LogInformation($"Enqueued document: {paperlessDocument}"); + } + + public void Process() + { + if(isWorking) + return; + + if(paperlessDocumentsQueue.Count == 0) + return; + + if(paperlessDocumentsQueue.TryDequeue(out PaperlessDocument? docToProcess)) + { + logger.LogInformation($"Dequeued: {docToProcess}"); + ProcessDocument(docToProcess); + } + } + + private void ProcessDocument(PaperlessDocument docToProcess) + { + logger.LogInformation($"Processing: {docToProcess}"); + isWorking = true; + + isWorking = false; + } +} + +class PaperlessDocumentSameDocument : EqualityComparer +{ + public override bool Equals(PaperlessDocument? x, PaperlessDocument? y) + { + if (x == null && y == null) + return true; + else if (x == null || y == null) + return false; + + return x.Id == y.Id || x.DocumentId == y.DocumentId; + } + + public override int GetHashCode([DisallowNull] PaperlessDocument obj) + { + var hcode = obj.Id + obj.DocumentId; + return hcode.GetHashCode(); + } +} diff --git a/Services/LLMAgentService.cs b/Services/LLMAgentService.cs new file mode 100644 index 0000000..0d2f825 --- /dev/null +++ b/Services/LLMAgentService.cs @@ -0,0 +1,8 @@ +using System; + +namespace PaperlessAI.Services; + +public class LLMAgentService +{ + +} diff --git a/appsettings.Template.json b/appsettings.Template.json index eb10998..c13832a 100644 --- a/appsettings.Template.json +++ b/appsettings.Template.json @@ -8,10 +8,17 @@ } }, "Application": { - "Version": "" + "Version": "" }, - "Settings": { - "MaxMediaDuration": 7200 + "LlmAgent": { + "Url": "", + "Token": "", + "Model": "", + "McpServer": "", + "ContextLength": "", + "MaxOutputTokens": "", + "Temperature": "", + "Reasoning": "" }, "ConnectionStrings": { "MariaDbConnectionString": "server=;user id=;password=;database="