using System.Reactive.Concurrency; using System.Reactive.Linq; using System.Reactive.Subjects; using Docker.DotNet; using Docker.DotNet.Models; using MoonCore.Observability; using MoonlightServers.Daemon.Helpers; namespace MoonlightServers.Daemon.Services; public class DockerEventService : BackgroundService { private readonly ILogger Logger; private readonly DockerClient DockerClient; public IAsyncObservable OnContainerEvent => OnContainerSubject; public IAsyncObservable OnImageEvent => OnImageSubject; public IAsyncObservable OnNetworkEvent => OnNetworkSubject; private readonly EventSubject OnContainerSubject = new(); private readonly EventSubject OnImageSubject = new(); private readonly EventSubject OnNetworkSubject = new(); public DockerEventService( ILogger logger, DockerClient dockerClient ) { Logger = logger; DockerClient = dockerClient; } 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 OnContainerSubject.OnNextAsync(message); break; case "image": await OnImageSubject.OnNextAsync(message); break; case "network": await OnNetworkSubject.OnNextAsync(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"); } public override void Dispose() { base.Dispose(); OnContainerSubject.Dispose(); OnImageSubject.Dispose(); OnNetworkSubject.Dispose(); } }