using System; using System.IO.Pipes; using System.Threading; using System.Threading.Tasks; using MxGateway.Worker.Bootstrap; namespace MxGateway.Worker.Ipc; public sealed class WorkerPipeClient : IWorkerPipeClient { public const int DefaultConnectTimeoutMilliseconds = 30000; private readonly int _connectTimeoutMilliseconds; public WorkerPipeClient() : this(DefaultConnectTimeoutMilliseconds) { } public WorkerPipeClient(int connectTimeoutMilliseconds) { if (connectTimeoutMilliseconds <= 0) { throw new ArgumentOutOfRangeException( nameof(connectTimeoutMilliseconds), "Worker pipe connect timeout must be greater than zero."); } _connectTimeoutMilliseconds = connectTimeoutMilliseconds; } public async Task RunAsync( WorkerOptions options, CancellationToken cancellationToken = default) { if (options is null) { throw new ArgumentNullException(nameof(options)); } WorkerFrameProtocolOptions frameOptions = new(options); using NamedPipeClientStream pipe = new( ".", options.PipeName, PipeDirection.InOut, PipeOptions.Asynchronous); await ConnectAsync(pipe, cancellationToken).ConfigureAwait(false); WorkerPipeSession session = new(pipe, frameOptions); await session.CompleteStartupHandshakeAsync(cancellationToken).ConfigureAwait(false); } private Task ConnectAsync( NamedPipeClientStream pipe, CancellationToken cancellationToken) { return Task.Run( () => { cancellationToken.ThrowIfCancellationRequested(); pipe.Connect(_connectTimeoutMilliseconds); }, cancellationToken); } }