Implemented basic virtual disk support
This commit is contained in:
@@ -17,7 +17,7 @@ namespace MoonlightServers.Daemon.Services;
|
||||
[Singleton]
|
||||
public class ServerService : IHostedLifecycleService
|
||||
{
|
||||
private readonly Dictionary<int, Server> Servers = new();
|
||||
private readonly ConcurrentDictionary<int, Server> Servers = new();
|
||||
|
||||
private readonly RemoteService RemoteService;
|
||||
private readonly DockerClient DockerClient;
|
||||
@@ -58,82 +58,9 @@ public class ServerService : IHostedLifecycleService
|
||||
else
|
||||
await Initialize(serverId);
|
||||
}
|
||||
|
||||
public async Task InitializeAll()
|
||||
{
|
||||
var initialPage = await RemoteService.GetServers(0, 1);
|
||||
|
||||
const int pageSize = 25;
|
||||
var pages = (initialPage.TotalItems == 0 ? 0 : (initialPage.TotalItems - 1) / pageSize) +
|
||||
1; // The +1 is to handle the pages starting at 0
|
||||
|
||||
// Create and fill a queue with pages to initialize
|
||||
var batchesLeft = new ConcurrentQueue<int>();
|
||||
|
||||
for (var i = 0; i < pages; i++)
|
||||
batchesLeft.Enqueue(i);
|
||||
|
||||
var tasksCount = pages > 5 ? 5 : pages;
|
||||
var tasks = new List<Task>();
|
||||
|
||||
Logger.LogInformation(
|
||||
"Starting initialization for {count} server(s) with {tasksCount} worker(s)",
|
||||
initialPage.TotalItems,
|
||||
tasksCount
|
||||
);
|
||||
|
||||
for (var i = 0; i < tasksCount; i++)
|
||||
{
|
||||
var id = i + 0;
|
||||
var task = Task.Run(() => BatchRunner(batchesLeft, id));
|
||||
|
||||
tasks.Add(task);
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
Logger.LogInformation("Initialization completed");
|
||||
}
|
||||
|
||||
private async Task BatchRunner(ConcurrentQueue<int> queue, int id)
|
||||
{
|
||||
while (!queue.IsEmpty)
|
||||
{
|
||||
if (!queue.TryDequeue(out var page))
|
||||
continue;
|
||||
|
||||
await InitializeBatch(page, 25);
|
||||
|
||||
Logger.LogDebug("Worker {id}: Finished initialization of page {page}", id, page);
|
||||
}
|
||||
|
||||
Logger.LogDebug("Worker {id}: Finished", id);
|
||||
}
|
||||
|
||||
private async Task InitializeBatch(int page, int pageSize)
|
||||
{
|
||||
var servers = await RemoteService.GetServers(page, pageSize);
|
||||
|
||||
var configurations = servers.Items
|
||||
.Select(x => x.ToServerConfiguration())
|
||||
.ToArray();
|
||||
|
||||
foreach (var configuration in configurations)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Sync(configuration.Id, configuration);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError(
|
||||
"An unhandled error occured while initializing server {id}: {e}",
|
||||
configuration.Id,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Server? Find(int serverId)
|
||||
=> Servers.GetValueOrDefault(serverId);
|
||||
|
||||
public async Task Initialize(int serverId)
|
||||
{
|
||||
@@ -143,9 +70,6 @@ public class ServerService : IHostedLifecycleService
|
||||
await Initialize(configuration);
|
||||
}
|
||||
|
||||
public Server? Find(int serverId)
|
||||
=> Servers.GetValueOrDefault(serverId);
|
||||
|
||||
public async Task Initialize(ServerConfiguration configuration)
|
||||
{
|
||||
var serverScope = ServiceProvider.CreateScope();
|
||||
@@ -235,16 +159,95 @@ public class ServerService : IHostedLifecycleService
|
||||
|
||||
private async Task DeleteServer_Unhandled(Server server)
|
||||
{
|
||||
await server.DisposeAsync();
|
||||
await server.Delete();
|
||||
await server.DisposeAsync();
|
||||
|
||||
lock (Servers)
|
||||
Servers.Remove(server.Configuration.Id);
|
||||
Servers.Remove(server.Configuration.Id, out _);
|
||||
}
|
||||
|
||||
#region Batch Initialization
|
||||
|
||||
public async Task InitializeAll()
|
||||
{
|
||||
var initialPage = await RemoteService.GetServers(0, 1);
|
||||
|
||||
const int pageSize = 25;
|
||||
var pages = (initialPage.TotalItems == 0 ? 0 : (initialPage.TotalItems - 1) / pageSize) +
|
||||
1; // The +1 is to handle the pages starting at 0
|
||||
|
||||
// Create and fill a queue with pages to initialize
|
||||
var batchesLeft = new ConcurrentQueue<int>();
|
||||
|
||||
for (var i = 0; i < pages; i++)
|
||||
batchesLeft.Enqueue(i);
|
||||
|
||||
var tasksCount = pages > 5 ? 5 : pages;
|
||||
var tasks = new List<Task>();
|
||||
|
||||
Logger.LogInformation(
|
||||
"Starting initialization for {count} server(s) with {tasksCount} worker(s)",
|
||||
initialPage.TotalItems,
|
||||
tasksCount
|
||||
);
|
||||
|
||||
for (var i = 0; i < tasksCount; i++)
|
||||
{
|
||||
var id = i + 0;
|
||||
var task = Task.Run(() => BatchRunner(batchesLeft, id));
|
||||
|
||||
tasks.Add(task);
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
Logger.LogInformation("Initialization completed");
|
||||
}
|
||||
|
||||
private async Task BatchRunner(ConcurrentQueue<int> queue, int id)
|
||||
{
|
||||
while (!queue.IsEmpty)
|
||||
{
|
||||
if (!queue.TryDequeue(out var page))
|
||||
continue;
|
||||
|
||||
await InitializeBatch(page, 25);
|
||||
|
||||
Logger.LogDebug("Worker {id}: Finished initialization of page {page}", id, page);
|
||||
}
|
||||
|
||||
Logger.LogDebug("Worker {id}: Finished", id);
|
||||
}
|
||||
|
||||
private async Task InitializeBatch(int page, int pageSize)
|
||||
{
|
||||
var servers = await RemoteService.GetServers(page, pageSize);
|
||||
|
||||
var configurations = servers.Items
|
||||
.Select(x => x.ToServerConfiguration())
|
||||
.ToArray();
|
||||
|
||||
foreach (var configuration in configurations)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Sync(configuration.Id, configuration);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError(
|
||||
"An unhandled error occured while initializing server {id}: {e}",
|
||||
configuration.Id,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Docker Monitoring
|
||||
|
||||
private async Task MonitorContainers()
|
||||
private Task StartContainerMonitoring()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
@@ -296,6 +299,8 @@ public class ServerService : IHostedLifecycleService
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -310,7 +315,7 @@ public class ServerService : IHostedLifecycleService
|
||||
|
||||
public async Task StartedAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await MonitorContainers();
|
||||
await StartContainerMonitoring();
|
||||
|
||||
await InitializeAll();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user