summaryrefslogtreecommitdiff
path: root/src/marlin.web/Controllers/Api/DispatchController.cs
blob: 076c4dd4ce8749636418881d3d9fa734c9168fb7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
namespace marlin.web.Controllers.Api;

using marlin.core.models;
using marlin.core.util;
using marlin.web.Data;
using marlin.web.Models;
using marlin.web.Util;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

[Route("api/dispatch")]
[ApiController]
[Authorize(Policy = "Agent")]
public class DispatchController(ApplicationDbContext dbContext) : ControllerBase
{
    [HttpPost("handshake")]
    public async Task<ActionResult<AgentConfiguration>> Handshake(AgentStatus status, CancellationToken ct)
    {
        var agentId = this.User.RequireAgentId();

        var agent = await dbContext.Agents
            .FirstAsync(x => x.Id == agentId, ct);

        foreach (var capability in status.CapabilitySet.Items)
            agent.Capabilities.Items[capability.Key] = capability.Value;

        await dbContext.SaveChangesAsync(ct);

        return new AgentConfiguration(
            Name: agent.Name,
            MaxConcurrentJobs: agent.MaxConcurrentJobs
        );
    }

    [HttpGet("queue")]
    public async Task<ActionResult<DispatchJob?>> Queue(CancellationToken ct)
    {
        var agentId = this.User.RequireAgentId();

        var nextJob = await dbContext
            .Jobs
            .Include(x => x.Source)
            .Include(x => x.Branch)
            .Include(x => x.Commit)
            .Where(x => x.Status == JobStatus.Pending && x.AgentId == null)
            .OrderBy(x => x.CreatedAt)
            .FirstOrDefaultAsync(ct);

        if (nextJob == null)
            return (DispatchJob?)null;

        string claimToken = SecureTokenGenerator.CreateClaimToken();
        nextJob.ClaimToken = claimToken;
        nextJob.AgentId = agentId;

        await dbContext.SaveChangesAsync(ct);

        return new DispatchJob(
            Id: nextJob.Id,
            Token: claimToken,
            Vcs: nextJob.Source.UpstreamUrl,
            Ref: nextJob.Branch.Name,
            Commit: nextJob.Commit.Hash,
            Recipe: nextJob.Recipe
        );
    }
}