using System.Diagnostics; using System.Text; using Azaion.CommonSecurity.DTO; using Azaion.CommonSecurity.DTO.Commands; using MessagePack; using Microsoft.Extensions.Options; using NetMQ; using NetMQ.Sockets; namespace Azaion.CommonSecurity.Services; public interface IInferenceClient { void Send(RemoteCommand create); T? Get(int retries = 24, int tryTimeoutSeconds = 5, CancellationToken ct = default) where T : class; byte[]? GetBytes(int retries = 24, int tryTimeoutSeconds = 5, CancellationToken ct = default); void Stop(); } public class InferenceClient : IInferenceClient { private readonly DealerSocket _dealer = new(); private readonly Guid _clientId = Guid.NewGuid(); private readonly InferenceClientConfig _inferenceClientConfig; public InferenceClient(IOptions config) { _inferenceClientConfig = config.Value; Start(); } private void Start() { try { using var process = new Process(); process.StartInfo = new ProcessStartInfo { FileName = SecurityConstants.EXTERNAL_INFERENCE_PATH, //Arguments = $"-e {credentials.Email} -p {credentials.Password} -f {apiConfig.ResourcesFolder}", //RedirectStandardOutput = true, //RedirectStandardError = true, //CreateNoWindow = true }; process.OutputDataReceived += (_, e) => { if (e.Data != null) Console.WriteLine(e.Data); }; process.ErrorDataReceived += (_, e) => { if (e.Data != null) Console.WriteLine(e.Data); }; process.Start(); } catch (Exception e) { Console.WriteLine(e); //throw; } _dealer.Options.Identity = Encoding.UTF8.GetBytes(_clientId.ToString("N")); _dealer.Connect($"tcp://{_inferenceClientConfig.ZeroMqHost}:{_inferenceClientConfig.ZeroMqPort}"); } public void Stop() { if (!_dealer.IsDisposed) { _dealer.SendFrame(MessagePackSerializer.Serialize(new RemoteCommand(CommandType.Exit))); _dealer.Close(); } } public void Send(RemoteCommand command) { _dealer.SendFrame(MessagePackSerializer.Serialize(command)); } public void SendString(string text) => Send(new RemoteCommand(CommandType.Load, MessagePackSerializer.Serialize(text))); public T? Get(int retries = 24, int tryTimeoutSeconds = 5, CancellationToken ct = default) where T : class { var bytes = GetBytes(retries, tryTimeoutSeconds, ct); return bytes != null ? MessagePackSerializer.Deserialize(bytes, cancellationToken: ct) : null; } public byte[]? GetBytes(int retries = 24, int tryTimeoutSeconds = 5, CancellationToken ct = default) { var tryNum = 0; while (!ct.IsCancellationRequested && tryNum++ < retries) { if (!_dealer.TryReceiveFrameBytes(TimeSpan.FromSeconds(tryTimeoutSeconds), out var bytes)) continue; return bytes; } if (!ct.IsCancellationRequested) throw new Exception($"Unable to get bytes after {tryNum} retries, {tryTimeoutSeconds} seconds each"); return null; } }