Added ability to bulk start servers

This commit is contained in:
Pat Hartl 2023-08-31 21:00:47 -05:00
parent c248ecc4f8
commit 685f7bf91d
3 changed files with 99 additions and 19 deletions

View file

@ -58,6 +58,8 @@
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
Server = await ServerService.Get(ServerId); Server = await ServerService.Get(ServerId);
ServerProcessService.OnStatusUpdate += OnStatusUpdate;
} }
protected override void OnAfterRender(bool firstRender) protected override void OnAfterRender(bool firstRender)
@ -73,26 +75,34 @@
} }
} }
private void OnStatusUpdate(object sender, ServerStatusUpdateEventArgs args)
{
if (args?.Server?.Id == ServerId)
{
Status = args.Status;
StateHasChanged();
if (Status == ServerProcessStatus.Error)
{
MessageService.Error("There was an unexpected error while trying to start the server.");
}
}
}
private async Task Start() private async Task Start()
{ {
try try
{ {
Status = ServerProcessStatus.Starting;
await ServerProcessService.StartServerAsync(Server); await ServerProcessService.StartServerAsync(Server);
} }
catch (Exception ex) catch (Exception ex)
{ {
Status = ServerProcessStatus.Error;
await MessageService.Error("There was an unexpected error while trying to start the server."); await MessageService.Error("There was an unexpected error while trying to start the server.");
} }
} }
private void Stop() private void Stop()
{ {
Status = ServerProcessStatus.Stopping;
ServerProcessService.StopServer(Server); ServerProcessService.StopServer(Server);
} }

View file

@ -10,6 +10,15 @@
<PageHeader Title="Servers"> <PageHeader Title="Servers">
<PageHeaderExtra> <PageHeaderExtra>
<Space Direction="DirectionVHType.Horizontal"> <Space Direction="DirectionVHType.Horizontal">
@if (SelectedServers != null && SelectedServers.Count() > 0)
{
<SpaceItem>
<Button Type="@ButtonType.Primary" OnClick="() => StartServers()">Start</Button>
<Popconfirm OnConfirm="() => StopServers()" Title="Are you sure you want to kill these server processes?">
<Button Danger Type="@ButtonType.Primary">Stop</Button>
</Popconfirm>
</SpaceItem>
}
<SpaceItem> <SpaceItem>
<Search Placeholder="Search" @bind-Value="Search" BindOnInput DebounceMilliseconds="150" OnChange="() => LoadData()" /> <Search Placeholder="Search" @bind-Value="Search" BindOnInput DebounceMilliseconds="150" OnChange="() => LoadData()" />
</SpaceItem> </SpaceItem>
@ -20,7 +29,8 @@
</PageHeaderExtra> </PageHeaderExtra>
</PageHeader> </PageHeader>
<Table TItem="Server" DataSource="@Servers" Loading="@Loading" PageSize="25"> <Table TItem="Server" DataSource="@Servers" Loading="@Loading" PageSize="25" @bind-SelectedRows="SelectedServers">
<Selection Key="@(context.Id.ToString())" />
<PropertyColumn Property="s => s.Name" Sortable /> <PropertyColumn Property="s => s.Name" Sortable />
<PropertyColumn Property="s => s.Game"> <PropertyColumn Property="s => s.Game">
<Image Src="@GetIcon(context.Game)" Height="32" Width="32" Preview="false"></Image> <Image Src="@GetIcon(context.Game)" Height="32" Width="32" Preview="false"></Image>
@ -56,6 +66,8 @@
string Search = ""; string Search = "";
IEnumerable<Server> SelectedServers;
protected override void OnAfterRender(bool firstRender) protected override void OnAfterRender(bool firstRender)
{ {
if (firstRender) if (firstRender)
@ -102,4 +114,30 @@
{ {
return $"/api/Games/{game?.Id}/Icon.png"; return $"/api/Games/{game?.Id}/Icon.png";
} }
private async Task StartServers()
{
foreach (var server in SelectedServers)
{
try
{
var status = ServerProcessService.GetStatus(server);
if (status == ServerProcessStatus.Stopped || status == ServerProcessStatus.Error)
{
await ServerProcessService.StartServerAsync(server);
}
}
catch { }
}
}
private void StopServers()
{
foreach (var server in SelectedServers)
{
if (ServerProcessService.GetStatus(server) == ServerProcessStatus.Running)
ServerProcessService.StopServer(server);
}
}
} }

View file

@ -33,6 +33,18 @@ namespace LANCommander.Services
} }
} }
public class ServerStatusUpdateEventArgs : EventArgs
{
public Server Server { get; private set; }
public ServerProcessStatus Status { get; private set; }
public ServerStatusUpdateEventArgs(Server server, ServerProcessStatus status)
{
Server = server;
Status = status;
}
}
public class LogFileMonitor : IDisposable public class LogFileMonitor : IDisposable
{ {
private ManualResetEvent Latch; private ManualResetEvent Latch;
@ -122,6 +134,9 @@ namespace LANCommander.Services
public delegate void OnLogHandler(object sender, ServerLogEventArgs e); public delegate void OnLogHandler(object sender, ServerLogEventArgs e);
public event OnLogHandler OnLog; public event OnLogHandler OnLog;
public delegate void OnStatusUpdateHandler(object sender, ServerStatusUpdateEventArgs e);
public event OnStatusUpdateHandler OnStatusUpdate;
private IHubContext<GameServerHub> HubContext; private IHubContext<GameServerHub> HubContext;
public ServerProcessService(IHubContext<GameServerHub> hubContext) public ServerProcessService(IHubContext<GameServerHub> hubContext)
@ -157,27 +172,42 @@ namespace LANCommander.Services
}); });
} }
process.Start(); try
if (!process.StartInfo.UseShellExecute)
{ {
process.BeginErrorReadLine(); OnStatusUpdate?.Invoke(this, new ServerStatusUpdateEventArgs(server, ServerProcessStatus.Starting));
process.BeginOutputReadLine();
process.Start();
if (!process.StartInfo.UseShellExecute)
{
process.BeginErrorReadLine();
process.BeginOutputReadLine();
}
Processes[server.Id] = process;
foreach (var logFile in server.ServerConsoles.Where(sc => sc.Type == ServerConsoleType.LogFile))
{
StartMonitoringLog(logFile, server);
}
OnStatusUpdate?.Invoke(this, new ServerStatusUpdateEventArgs(server, ServerProcessStatus.Running));
await process.WaitForExitAsync();
} }
catch (Exception ex)
Processes[server.Id] = process;
foreach (var logFile in server.ServerConsoles.Where(sc => sc.Type == ServerConsoleType.LogFile))
{ {
StartMonitoringLog(logFile, server); OnStatusUpdate?.Invoke(this, new ServerStatusUpdateEventArgs(server, ServerProcessStatus.Error));
}
await process.WaitForExitAsync(); Logger.Error(ex, "Could not start server process");
}
} }
public void StopServer(Server server) public void StopServer(Server server)
{ {
OnStatusUpdate?.Invoke(this, new ServerStatusUpdateEventArgs(server, ServerProcessStatus.Stopping));
if (Processes.ContainsKey(server.Id)) if (Processes.ContainsKey(server.Id))
{ {
var process = Processes[server.Id]; var process = Processes[server.Id];
@ -190,6 +220,8 @@ namespace LANCommander.Services
LogFileMonitors[server.Id].Dispose(); LogFileMonitors[server.Id].Dispose();
LogFileMonitors.Remove(server.Id); LogFileMonitors.Remove(server.Id);
} }
OnStatusUpdate?.Invoke(this, new ServerStatusUpdateEventArgs(server, ServerProcessStatus.Stopped));
} }
private void StartMonitoringLog(ServerConsole log, Server server) private void StartMonitoringLog(ServerConsole log, Server server)