namespace marlin.agents.shell; using System.Runtime.InteropServices; using core.contracts; using core.functional; using core.models; using core.util; using ProtoBuf.Grpc.Client; public class SlaveLoop { private static readonly string _jobInstanceDir = Path.Combine(CommonPaths.AgentRoot, "instance"); private readonly MarlinApiClient _client; public SlaveLoop() { this._client = MarlinApiClient.FromEnvironment(); } public async Task Start() { AgentConfiguration config = await Handshake(); Console.WriteLine($"IAM: {config.Name}"); Console.WriteLine($"MCJ: {config.MaxConcurrentJobs}"); while (true) { var job = await this._client.QueueNextJob(); if (job == null) { await Task.Delay(TimeSpan.FromSeconds(5)); continue; } Console.WriteLine($"Claimed job {job.Id}: {job.Recipe}"); await FireJob(job); } } private async Task Handshake() { var capabilities = new CapabilitySet(); capabilities.Items.Add(KnownCapabilities.Architecture, RuntimeInformation.OSArchitecture.ToString()); capabilities.Items.Add(KnownCapabilities.CoreCount, Environment.ProcessorCount.ToString()); capabilities.Items.Add(KnownCapabilities.Memory, (GC.GetGCMemoryInfo().TotalAvailableMemoryBytes / (1024 * 1024)).ToString()); var status = new AgentStatus(capabilities); AgentConfiguration config = await _client.Handshake(status); return config; } private async Task FireJob(DispatchJob job) { GitBinaryClient gitClient = new(); var channel = this._client.CreateJobScopedRpc(job); var instanceService = channel.CreateGrpcService(); string workingDir = Path.Combine(_jobInstanceDir, job.Id.ToString("N")); Directory.CreateDirectory(_jobInstanceDir); if (Path.Exists(workingDir)) Directory.Delete(workingDir, true); await gitClient.Checkout(workingDir, job.Vcs, job.Ref, job.Commit); var uow = new JobUnitOfWork(instanceService, workingDir, job.Recipe); await uow.Run(); } }