Errors sending to UI

notifying client of AI model conversion
This commit is contained in:
dzaitsev
2025-05-07 17:32:29 +03:00
committed by Alex Bezdieniezhnykh
42 changed files with 630 additions and 363 deletions
@@ -8,6 +8,7 @@
<ItemGroup>
<PackageReference Include="LazyCache.AspNetCore" Version="2.4.0" />
<PackageReference Include="MediatR" Version="12.4.1" />
<PackageReference Include="MessagePack" Version="3.1.0" />
<PackageReference Include="MessagePack.Annotations" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
@@ -3,7 +3,7 @@
namespace Azaion.CommonSecurity.DTO.Commands;
[MessagePackObject]
public class RemoteCommand(CommandType commandType, byte[]? data = null)
public class RemoteCommand(CommandType commandType, byte[]? data = null, string? message = null)
{
[Key("CommandType")]
public CommandType CommandType { get; set; } = commandType;
@@ -11,11 +11,14 @@ public class RemoteCommand(CommandType commandType, byte[]? data = null)
[Key("Data")]
public byte[]? Data { get; set; } = data;
[Key("Message")]
public string? Message { get; set; } = message;
public static RemoteCommand Create(CommandType commandType) =>
new(commandType);
public static RemoteCommand Create<T>(CommandType commandType, T data) where T : class =>
new(commandType, MessagePackSerializer.Serialize(data));
public static RemoteCommand Create<T>(CommandType commandType, T data, string? message = null) where T : class =>
new(commandType, MessagePackSerializer.Serialize(data), message);
}
[MessagePackObject]
@@ -34,7 +37,12 @@ public enum CommandType
None = 0,
Login = 10,
Load = 20,
DataBytes = 25,
Inference = 30,
InferenceData = 35,
StopInference = 40,
Exit = 100
AIAvailabilityCheck = 80,
AIAvailabilityResult = 85,
Error = 90,
Exit = 100,
}
@@ -10,7 +10,7 @@ public abstract class ExternalClientConfig
public class InferenceClientConfig : ExternalClientConfig
{
public string ApiUrl { get; set; }
public string ApiUrl { get; set; } = null!;
}
public class GpsDeniedClientConfig : ExternalClientConfig
@@ -1,4 +1,4 @@
namespace Azaion.Common.Extensions;
namespace Azaion.CommonSecurity.DTO;
public static class EnumerableExtensions
{
+1 -3
View File
@@ -1,6 +1,4 @@
using Azaion.Common.Extensions;
namespace Azaion.CommonSecurity.DTO;
namespace Azaion.CommonSecurity.DTO;
public enum RoleEnum
{
@@ -0,0 +1,3 @@
namespace Azaion.CommonSecurity.Exceptions;
public class BusinessException(string message) : Exception(message);
@@ -1,104 +0,0 @@
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<T>(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<InferenceClientConfig> config)
{
_inferenceClientConfig = config.Value;
Start();
_ = Task.Run(ProcessClientCommands);
}
private void Start()
{
try
{
using var process = new Process();
process.StartInfo = new ProcessStartInfo
{
FileName = SecurityConstants.EXTERNAL_INFERENCE_PATH,
Arguments = $"--port {_inferenceClientConfig.ZeroMqPort} --api {_inferenceClientConfig.ApiUrl}",
//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}");
}
private async Task ProcessClientCommands()
{
//TODO: implement always on ready to client's requests. Utilize RemoteCommand
await Task.CompletedTask;
}
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 T? Get<T>(int retries = 24, int tryTimeoutSeconds = 5, CancellationToken ct = default) where T : class
{
var bytes = GetBytes(retries, tryTimeoutSeconds, ct);
return bytes != null ? MessagePackSerializer.Deserialize<T>(bytes, cancellationToken: ct) : null;
}
public byte[]? GetBytes(int retries = 24, int tryTimeoutSeconds = 5, CancellationToken ct = default)
{
var tryNum = 0;
while (!ct.IsCancellationRequested && tryNum < retries)
{
tryNum++;
if (!_dealer.TryReceiveFrameBytes(TimeSpan.FromSeconds(tryTimeoutSeconds), out var bytes))
continue;
return bytes;
}
if (!ct.IsCancellationRequested)
throw new Exception($"Unable to get bytes after {tryNum - 1} retries, {tryTimeoutSeconds} seconds each");
return null;
}
}
@@ -1,22 +1,8 @@
using Azaion.CommonSecurity.DTO.Commands;
using Microsoft.Extensions.DependencyInjection;
namespace Azaion.CommonSecurity.Services;
public interface IResourceLoader
{
MemoryStream LoadFile(string fileName, string? folder = null);
}
public class ResourceLoader([FromKeyedServices(SecurityConstants.EXTERNAL_INFERENCE_PATH)] IInferenceClient inferenceClient) : IResourceLoader
{
public MemoryStream LoadFile(string fileName, string? folder = null)
{
inferenceClient.Send(RemoteCommand.Create(CommandType.Load, new LoadFileData(fileName, folder)));
var bytes = inferenceClient.GetBytes(2, 3);
if (bytes == null)
throw new Exception($"Unable to receive {fileName}");
return new MemoryStream(bytes);
}
MemoryStream LoadFile(string fileName, string? folder, TimeSpan? timeout = null);
}