333b21224d
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>
46 lines
1.8 KiB
C#
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" });
|
|
}
|
|
}
|