Private
Public Access
1
0
Files
Purrse/src/Purrse.Api/Controllers/AiCategorizationController.cs
T
Catherine Renelle 333b21224d Run AI classification in background with SignalR notifications
Move the classify-uncategorized endpoint from synchronous to async.
The controller now queues a ClassificationJob to an unbounded channel
and returns 202 Accepted. A new BackgroundService processes jobs and
pushes results (or errors) to the user via SignalR. The frontend
listens for the AiClassificationComplete event and surfaces it in the
notification system.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 23:53:14 -05:00

46 lines
1.8 KiB
C#

using System.Threading.Channels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Purrse.Api.Services;
using Purrse.Core.DTOs;
using Purrse.Core.Interfaces.Services;
using System.Security.Claims;
namespace Purrse.Api.Controllers;
[Authorize]
[ApiController]
[Route("api/ai-categorization")]
public class AiCategorizationController : ControllerBase
{
private readonly IAiCategorizationService _aiService;
private readonly Channel<ClassificationJob> _classificationChannel;
private Guid UserId => Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
public AiCategorizationController(IAiCategorizationService aiService, Channel<ClassificationJob> classificationChannel)
{
_aiService = aiService;
_classificationChannel = classificationChannel;
}
[HttpGet("settings")]
public async Task<ActionResult<AiCategorizationSettingsResponse>> GetSettings()
=> Ok(await _aiService.GetSettingsAsync(UserId));
[HttpPut("settings")]
public async Task<ActionResult<AiCategorizationSettingsResponse>> UpdateSettings(UpdateAiCategorizationSettingsRequest request)
=> Ok(await _aiService.UpdateSettingsAsync(UserId, request));
[HttpPost("test-connection")]
public async Task<ActionResult<OllamaConnectionTestResponse>> TestConnection()
=> Ok(await _aiService.TestConnectionAsync(UserId));
[HttpPost("classify")]
public async Task<IActionResult> ClassifyUncategorized(ClassifyUncategorizedRequest request)
{
var job = new ClassificationJob(UserId, request.AccountId, request.StartDate, request.EndDate, request.SearchText, request.Status);
await _classificationChannel.Writer.WriteAsync(job);
return Accepted(new { message = "Classification job queued" });
}
}