using System.Reactive.Concurrency; using System.Reactive.Linq; using System.Reactive.Subjects; using Docker.DotNet; using Docker.DotNet.Models; using MoonCore.Events; using MoonCore.Observability; using MoonlightServers.Daemon.Helpers; namespace MoonlightServers.Daemon.Services; public class DockerEventService : BackgroundService { private readonly ILogger Logger; private readonly DockerClient DockerClient; private readonly EventSource ContainerSource = new(); private readonly EventSource ImageSource = new(); private readonly EventSource NetworkSource = new(); public DockerEventService( ILogger logger, DockerClient dockerClient ) { Logger = logger; DockerClient = dockerClient; } public async ValueTask SubscribeContainerAsync(Func callback) => await ContainerSource.SubscribeAsync(callback); public async ValueTask SubscribeImageAsync(Func callback) => await ImageSource.SubscribeAsync(callback); public async ValueTask SubscribeNetworkAsync(Func callback) => await NetworkSource.SubscribeAsync(callback); protected override async Task ExecuteAsync(CancellationToken stoppingToken) { Logger.LogInformation("Starting docker event service"); while (!stoppingToken.IsCancellationRequested) { try { await DockerClient.System.MonitorEventsAsync( new ContainerEventsParameters(), new Progress(async message => { try { switch (message.Type) { case "container": await ContainerSource.InvokeAsync(message); break; case "image": await ImageSource.InvokeAsync(message); break; case "network": await NetworkSource.InvokeAsync(message); break; } } catch (Exception e) { Logger.LogError(e, "An error occured while processing docker event"); } }), stoppingToken ); } catch (TaskCanceledException) { // ignored } catch (Exception e) { Logger.LogError(e, "An error occured while listening for docker events: {message}", e.Message); } } Logger.LogInformation("Stopping docker event service"); } }