Skip to content

Commit 239d535

Browse files
Move webconsole log into Singleton class (#566)
1 parent 9267eae commit 239d535

8 files changed

Lines changed: 201 additions & 170 deletions

src/Runner.Server/Controllers/ActionDownloadInfoController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public async Task<IActionResult> Get(Guid scopeIdentifier, string hubName, Guid
115115
actions[name] = new ActionDownloadInfo() {NameWithOwner = item.NameWithOwner, Ref = item.Ref, ResolvedNameWithOwner = item.NameWithOwner, TarballUrl = new Uri(new Uri(ServerUrl), item.Ref == BuildConstants.Source.CommitHash ? "localcheckout.tar.gz" : $"_apis/v1/ActionDownloadInfo/localcheckout?format=tarball&version={Uri.EscapeDataString(item.Ref)}&name={Uri.EscapeDataString(localcheckout)}").ToString(), ZipballUrl = new Uri(new Uri(ServerUrl), item.Ref == BuildConstants.Source.CommitHash ? "localcheckout.zip" : $"_apis/v1/ActionDownloadInfo/localcheckout?format=zipball&version={Uri.EscapeDataString(item.Ref)}&name={Uri.EscapeDataString(localcheckout)}").ToString(), ResolvedSha = item.Ref != BuildConstants.Source.CommitHash ? GitHub.Runner.Sdk.BuildConstants.Source.CommitHash : $"{GitHub.Runner.Sdk.BuildConstants.Source.CommitHash}${item.Ref}" };
116116
} else {
117117
if(!string.IsNullOrEmpty(localcheckout) && !string.IsNullOrEmpty(runid) && long.TryParse(runid, out var _runid)) {
118-
var handler = new MessageController(Configuration, this._cache, null, null);
118+
var handler = new MessageController(Configuration, this._cache, null, null, null);
119119
if(await handler.RepoExists(_runid, name)) {
120120
actions[name] = new ActionDownloadInfo() {NameWithOwner = item.NameWithOwner, ResolvedNameWithOwner = item.NameWithOwner, Ref = item.Ref, TarballUrl = new Uri(new Uri(ServerUrl), $"_apis/v1/Message/tardown/{_runid}?repositoryAndRef={Uri.EscapeDataString(name)}").ToString(), ZipballUrl = new Uri(new Uri(ServerUrl), $"_apis/v1/Message/zipdown/{_runid}?repositoryAndRef={Uri.EscapeDataString(name)}").ToString(), ResolvedSha = "Local-Repository" };
121121
continue;

src/Runner.Server/Controllers/FinishJobController.cs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Runner.Server.Models;
1313
using Microsoft.EntityFrameworkCore;
1414
using Microsoft.Extensions.Configuration;
15+
using Runner.Server.Services;
1516

1617
namespace Runner.Server.Controllers
1718
{
@@ -22,21 +23,19 @@ public class FinishJobController : VssControllerBase
2223
{
2324
private IMemoryCache _cache;
2425
private SqLiteDb _context;
26+
private WebConsoleLogService _webConsoleLogService;
2527

26-
public FinishJobController(IMemoryCache cache, SqLiteDb context, IConfiguration conf) : base(conf)
28+
public FinishJobController(IMemoryCache cache, SqLiteDb context, IConfiguration conf, WebConsoleLogService webConsoleLogService) : base(conf)
2729
{
2830
_cache = cache;
2931
_context = context;
32+
_webConsoleLogService = webConsoleLogService;
3033
}
3134

3235
public delegate void JobCompleted(JobCompletedEvent jobCompletedEvent);
33-
public delegate void JobAssigned(JobAssignedEvent jobAssignedEvent);
34-
public delegate void JobStarted(JobStartedEvent jobStartedEvent);
3536

3637
public static event JobCompleted OnJobCompleted;
3738
public static event JobCompleted OnJobCompletedAfter;
38-
public static event JobAssigned OnJobAssigned;
39-
public static event JobStarted OnJobStarted;
4039

4140
internal void InvokeJobCompleted(JobCompletedEvent ev) {
4241
try {
@@ -64,7 +63,7 @@ internal void InvokeJobCompleted(JobCompletedEvent ev) {
6463
}
6564
MessageController.UpdateJob(this, job);
6665
_context.SaveChanges();
67-
new TimelineController(_context, Configuration).SyncLiveLogsToDb(job.TimeLineId);
66+
_webConsoleLogService.SyncLiveLogsToDb(job.TimeLineId);
6867
}
6968
}
7069
} finally {
@@ -86,12 +85,6 @@ public IActionResult OnEvent(Guid scopeIdentifier, string hubName, Guid planId,
8685
if (jevent is JobCompletedEvent ev) {
8786
InvokeJobCompleted(ev);
8887
return Ok();
89-
} else if (jevent is JobAssignedEvent a) {
90-
Task.Run(() => OnJobAssigned?.Invoke(a));
91-
return Ok();
92-
} else if(jevent is JobStartedEvent s) {
93-
Task.Run(() => OnJobStarted?.Invoke(s));
94-
return Ok();
9588
}
9689
return NotFound();
9790
}

src/Runner.Server/Controllers/MessageController.cs

Lines changed: 89 additions & 88 deletions
Large diffs are not rendered by default.

src/Runner.Server/Controllers/TaskController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public IActionResult GetTaskArchive(Guid taskid, string version) {
6262
var archivePath = tasksByNameAndVersion[$"{taskid}@{version}"].ArchivePath;
6363
var prefix = "localtaskzip://";
6464
if(archivePath.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) {
65-
var handler = new MessageController(Configuration, cache, null, null);
65+
var handler = new MessageController(Configuration, cache, null, null, null);
6666
handler.ControllerContext = ControllerContext;
6767
handler.HttpContext.Response.GetTypedHeaders().ContentType = new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("application/zip");
6868
handler.GetZip(runid, false, false, archivePath.Substring(prefix.Length), true).GetAwaiter().GetResult();

src/Runner.Server/Controllers/TimeLineWebConsoleLogController.cs

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using Newtonsoft.Json.Converters;
1919
using Newtonsoft.Json.Serialization;
2020
using Runner.Server.Models;
21+
using Runner.Server.Services;
2122

2223
namespace Runner.Server.Controllers
2324
{
@@ -28,33 +29,26 @@ public class TimeLineWebConsoleLogController : VssControllerBase
2829
{
2930

3031
private IMemoryCache _cache;
32+
private readonly WebConsoleLogService _webConsoleLogService;
3133

32-
public TimeLineWebConsoleLogController(IMemoryCache cache, IConfiguration conf) : base(conf)
34+
public TimeLineWebConsoleLogController(IMemoryCache cache, IConfiguration conf, WebConsoleLogService webConsoleLogService) : base(conf)
3335
{
3436
_cache = cache;
37+
_webConsoleLogService = webConsoleLogService;
3538
}
3639

3740
[HttpGet("{timelineId}/{recordId}")]
3841
public IEnumerable<TimelineRecordLogLine> GetLogLines(Guid timelineId, Guid recordId)
3942
{
40-
if(TimelineController.dict.TryGetValue(timelineId, out var rec) && rec.Item2.TryGetValue(recordId, out var value)) {
41-
return from line in value where line != null select line;
42-
}
43-
return null;
43+
return _webConsoleLogService.GetLogLines(timelineId, recordId);
4444
}
4545

4646
[HttpGet("{timelineId}")]
4747
public ConcurrentDictionary<Guid, List<TimelineRecordLogLine>> GetLogLines(Guid timelineId)
4848
{
49-
if(TimelineController.dict.TryGetValue(timelineId, out var rec)) {
50-
return rec.Item2;
51-
}
52-
return null;
49+
return _webConsoleLogService.GetLogLines(timelineId);
5350
}
5451

55-
public delegate void LogFeedEvent(object sender, Guid timelineId, Guid recordId, TimelineRecordFeedLinesWrapper record);
56-
public static event LogFeedEvent logfeed;
57-
5852
[HttpGet]
5953
public IActionResult Message([FromQuery] Guid timelineId, [FromQuery] long[] runid)
6054
{
@@ -64,17 +58,17 @@ public IActionResult Message([FromQuery] Guid timelineId, [FromQuery] long[] run
6458
await using(var writer = new StreamWriter(stream) { NewLine = "\n" } ) {
6559
var queue2 = Channel.CreateUnbounded<KeyValuePair<string,string>>(new UnboundedChannelOptions { SingleReader = true });
6660
var chwriter = queue2.Writer;
67-
LogFeedEvent handler = (sender, timelineId2, recordId, record) => {
68-
(List<TimelineRecord>, ConcurrentDictionary<Guid, List<TimelineRecordLogLine>>) val;
61+
WebConsoleLogService.LogFeedEvent handler = (sender, timelineId2, recordId, record) => {
6962
Job job;
70-
if (timelineId == timelineId2 || timelineId == Guid.Empty && (runid.Length == 0 || TimelineController.dict.TryGetValue(timelineId2, out val) && val.Item1.Any() && _cache.TryGetValue(val.Item1[0].Id, out job) && runid.Contains(job.runid))) {
63+
TimelineRecord record1;
64+
if (timelineId == timelineId2 || timelineId == Guid.Empty && (runid.Length == 0 || (record1 = _webConsoleLogService.GetTimeLine(timelineId2)?.FirstOrDefault()) != null && _cache.TryGetValue(record1.Id, out job) && runid.Contains(job.runid))) {
7165
chwriter.WriteAsync(new KeyValuePair<string, string>("log", JsonConvert.SerializeObject(new { timelineId = timelineId2, recordId, record }, new JsonSerializerSettings{ ContractResolver = new CamelCasePropertyNamesContractResolver(), Converters = new List<JsonConverter>{new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy() }}})));
7266
}
7367
};
7468
TimelineController.TimeLineUpdateDelegate handler2 = (timelineId2, timeline) => {
75-
(List<TimelineRecord>, ConcurrentDictionary<Guid, List<TimelineRecordLogLine>>) val;
7669
Job job;
77-
if(timelineId == timelineId2 || timelineId == Guid.Empty && (runid.Length == 0 || TimelineController.dict.TryGetValue(timelineId2, out val) && val.Item1.Any() && _cache.TryGetValue(val.Item1[0].Id, out job) && runid.Contains(job.runid))) {
70+
TimelineRecord record2;
71+
if(timelineId == timelineId2 || timelineId == Guid.Empty && (runid.Length == 0 || (record2 = _webConsoleLogService.GetTimeLine(timelineId2)?.FirstOrDefault()) != null && _cache.TryGetValue(record2.Id, out job) && runid.Contains(job.runid))) {
7872
chwriter.WriteAsync(new KeyValuePair<string, string>("timeline", JsonConvert.SerializeObject(new { timelineId = timelineId2, timeline }, new JsonSerializerSettings{ ContractResolver = new CamelCasePropertyNamesContractResolver(), Converters = new List<JsonConverter>{new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy() }}})));
7973
}
8074
};
@@ -111,7 +105,7 @@ public IActionResult Message([FromQuery] Guid timelineId, [FromQuery] long[] run
111105

112106
}
113107
}, requestAborted);
114-
logfeed += handler;
108+
_webConsoleLogService.LogFeed += handler;
115109
TimelineController.TimeLineUpdate += handler2;
116110
MessageController.OnRepoDownload += rd;
117111
FinishJobController.OnJobCompleted += completed;
@@ -121,7 +115,7 @@ public IActionResult Message([FromQuery] Guid timelineId, [FromQuery] long[] run
121115
} catch(OperationCanceledException) {
122116

123117
} finally {
124-
logfeed -= handler;
118+
_webConsoleLogService.LogFeed -= handler;
125119
TimelineController.TimeLineUpdate -= handler2;
126120
MessageController.OnRepoDownload -= rd;
127121
FinishJobController.OnJobCompleted -= completed;
@@ -131,16 +125,6 @@ public IActionResult Message([FromQuery] Guid timelineId, [FromQuery] long[] run
131125
}, "text/event-stream");
132126
}
133127

134-
public static void AppendTimelineRecordFeed(TimelineRecordFeedLinesWrapper record, Guid timelineId, Guid recordId) {
135-
logfeed?.Invoke(null, timelineId, recordId, record);
136-
(List<TimelineRecord>, ConcurrentDictionary<Guid, List<TimelineRecordLogLine>>) timeline;
137-
timeline = TimelineController.dict.GetOrAdd(timelineId, g => (new List<TimelineRecord>(), new ConcurrentDictionary<Guid, List<TimelineRecordLogLine>>()));
138-
timeline.Item2.AddOrUpdate(record.StepId, t => record.Value.Select((s, i) => new TimelineRecordLogLine(s, null)).ToList(), (g, t) => {
139-
t.AddRange(record.Value.Select((s) => new TimelineRecordLogLine(s, null)));
140-
return t;
141-
});
142-
}
143-
144128
[HttpPost("{scopeIdentifier}/{hubName}/{planId}/{timelineId}/{recordId}")]
145129
[Authorize(AuthenticationSchemes = "Bearer", Policy = "AgentJob")]
146130
public IActionResult AppendTimelineRecordFeed(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, Guid recordId, [FromBody, Vss] TimelineRecordFeedLinesWrapper record)
@@ -150,7 +134,7 @@ public IActionResult AppendTimelineRecordFeed(Guid scopeIdentifier, string hubNa
150134
var nl = record.Value.SelectMany(lines => regex.Split(lines)).ToList();
151135
record.Value.Clear();
152136
record.Value.AddRange(nl);
153-
Task.Run(() => AppendTimelineRecordFeed(record, timelineId, recordId));
137+
Task.Run(() => _webConsoleLogService.AppendTimelineRecordFeed(record, timelineId, recordId));
154138
return Ok();
155139
}
156140

@@ -181,7 +165,7 @@ public async Task Get(Guid timelineId)
181165
var regex = new Regex("\r?\n");
182166
var nl = livelogfeed.Value.SelectMany(lines => regex.Split(lines)).ToList();
183167
var record = new TimelineRecordFeedLinesWrapper(livelogfeed.StepId, nl);
184-
AppendTimelineRecordFeed(record, timelineId, livelogfeed.StepId);
168+
_webConsoleLogService.AppendTimelineRecordFeed(record, timelineId, livelogfeed.StepId);
185169
}
186170
}
187171
} finally {

src/Runner.Server/Controllers/TimelineController.cs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,13 @@ namespace Runner.Server.Controllers
2626
[Route("{owner}/{repo}/_apis/v1/[controller]")]
2727
public class TimelineController : VssControllerBase
2828
{
29-
public static ConcurrentDictionary<Guid, (List<TimelineRecord>, ConcurrentDictionary<Guid, List<TimelineRecordLogLine>>)> dict = new ConcurrentDictionary<Guid, (List<TimelineRecord>, ConcurrentDictionary<Guid, List<TimelineRecordLogLine>>)>();
3029
private SqLiteDb _context;
3130

3231
public TimelineController(SqLiteDb context, IConfiguration conf) : base(conf)
3332
{
3433
_context = context;
3534
}
3635

37-
internal void SyncLiveLogsToDb(Guid timelineId) {
38-
if(dict.TryRemove(timelineId, out var entry)) {
39-
foreach(var rec in (from record in _context.TimeLineRecords where record.TimelineId == timelineId select record).Include(r => r.Log).ToList()) {
40-
if(rec.Log == null && entry.Item2.TryGetValue(rec.Id, out var value)) {
41-
var log = new TaskLog() { };
42-
_context.Logs.Add(new SqLiteDb.LogStorage() { Ref = log, Content = string.Join('\n', from line in value where line != null select line.Line) });
43-
rec.Log = log;
44-
}
45-
}
46-
_context.SaveChanges();
47-
}
48-
}
49-
5036
[HttpGet("{timelineId}")]
5137
public async Task<IActionResult> GetTimelineRecords(Guid timelineId) {
5238
var l = (from record in _context.TimeLineRecords where record.TimelineId == timelineId select record).Include(r => r.Log).ToList();
@@ -178,14 +164,14 @@ private List<TimelineRecord> MergeTimelineRecords(List<TimelineRecord> timelineR
178164
[SwaggerResponse(200, type: typeof(VssJsonCollectionWrapper<List<TimelineRecord>>))]
179165
public async Task<IActionResult> Patch(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, [FromBody, Vss] VssJsonCollectionWrapper<List<TimelineRecord>> patch)
180166
{
181-
return await UpdateTimeLine(timelineId, patch, true);
167+
return await Ok(new VssJsonCollectionWrapper<List<TimelineRecord>>(await UpdateTimeLine(timelineId, patch?.Value, true)));
182168
}
183169

184-
internal async Task<IActionResult> UpdateTimeLine(Guid timelineId, VssJsonCollectionWrapper<List<TimelineRecord>> patch, bool outOfSyncTimeLineUpdate = false)
170+
internal async Task<List<TimelineRecord>> UpdateTimeLine(Guid timelineId, List<TimelineRecord> patch, bool outOfSyncTimeLineUpdate = false)
185171
{
186172
var old = (from record in _context.TimeLineRecords where record.TimelineId == timelineId select record).Include(r => r.Log).ToList();
187173
var records = old.ToList();
188-
records.AddRange(patch.Value.Select((r, _) => {
174+
records.AddRange(patch.Select((r, _) => {
189175
r.TimelineId = timelineId;
190176
if(r.Log != null) {
191177
var logId = r.Log.Id;
@@ -226,7 +212,7 @@ internal async Task<IActionResult> UpdateTimeLine(Guid timelineId, VssJsonCollec
226212

227213
await _context.AddRangeAsync(from rec in records where !old.Contains(rec) select rec);
228214
await _context.SaveChangesAsync();
229-
return await Ok(patch);
215+
return patch;
230216
}
231217
}
232218
}

0 commit comments

Comments
 (0)