using Docker.DotNet; using Docker.DotNet.Models; using MoonlightServers.Daemon.ServerSystem.Implementations.Docker.Events; namespace MoonlightServers.Daemon.ServerSystem.Implementations.Docker; public class DockerEventService : BackgroundService { public event Func? OnContainerDied; private readonly ILogger Logger; private readonly DockerClient DockerClient; public DockerEventService( ILogger logger, DockerClient dockerClient ) { Logger = logger; DockerClient = dockerClient; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { Logger.LogTrace("Starting up docker event monitor"); while (!stoppingToken.IsCancellationRequested) { try { Logger.LogTrace("Monitoring events"); await DockerClient.System.MonitorEventsAsync( new ContainerEventsParameters(), new Progress(OnEventAsync), stoppingToken ); } catch (OperationCanceledException) { // ignored } catch (Exception e) { Logger.LogError(e, "An error occured while processing container event monitoring"); } } Logger.LogTrace("Closed docker event monitor"); } private async void OnEventAsync(Message message) { try { switch (message.Type) { case "container": var containerId = message.Actor.ID; switch (message.Action) { case "die": if ( !message.Actor.Attributes.TryGetValue("exitCode", out var exitCodeStr) || !int.TryParse(exitCodeStr, out var exitCode) ) { return; } if (OnContainerDied != null) await OnContainerDied.Invoke(new ContainerDieEvent(containerId, exitCode)); return; } break; } } catch (Exception e) { Logger.LogError( e, "An error occured while handling event {type} for {action}", message.Type, message.Action ); } } }