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
|
namespace marlin.agents.shell;
using System.Net.Http.Json;
using core.contracts;
using core.models;
using Grpc.Core;
using Grpc.Net.Client;
using ProtoBuf.Grpc.Client;
public class MarlinApiClient
{
private readonly string _baseUrl;
private readonly Guid _agentId;
private readonly string _agentToken;
private readonly HttpClient _http;
public MarlinApiClient(string baseUrl, Guid agentId, string agentToken)
{
this._baseUrl = baseUrl;
this._agentId = agentId;
this._agentToken = agentToken;
_http = new HttpClient { BaseAddress = new Uri(this._baseUrl) };
_http.DefaultRequestHeaders.Add("Agent", $"{this._agentId} {this._agentToken}");
}
public static MarlinApiClient FromEnvironment()
{
var baseUrl = RequireEnv("MARLIN_API_BASE_URL");
var agentId = RequireEnv("MARLIN_AGENT_ID");
var agentToken = RequireEnv("MARLIN_AGENT_TOKEN");
return new MarlinApiClient(baseUrl, Guid.Parse(agentId), agentToken);
}
private static string RequireEnv(string name) =>
Environment.GetEnvironmentVariable(name)
?? throw new InvalidOperationException($"Missing required environment variable: {name}");
public async Task<AgentConfiguration> Handshake(AgentStatus status, CancellationToken ct = default)
{
var response = await _http.PostAsJsonAsync("api/dispatch/handshake", status, ct);
response.EnsureSuccessStatusCode();
return (await response.Content.ReadFromJsonAsync<AgentConfiguration>(ct))!;
}
public async Task<DispatchJob?> QueueNextJob(CancellationToken ct = default)
=> await _http.GetFromJsonAsync<DispatchJob?>("api/dispatch/queue", ct);
public GrpcChannel CreateJobScopedRpc(DispatchJob job)
{
var credentials = CallCredentials.FromInterceptor(
async (_, metadata) =>
{
metadata.Add("Agent", $"{this._agentId} {this._agentToken}");
metadata.Add("Job", $"{job.Id} {job.Token}");
});
var channel = GrpcChannel.ForAddress(this._baseUrl, new GrpcChannelOptions
{
Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
});
return channel;
}
}
|