Skip to content

Commit e3baec6

Browse files
committed
Improve agent
1 parent 284f347 commit e3baec6

File tree

1 file changed

+122
-47
lines changed

1 file changed

+122
-47
lines changed

src/IntelOrca.Biohazard.BioRand.Common/RandomizerAgent.cs

Lines changed: 122 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
using System;
2-
using System.Net.Http;
3-
using System.Text;
4-
using System.Text.Json;
5-
using System.Threading;
6-
using System.Threading.Tasks;
7-
81
namespace IntelOrca.Biohazard.BioRand
92
{
103
public class RandomizerAgent
@@ -18,10 +11,10 @@ public class RandomizerAgent
1811
{
1912
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
2013
};
21-
private bool _generating;
22-
private TimeSpan _pollTime = TimeSpan.FromSeconds(5);
23-
private TimeSpan _restartTime = TimeSpan.FromSeconds(5);
2414
private readonly IRandomizerAgentHandler _handler;
15+
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
16+
private DateTime _lastHeartbeatTime;
17+
private bool _shownWaitingMessage;
2518

2619
public IRandomizer Randomizer => _handler.Randomizer;
2720
public string BaseUri { get; }
@@ -30,6 +23,10 @@ public class RandomizerAgent
3023
public Guid Id { get; private set; }
3124
public string Status { get; private set; } = StatusIdle;
3225

26+
public TimeSpan HeartbeatTime { get; set; } = TimeSpan.FromSeconds(5);
27+
public TimeSpan PollTime { get; set; } = TimeSpan.FromSeconds(5);
28+
public TimeSpan RestartTime { get; set; } = TimeSpan.FromSeconds(5);
29+
3330
public RandomizerAgent(string baseUri, string apiKey, int gameId, IRandomizerAgentHandler handler)
3431
{
3532
BaseUri = baseUri;
@@ -44,21 +41,18 @@ public async Task RunAsync(CancellationToken ct = default)
4441
{
4542
while (!ct.IsCancellationRequested)
4643
{
47-
await RegisterAsync();
48-
while (!ct.IsCancellationRequested)
44+
if (await RegisterAsync())
4945
{
50-
await SendStatusAsync();
51-
if (!_generating)
52-
{
53-
await ProcessNextRandomizer();
54-
}
55-
await Task.Delay(_pollTime);
46+
await Task.WhenAny(
47+
RunStatusLoopAsync(ct),
48+
RunProcessLoopAsync(ct));
49+
await UnregisterAsync();
5650
}
57-
await Task.Delay(_restartTime);
51+
await Task.Delay(RestartTime, ct);
5852
}
5953
}
6054

61-
private async Task RegisterAsync()
55+
private async Task<bool> RegisterAsync()
6256
{
6357
_handler.LogInfo($"Registering agent at {BaseUri}...");
6458
try
@@ -71,10 +65,59 @@ private async Task RegisterAsync()
7165
});
7266
Id = response.Id;
7367
_handler.LogInfo($"Registered as agent {Id}");
68+
return true;
7469
}
7570
catch (Exception ex)
7671
{
7772
_handler.LogError(ex, "Failed to register agent");
73+
return false;
74+
}
75+
}
76+
77+
private async Task UnregisterAsync()
78+
{
79+
_handler.LogInfo($"Unregistering agent...");
80+
try
81+
{
82+
await PostAsync<object>("generator/unregister", new { Id });
83+
_handler.LogInfo($"Unregistered agent {Id}");
84+
}
85+
catch (Exception ex)
86+
{
87+
_handler.LogError(ex, "Failed to unregister agent");
88+
}
89+
}
90+
91+
private async Task RunStatusLoopAsync(CancellationToken ct)
92+
{
93+
while (!ct.IsCancellationRequested)
94+
{
95+
await _semaphore.WaitAsync();
96+
try
97+
{
98+
var timeSinceLastHeartbeat = DateTime.UtcNow - _lastHeartbeatTime;
99+
if (timeSinceLastHeartbeat >= HeartbeatTime)
100+
{
101+
await SendStatusAsync();
102+
}
103+
}
104+
finally
105+
{
106+
_semaphore.Release();
107+
}
108+
await Task.Delay(HeartbeatTime, ct);
109+
}
110+
}
111+
112+
private async Task RunProcessLoopAsync(CancellationToken ct)
113+
{
114+
_shownWaitingMessage = false;
115+
while (!ct.IsCancellationRequested)
116+
{
117+
if (!await ProcessNextRandomizer(ct))
118+
{
119+
await Task.Delay(PollTime, ct);
120+
}
78121
}
79122
}
80123

@@ -87,51 +130,81 @@ private async Task SendStatusAsync()
87130
Id,
88131
Status
89132
});
133+
_lastHeartbeatTime = DateTime.UtcNow;
90134
}
91135
catch (Exception ex)
92136
{
93137
_handler.LogError(ex, "Failed to send heartbeat");
94138
}
95139
}
96140

97-
private async Task ProcessNextRandomizer()
141+
private async Task SetStatusAsync(string status)
142+
{
143+
await _semaphore.WaitAsync();
144+
try
145+
{
146+
Status = status;
147+
await SendStatusAsync();
148+
}
149+
finally
150+
{
151+
_semaphore.Release();
152+
}
153+
}
154+
155+
private async Task<bool> ProcessNextRandomizer(CancellationToken ct)
98156
{
99157
try
100158
{
159+
if (ct.IsCancellationRequested)
160+
return false;
161+
162+
if (!_shownWaitingMessage)
163+
{
164+
_shownWaitingMessage = true;
165+
_handler.LogInfo($"Waiting for next rando to generate...");
166+
}
101167
var queue = await GetAsync<QueueResponseItem[]>("generator/queue");
102168
foreach (var q in queue)
103169
{
170+
if (ct.IsCancellationRequested)
171+
return false;
104172
if (q.GameId != GameId)
105173
continue;
106174

107175
if (await _handler.CanGenerateAsync(q))
108176
{
177+
if (ct.IsCancellationRequested)
178+
return false;
179+
109180
try
110181
{
111182
_handler.LogInfo($"Generating rando {q.Id}...");
183+
_shownWaitingMessage = false;
112184
await PostAsync<object>("generator/begin", new
113185
{
114186
Id,
115187
RandoId = q.Id,
116188
Version = Randomizer.BuildVersion
117189
});
118-
await BeginGeneration(q);
190+
await GenerateRandomizer(q);
191+
return true;
119192
}
120193
catch (Exception ex)
121194
{
122195
_handler.LogError(ex, "Failed to begin generating randomizer");
123196
}
124-
break;
125197
}
126198
}
127199
}
128200
catch (Exception ex)
129201
{
130202
_handler.LogError(ex, "Failed to get randomizer queue");
131203
}
204+
return false;
132205
}
133206

134-
private async Task BeginGeneration(QueueResponseItem q)
207+
private async Task GenerateRandomizer(QueueResponseItem q)
135208
{
136209
var randomizerInput = new RandomizerInput()
137210
{
@@ -142,37 +215,39 @@ private async Task BeginGeneration(QueueResponseItem q)
142215
Seed = q.Seed
143216
};
144217

145-
_generating = true;
146218
try
147219
{
148-
await Task.Run(async () =>
220+
await SetStatusAsync(StatusGenerating);
221+
RandomizerOutput output;
222+
try
149223
{
150-
try
224+
output = await _handler.GenerateAsync(q, randomizerInput);
225+
}
226+
catch (Exception ex)
227+
{
228+
await PostAsync<object>("generator/fail", new
151229
{
152-
Status = StatusGenerating;
153-
var output = await _handler.GenerateAsync(q, randomizerInput);
230+
Id,
231+
RandoId = q.Id
232+
});
233+
_handler.LogError(ex, "Failed to generate randomizer");
234+
return;
235+
}
154236

155-
Status = StatusUploading;
156-
_handler.LogInfo($"Uploading rando {q.Id}...");
157-
await PostAsync<object>("generator/end", new
158-
{
159-
Id,
160-
RandoId = q.Id,
161-
output.PakOutput,
162-
output.FluffyOutput
163-
});
164-
_handler.LogInfo($"Uploaded rando {q.Id}");
165-
}
166-
finally
167-
{
168-
Status = StatusIdle;
169-
_generating = false;
170-
}
237+
await SetStatusAsync(StatusUploading);
238+
_handler.LogInfo($"Uploading rando {q.Id}...");
239+
await PostAsync<object>("generator/end", new
240+
{
241+
Id,
242+
RandoId = q.Id,
243+
output.PakOutput,
244+
output.FluffyOutput
171245
});
246+
_handler.LogInfo($"Uploaded rando {q.Id}");
172247
}
173-
catch
248+
finally
174249
{
175-
_generating = false;
250+
await SetStatusAsync(StatusIdle);
176251
}
177252
}
178253

0 commit comments

Comments
 (0)