nitai/projects
rblxtool / src / ui / RblxTool / Services / JobRunner.cs
97 lines · 2.4 KB Raw
1using Microsoft.UI.Dispatching;
2using RblxTool.Interop;
3using RblxTool.Models;
4
5namespace RblxTool.Services;
6
7public sealed class JobRunner
8{
9 private readonly RblxEngine _engine;
10 private readonly DispatcherQueue _dispatcher;
11 private CancellationTokenSource? _pump;
12
13 public JobRunner(RblxEngine engine, DispatcherQueue dispatcher)
14 {
15 _engine = engine;
16 _dispatcher = dispatcher;
17 }
18
19 public ulong JobId { get; private set; }
20
21 public bool Running => _pump is not null && !_pump.IsCancellationRequested;
22
23 public event Action<JobEvent>? EventReceived;
24
25 public event Action<string>? Completed;
26
27 public void Start(ulong jobId, int pollIntervalMs = 120)
28 {
29 if (jobId == 0)
30 {
31 Completed?.Invoke("engine refused the job");
32 return;
33 }
34 Stop();
35 JobId = jobId;
36 var source = new CancellationTokenSource();
37 _pump = source;
38 _ = Task.Run(() => Pump(jobId, pollIntervalMs, source.Token), source.Token);
39 }
40
41 private async Task Pump(ulong jobId, int pollIntervalMs, CancellationToken token)
42 {
43 var idle = 0;
44 while (!token.IsCancellationRequested)
45 {
46 var poll = _engine.Poll(jobId);
47 if (poll.Events.Count > 0)
48 {
49 idle = 0;
50 var batch = poll.Events;
51 _dispatcher.TryEnqueue(DispatcherQueuePriority.Low, () =>
52 {
53 foreach (var item in batch)
54 {
55 EventReceived?.Invoke(item);
56 }
57 });
58 }
59 else
60 {
61 idle++;
62 }
63
64 if (poll.Done && poll.Events.Count == 0)
65 {
66 var result = _engine.Result(jobId);
67 _dispatcher.TryEnqueue(() => Completed?.Invoke(result));
68 break;
69 }
70
71 var delay = idle > 20 ? pollIntervalMs * 4 : pollIntervalMs;
72 try
73 {
74 await Task.Delay(delay, token).ConfigureAwait(false);
75 }
76 catch (TaskCanceledException)
77 {
78 break;
79 }
80 }
81 }
82
83 public void Cancel()
84 {
85 if (JobId != 0)
86 {
87 _engine.Cancel(JobId);
88 }
89 }
90
91 public void Stop()
92 {
93 _pump?.Cancel();
94 _pump?.Dispose();
95 _pump = null;
96 }
97}