Changes
Build and Push Docker Images / build (push) Failing after 0s

This commit is contained in:
2026-05-07 19:32:07 +03:00
parent fe3dbc37ad
commit f608bec742
12 changed files with 57 additions and 34 deletions
+3 -6
View File
@@ -1,14 +1,11 @@
using Microsoft.AspNetCore.Http; using Shared.Models.Requests;
using System.ComponentModel.DataAnnotations;
namespace Models.Requests namespace Models.Requests
{ {
public sealed class UploadCvRequest public sealed class UploadCvRequest : UploadFileRequest
{ {
[Required]
public IFormFile Cv { get; set; } = default!;
public bool GdprConsent { get; set; } public bool GdprConsent { get; set; }
public string? CaptchaToken { get; set; } public string? CaptchaToken { get; set; }
} }
} }
+4
View File
@@ -11,4 +11,8 @@
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="5.0.17" /> <PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="5.0.17" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\shared-models\shared-models.csproj" />
</ItemGroup>
</Project> </Project>
+4 -4
View File
@@ -1,6 +1,6 @@
using Refit;
using Models.Requests;
using CvMatcher.Models.Responses; using CvMatcher.Models.Responses;
using Models.Requests;
using Refit;
namespace Api.Clients.Api.Contracts; namespace Api.Clients.Api.Contracts;
@@ -8,8 +8,8 @@ public interface ICvMatcherApi
{ {
[Multipart] [Multipart]
[Post("/api/cv/upload")] [Post("/api/cv/upload")]
Task<CvUploadResponse> Upload([AliasAs("cv")] StreamPart cv, [AliasAs("gdprConsent")] bool gdprConsent); Task<CvUploadResponse> Upload([AliasAs("file")] StreamPart file, CancellationToken ct);
[Post("/api/cv/match-job")] [Post("/api/cv/match-job")]
Task<JobMatchResponse> MatchJob([Body] JobMatchRequest request); Task<JobMatchResponse> MatchJob([Body] JobMatchRequest request, CancellationToken ct);
} }
+6 -4
View File
@@ -47,12 +47,12 @@ public sealed class CvMatcherController : ControllerBase
[FromForm] UploadCvRequest request, [FromForm] UploadCvRequest request,
CancellationToken ct) CancellationToken ct)
{ {
if (request.Cv is null) if (request.File is null)
{ {
return BadRequest(new { error = "Missing CV PDF." }); return BadRequest(new { error = "Missing CV PDF." });
} }
var cv = request.Cv; var cv = request.File;
var gdprConsent = request.GdprConsent; var gdprConsent = request.GdprConsent;
try try
@@ -65,12 +65,14 @@ public sealed class CvMatcherController : ControllerBase
return BadRequest(new { error = "Captcha verification failed." }); return BadRequest(new { error = "Captcha verification failed." });
} }
if (!gdprConsent) throw new InvalidOperationException("GDPR consent is required.");
_logger.LogInformation("Proxying CV upload to cv-matcher-api. FileName={FileName}, Size={SizeBytes}, GdprConsent={GdprConsent}", _logger.LogInformation("Proxying CV upload to cv-matcher-api. FileName={FileName}, Size={SizeBytes}, GdprConsent={GdprConsent}",
cv.FileName, cv.Length, gdprConsent); cv.FileName, cv.Length, gdprConsent);
var stream = cv.OpenReadStream(); var stream = cv.OpenReadStream();
var part = new Refit.StreamPart(stream, cv.FileName, "application/pdf"); var part = new Refit.StreamPart(stream, cv.FileName, "application/pdf");
var res = await _cvApi.Upload(part, gdprConsent); var res = await _cvApi.Upload(part, ct);
return Ok(res); return Ok(res);
} }
catch (OperationCanceledException) when (ct.IsCancellationRequested) catch (OperationCanceledException) when (ct.IsCancellationRequested)
@@ -114,7 +116,7 @@ public sealed class CvMatcherController : ControllerBase
request.CvDocumentId, request.CvDocumentId,
!string.IsNullOrWhiteSpace(request.JobUrl), !string.IsNullOrWhiteSpace(request.JobUrl),
!string.IsNullOrWhiteSpace(request.JobDescription)); !string.IsNullOrWhiteSpace(request.JobDescription));
var res = await _cvApi.MatchJob(request); var res = await _cvApi.MatchJob(request, ct);
return Ok(res); return Ok(res);
} }
catch (OperationCanceledException) when (ct.IsCancellationRequested) catch (OperationCanceledException) when (ct.IsCancellationRequested)
+5 -4
View File
@@ -2,6 +2,7 @@ using CvMatcher.Models.Requests;
using Api.Services.Contracts; using Api.Services.Contracts;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using CvMatcher.Models.Responses; using CvMatcher.Models.Responses;
using Shared.Models.Requests;
namespace Api.Controllers; namespace Api.Controllers;
@@ -20,13 +21,13 @@ public sealed class CvController : ControllerBase
[HttpPost("upload")] [HttpPost("upload")]
[RequestSizeLimit(10 * 1024 * 1024)] [RequestSizeLimit(10 * 1024 * 1024)]
public async Task<ActionResult<CvUploadResponse>> Upload([FromForm(Name = "cv")] IFormFile? cv, [FromForm] bool gdprConsent, CancellationToken ct) public async Task<ActionResult<CvUploadResponse>> Upload([FromForm] UploadFileRequest request, CancellationToken ct)
{ {
try try
{ {
if (cv is null) return BadRequest(new { error = "Missing CV PDF." }); if (request.File is null) return BadRequest(new { error = "Missing CV PDF." });
_logger.LogInformation("CV upload received. FileName={FileName}, Size={SizeBytes}, GdprConsent={GdprConsent}", cv.FileName, cv.Length, gdprConsent); _logger.LogInformation("CV upload received. FileName={FileName}, Size={SizeBytes}", request.File.FileName, request.File.Length);
var result = await _service.UploadCvAsync(cv, gdprConsent, ct); var result = await _service.UploadCvAsync(request.File, ct);
_logger.LogInformation("CV upload processed. CvDocumentId={CvDocumentId}, Cached={Cached}", result.DocumentId, result.Cached); _logger.LogInformation("CV upload processed. CvDocumentId={CvDocumentId}, Cached={Cached}", result.DocumentId, result.Cached);
return Ok(result); return Ok(result);
} }
@@ -5,7 +5,7 @@ namespace Api.Services.Contracts;
public interface ICvMatcherService public interface ICvMatcherService
{ {
Task<CvUploadResponse> UploadCvAsync(IFormFile file, bool gdprConsent, CancellationToken ct); Task<CvUploadResponse> UploadCvAsync(IFormFile file, CancellationToken ct);
Task<JobMatchResponse> MatchJobAsync(MatchJobRequest request, CancellationToken ct); Task<JobMatchResponse> MatchJobAsync(MatchJobRequest request, CancellationToken ct);
Task<FindJobsResponse> FindJobsAsync(FindJobsRequest request, CancellationToken ct); Task<FindJobsResponse> FindJobsAsync(FindJobsRequest request, CancellationToken ct);
} }
+1 -2
View File
@@ -32,9 +32,8 @@ public sealed class CvMatcherService : ICvMatcherService
_settings = options.Value; _settings = options.Value;
} }
public async Task<CvUploadResponse> UploadCvAsync(IFormFile file, bool gdprConsent, CancellationToken ct) public async Task<CvUploadResponse> UploadCvAsync(IFormFile file, CancellationToken ct)
{ {
if (!gdprConsent) throw new InvalidOperationException("GDPR consent is required.");
var response = await _rag.IndexCvPdfAsync(file, ct); var response = await _rag.IndexCvPdfAsync(file, ct);
return new CvUploadResponse return new CvUploadResponse
{ {
@@ -1,6 +1,6 @@
namespace Rag.Models.Requests namespace Rag.Models.Requests
{ {
public sealed class IndexDocumentRequest public class IndexDocumentRequest
{ {
public string? Text { get; set; } public string? Text { get; set; }
public string? SourceUrl { get; set; } public string? SourceUrl { get; set; }
@@ -0,0 +1,9 @@
using Microsoft.AspNetCore.Http;
namespace Rag.Models.Requests
{
public sealed class IndexDocumentUploadRequest: IndexDocumentRequest
{
public IFormFile? File { get; set; }
}
}
+8 -12
View File
@@ -21,21 +21,17 @@ public sealed class RagController : ControllerBase
[HttpPost("documents")] [HttpPost("documents")]
[RequestSizeLimit(10 * 1024 * 1024)] [RequestSizeLimit(10 * 1024 * 1024)]
public async Task<ActionResult<IndexDocumentResponse>> IndexDocument( public async Task<ActionResult<IndexDocumentResponse>> IndexDocument(
[FromForm] IFormFile? file, [FromForm] IndexDocumentUploadRequest request,
[FromForm] string? text,
[FromForm] string? documentType,
[FromForm] string? title,
[FromForm] string? sourceUrl,
CancellationToken ct) CancellationToken ct)
{ {
try try
{ {
_logger.LogInformation("Index document request received. HasFile={HasFile}, DocumentType={DocumentType}, Title={Title}, SourceUrl={SourceUrl}", _logger.LogInformation("Index document request received. HasFile={HasFile}, DocumentType={DocumentType}, Title={Title}, SourceUrl={SourceUrl}",
file is not null, documentType, title, sourceUrl); request.File is not null, request.DocumentType, request.Title, request.SourceUrl);
if (file is not null) if (request.File is not null)
{ {
var result = await _ragService.IndexPdfAsync(file, documentType, title, sourceUrl, ct); var result = await _ragService.IndexPdfAsync(request.File, request.DocumentType, request.Title, request.SourceUrl, ct);
_logger.LogInformation("Indexed PDF document. DocumentId={DocumentId}, DocumentType={DocumentType}, Chunks={Chunks}, Cached={Cached}", _logger.LogInformation("Indexed PDF document. DocumentId={DocumentId}, DocumentType={DocumentType}, Chunks={Chunks}, Cached={Cached}",
result.DocumentId, result.DocumentType, result.Chunks, result.Cached); result.DocumentId, result.DocumentType, result.Chunks, result.Cached);
return Ok(result); return Ok(result);
@@ -43,10 +39,10 @@ public sealed class RagController : ControllerBase
var textResult = await _ragService.IndexTextAsync(new IndexDocumentRequest var textResult = await _ragService.IndexTextAsync(new IndexDocumentRequest
{ {
Text = text, Text = request.Text,
DocumentType = documentType, DocumentType = request.DocumentType,
Title = title, Title = request.Title,
SourceUrl = sourceUrl SourceUrl = request.SourceUrl
}, ct); }, ct);
_logger.LogInformation("Indexed text document. DocumentId={DocumentId}, DocumentType={DocumentType}, Chunks={Chunks}, Cached={Cached}", _logger.LogInformation("Indexed text document. DocumentId={DocumentId}, DocumentType={DocumentType}, Chunks={Chunks}, Cached={Cached}",
textResult.DocumentId, textResult.DocumentType, textResult.Chunks, textResult.Cached); textResult.DocumentId, textResult.DocumentType, textResult.Chunks, textResult.Cached);
@@ -0,0 +1,11 @@
using Microsoft.AspNetCore.Http;
using System.ComponentModel.DataAnnotations;
namespace Shared.Models.Requests
{
public class UploadFileRequest
{
[Required]
public IFormFile File { get; set; } = default!;
}
}
+4
View File
@@ -7,4 +7,8 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="5.0.17" />
</ItemGroup>
</Project> </Project>