feat: daily node restart controlled from the admin, connect timings as a default line task [CI]
ci/woodpecker/push/main-amd64-build Pipeline was successful
ci/woodpecker/push/main-amd64-build Pipeline was successful
Agents and Probes exit in order at a configured time (default 04:30 UTC+8, switch and time zone in the admin settings) and the service manager starts them again; a local restart_at or MOSHIRO_RESTART_AT wins. The connect kind (TCP connect and TLS handshake timings) is now a default continuous line template, with a section on the line page.
This commit is contained in:
1 parent
388619b8b6
commit
9bcef56497
37 files changed
+928
-101
No files matched your search
@@ -126,7 +126,8 @@ public static class PlatformCheck
|
||||
/// <summary>处理 Ctrl+C 和 SIGTERM:取消令牌,让各个模块有序退出。</summary>
|
||||
public static class ServiceShell
|
||||
{
|
||||
public static async Task RunAsync(Func<CancellationToken, Task> run, INodeLog log)
|
||||
/// <param name="restart">每天定时有序退出一次(见 <see cref="RestartController"/>),重新拉起由服务管理器负责。</param>
|
||||
public static async Task RunAsync(Func<CancellationToken, Task> run, INodeLog log, RestartController? restart = null, TimeProvider? time = null)
|
||||
{
|
||||
using var cts = new CancellationTokenSource();
|
||||
using PosixSignalRegistration term = PosixSignalRegistration.Create(PosixSignal.SIGTERM, context =>
|
||||
@@ -156,6 +157,7 @@ public static class ServiceShell
|
||||
cts.Cancel();
|
||||
});
|
||||
Task trimmer = TrimHeapAsync(cts.Token);
|
||||
Task scheduled = restart is null ? Task.CompletedTask : WaitForRestartAsync(restart, time ?? TimeProvider.System, log, cts);
|
||||
try
|
||||
{
|
||||
await run(cts.Token);
|
||||
@@ -168,6 +170,38 @@ public static class ServiceShell
|
||||
{
|
||||
await cts.CancelAsync();
|
||||
await trimmer;
|
||||
await scheduled;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task WaitForRestartAsync(RestartController restart, TimeProvider time, INodeLog log, CancellationTokenSource cts)
|
||||
{
|
||||
while (!cts.IsCancellationRequested)
|
||||
{
|
||||
// 先取令牌、再取设置:中间被改动的话令牌会被取消,下一轮重新排
|
||||
CancellationToken changed = restart.ChangeToken;
|
||||
RestartSchedule? schedule = restart.Current;
|
||||
using CancellationTokenSource wait = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, changed);
|
||||
try
|
||||
{
|
||||
if (schedule is null)
|
||||
{
|
||||
await Task.Delay(Timeout.Infinite, wait.Token);
|
||||
continue;
|
||||
}
|
||||
|
||||
DateTimeOffset next = schedule.NextAfter(time.GetUtcNow() + RestartSchedule.MinimumUptime);
|
||||
log.Info("restart scheduled", ("at", next.ToString("O", System.Globalization.CultureInfo.InvariantCulture)), ("source", restart.IsLocal ? "local" : "panel"));
|
||||
await Task.Delay(next - time.GetUtcNow(), time, wait.Token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
continue; // 进程在退出,或者设置被改了:循环条件和下一轮会处理
|
||||
}
|
||||
|
||||
log.Info("stopping", ("result", "scheduled_restart"));
|
||||
await cts.CancelAsync();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user