mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 10:46:30 +00:00
consolidate CommonSecurity to Common.dll
This commit is contained in:
@@ -7,7 +7,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageReference Include="CsvHelper" Version="33.0.1" />
|
||||
<PackageReference Include="LazyCache" Version="2.4.0" />
|
||||
<PackageReference Include="linq2db.SQLite" Version="5.4.1" />
|
||||
<PackageReference Include="MediatR" Version="12.5.0" />
|
||||
<PackageReference Include="MessagePack" Version="3.1.0" />
|
||||
@@ -15,17 +17,15 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.5" />
|
||||
<PackageReference Include="NetMQ" Version="4.0.1.16" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Polly" Version="8.5.2" />
|
||||
<PackageReference Include="RabbitMQ.Stream.Client" Version="1.8.9" />
|
||||
<PackageReference Include="Serilog" Version="4.3.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
|
||||
<PackageReference Include="Stub.System.Data.SQLite.Core.NetStandard" Version="1.0.119" />
|
||||
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.119" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="5.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Azaion.CommonSecurity\Azaion.CommonSecurity.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using Azaion.Common.DTO;
|
||||
using Azaion.Common.Extensions;
|
||||
using Azaion.CommonSecurity.DTO;
|
||||
|
||||
namespace Azaion.Common.Controls;
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Runtime.CompilerServices;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Azaion.Common.Database;
|
||||
using Azaion.Common.Extensions;
|
||||
using Azaion.CommonSecurity.DTO;
|
||||
|
||||
namespace Azaion.Common.DTO;
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using CommandLine;
|
||||
using MessagePack;
|
||||
|
||||
namespace Azaion.Common.DTO;
|
||||
|
||||
[MessagePackObject]
|
||||
public class ApiCredentials : EventArgs
|
||||
{
|
||||
[Key(nameof(Email))]
|
||||
[Option('e', "email", Required = true, HelpText = "User Email")]
|
||||
public string Email { get; set; } = null!;
|
||||
|
||||
[Key(nameof(Password))]
|
||||
[Option('p', "pass", Required = true, HelpText = "User Password")]
|
||||
public string Password { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Azaion.Common.DTO;
|
||||
|
||||
public class BusinessExceptionDto
|
||||
{
|
||||
public int ErrorCode { get; set; }
|
||||
public string Message { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Azaion.CommonSecurity;
|
||||
using Azaion.CommonSecurity.DTO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Azaion.Common.DTO.Config;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Azaion.Common.DTO;
|
||||
|
||||
public class DirectoriesConfig
|
||||
|
||||
{
|
||||
public string ApiResourcesDirectory { get; set; } = null!;
|
||||
|
||||
public string VideosDirectory { get; set; } = null!;
|
||||
public string LabelsDirectory { get; set; } = null!;
|
||||
public string ImagesDirectory { get; set; } = null!;
|
||||
public string ResultsDirectory { get; set; } = null!;
|
||||
public string ThumbnailsDirectory { get; set; } = null!;
|
||||
|
||||
public string GpsSatDirectory { get; set; } = null!;
|
||||
public string GpsRouteDirectory { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Azaion.Common.DTO;
|
||||
|
||||
public abstract class ExternalClientConfig
|
||||
{
|
||||
public string ZeroMqHost { get; set; } = "";
|
||||
public int ZeroMqPort { get; set; }
|
||||
}
|
||||
|
||||
public class LoaderClientConfig : ExternalClientConfig
|
||||
{
|
||||
public string ApiUrl { get; set; } = null!;
|
||||
}
|
||||
|
||||
public class InferenceClientConfig : ExternalClientConfig
|
||||
{
|
||||
public string ApiUrl { get; set; } = null!;
|
||||
}
|
||||
|
||||
public class GpsDeniedClientConfig : ExternalClientConfig
|
||||
{
|
||||
public int ZeroMqReceiverPort { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Azaion.Common.DTO;
|
||||
|
||||
public static class EnumerableExtensions
|
||||
{
|
||||
public static bool In<T>(this T obj, params T[] objects) =>
|
||||
objects.Contains(obj);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Azaion.Common.DTO;
|
||||
|
||||
public class InitConfig
|
||||
{
|
||||
public LoaderClientConfig LoaderClientConfig { get; set; } = null!;
|
||||
public InferenceClientConfig InferenceClientConfig { get; set; } = null!;
|
||||
public GpsDeniedClientConfig GpsDeniedClientConfig { get; set; } = null!;
|
||||
public DirectoriesConfig DirectoriesConfig { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Azaion.Common.DTO;
|
||||
|
||||
public class LoginResponse
|
||||
{
|
||||
public string Token { get; set; } = null!;
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Azaion.Common.Database;
|
||||
using Azaion.CommonSecurity.DTO;
|
||||
|
||||
namespace Azaion.Common.DTO.Queue;
|
||||
using MessagePack;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
using MessagePack;
|
||||
|
||||
namespace Azaion.Common.DTO;
|
||||
|
||||
[MessagePackObject]
|
||||
public class RemoteCommand(CommandType commandType, byte[]? data = null, string? message = null)
|
||||
{
|
||||
[Key("CommandType")]
|
||||
public CommandType CommandType { get; set; } = commandType;
|
||||
|
||||
[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, string? message = null) where T : class =>
|
||||
new(commandType, MessagePackSerializer.Serialize(data), message);
|
||||
|
||||
public override string ToString() => $"({CommandType.ToString().ToUpper()}: Data: {Data?.Length ?? 0} bytes. Message: {Message})";
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class LoadFileData(string filename, string? folder = null )
|
||||
{
|
||||
[Key(nameof(Folder))]
|
||||
public string? Folder { get; set; } = folder;
|
||||
|
||||
[Key(nameof(Filename))]
|
||||
public string Filename { get; set; } = filename;
|
||||
}
|
||||
|
||||
|
||||
public enum CommandType
|
||||
{
|
||||
None = 0,
|
||||
Ok = 3,
|
||||
Login = 10,
|
||||
ListRequest = 15,
|
||||
ListFiles = 18,
|
||||
Load = 20,
|
||||
LoadBigSmall = 22,
|
||||
UploadBigSmall = 24,
|
||||
DataBytes = 25,
|
||||
Inference = 30,
|
||||
InferenceData = 35,
|
||||
StopInference = 40,
|
||||
AIAvailabilityCheck = 80,
|
||||
AIAvailabilityResult = 85,
|
||||
Error = 90,
|
||||
Exit = 100,
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Azaion.Common.DTO;
|
||||
|
||||
public enum RoleEnum
|
||||
{
|
||||
None = 0,
|
||||
Operator = 10, //only annotator is available. Could send annotations to queue.
|
||||
Validator = 20, //annotator + dataset explorer. This role allows to receive annotations from the queue.
|
||||
CompanionPC = 30,
|
||||
Admin = 40, //
|
||||
ApiAdmin = 1000 //everything
|
||||
}
|
||||
|
||||
public static class RoleEnumExtensions
|
||||
{
|
||||
public static bool IsValidator(this RoleEnum role) =>
|
||||
role.In(RoleEnum.Validator, RoleEnum.Admin, RoleEnum.ApiAdmin);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace Azaion.Common.DTO;
|
||||
|
||||
public class User
|
||||
{
|
||||
public string Id { get; set; } = "";
|
||||
public string Email { get; set; } = "";
|
||||
public RoleEnum Role { get; set; }
|
||||
public UserConfig? UserConfig { get; set; } = null!;
|
||||
}
|
||||
|
||||
public class UserConfig
|
||||
{
|
||||
public UserQueueOffsets? QueueOffsets { get; set; } = new();
|
||||
}
|
||||
|
||||
public class UserQueueOffsets
|
||||
{
|
||||
public ulong AnnotationsOffset { get; set; }
|
||||
public ulong AnnotationsConfirmOffset { get; set; }
|
||||
public ulong AnnotationsCommandsOffset { get; set; }
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
using Azaion.Common.DTO;
|
||||
using Azaion.Common.DTO.Config;
|
||||
using Azaion.Common.DTO.Queue;
|
||||
using Azaion.CommonSecurity.DTO;
|
||||
using MessagePack;
|
||||
|
||||
namespace Azaion.Common.Database;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Azaion.CommonSecurity.Exceptions;
|
||||
|
||||
public class BusinessException(string message) : Exception(message);
|
||||
@@ -0,0 +1,79 @@
|
||||
using System.IO;
|
||||
using Azaion.Common.DTO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Azaion.Common;
|
||||
|
||||
public class SecurityConstants
|
||||
{
|
||||
public const string CONFIG_PATH = "config.json";
|
||||
|
||||
private const string DEFAULT_API_URL = "https://api.azaion.com";
|
||||
|
||||
#region ExternalClientsConfig
|
||||
|
||||
private const string DEFAULT_ZMQ_LOADER_HOST = "127.0.0.1";
|
||||
private const int DEFAULT_ZMQ_LOADER_PORT = 5025;
|
||||
|
||||
public const string EXTERNAL_LOADER_PATH = "azaion-loader.exe";
|
||||
public const string EXTERNAL_INFERENCE_PATH = "azaion-inference.exe";
|
||||
public const string EXTERNAL_GPS_DENIED_FOLDER = "gps-denied";
|
||||
public static readonly string ExternalGpsDeniedPath = Path.Combine(EXTERNAL_GPS_DENIED_FOLDER, "image-matcher.exe");
|
||||
|
||||
public const string DEFAULT_ZMQ_INFERENCE_HOST = "127.0.0.1";
|
||||
public const int DEFAULT_ZMQ_INFERENCE_PORT = 5227;
|
||||
|
||||
public const string DEFAULT_ZMQ_GPS_DENIED_HOST = "127.0.0.1";
|
||||
public const int DEFAULT_ZMQ_GPS_DENIED_PORT = 5227;
|
||||
|
||||
# region Cache keys
|
||||
|
||||
public const string CURRENT_USER_CACHE_KEY = "CurrentUser";
|
||||
public const string HARDWARE_INFO_KEY = "HardwareInfo";
|
||||
|
||||
# endregion
|
||||
|
||||
public static readonly InitConfig DefaultInitConfig = new()
|
||||
{
|
||||
LoaderClientConfig = new LoaderClientConfig
|
||||
{
|
||||
ZeroMqHost = DEFAULT_ZMQ_LOADER_HOST,
|
||||
ZeroMqPort = DEFAULT_ZMQ_LOADER_PORT,
|
||||
ApiUrl = DEFAULT_API_URL
|
||||
},
|
||||
InferenceClientConfig = new InferenceClientConfig
|
||||
{
|
||||
ZeroMqHost = DEFAULT_ZMQ_INFERENCE_HOST,
|
||||
ZeroMqPort = DEFAULT_ZMQ_INFERENCE_PORT,
|
||||
ApiUrl = DEFAULT_API_URL
|
||||
},
|
||||
GpsDeniedClientConfig = new GpsDeniedClientConfig
|
||||
{
|
||||
ZeroMqHost = DEFAULT_ZMQ_GPS_DENIED_HOST,
|
||||
ZeroMqPort = DEFAULT_ZMQ_GPS_DENIED_PORT
|
||||
},
|
||||
DirectoriesConfig = new DirectoriesConfig
|
||||
{
|
||||
ApiResourcesDirectory = ""
|
||||
}
|
||||
};
|
||||
#endregion ExternalClientsConfig
|
||||
|
||||
public static InitConfig ReadInitConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(CONFIG_PATH))
|
||||
throw new FileNotFoundException(CONFIG_PATH);
|
||||
var configStr = File.ReadAllText(CONFIG_PATH);
|
||||
var config = JsonConvert.DeserializeObject<InitConfig>(configStr);
|
||||
|
||||
return config ?? DefaultInitConfig;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
return DefaultInitConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,6 @@ using Azaion.Common.DTO.Config;
|
||||
using Azaion.Common.DTO.Queue;
|
||||
using Azaion.Common.Events;
|
||||
using Azaion.Common.Extensions;
|
||||
using Azaion.CommonSecurity.DTO;
|
||||
using Azaion.CommonSecurity.Services;
|
||||
using LinqToDB;
|
||||
using LinqToDB.Data;
|
||||
using MediatR;
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using Azaion.Common.DTO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Azaion.Common.Services;
|
||||
|
||||
public interface IAzaionApi
|
||||
{
|
||||
ApiCredentials Credentials { get; }
|
||||
User CurrentUser { get; }
|
||||
void UpdateOffsets(UserQueueOffsets offsets);
|
||||
//Stream GetResource(string filename, string folder);
|
||||
}
|
||||
|
||||
public class AzaionApi(HttpClient client, ICache cache, ApiCredentials credentials) : IAzaionApi
|
||||
{
|
||||
private string _jwtToken = null!;
|
||||
const string APP_JSON = "application/json";
|
||||
public ApiCredentials Credentials => credentials;
|
||||
|
||||
public User CurrentUser
|
||||
{
|
||||
get
|
||||
{
|
||||
var user = cache.GetFromCache(SecurityConstants.CURRENT_USER_CACHE_KEY,
|
||||
() => Get<User>("currentUser"));
|
||||
if (user == null)
|
||||
throw new Exception("Can't get current user");
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateOffsets(UserQueueOffsets offsets)
|
||||
{
|
||||
Put($"/users/queue-offsets/set", new
|
||||
{
|
||||
Email = CurrentUser.Email,
|
||||
Offsets = offsets
|
||||
});
|
||||
}
|
||||
|
||||
private HttpResponseMessage Send(HttpRequestMessage request)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_jwtToken))
|
||||
Authorize();
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _jwtToken);
|
||||
var response = client.Send(request);
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
Authorize();
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _jwtToken);
|
||||
response = client.Send(request);
|
||||
}
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
return response;
|
||||
|
||||
var stream = response.Content.ReadAsStream();
|
||||
var content = new StreamReader(stream).ReadToEnd();
|
||||
if (response.StatusCode == HttpStatusCode.Conflict)
|
||||
{
|
||||
var result = JsonConvert.DeserializeObject<BusinessExceptionDto>(content);
|
||||
throw new Exception($"Failed: {response.StatusCode}! Error Code: {result?.ErrorCode}. Message: {result?.Message}");
|
||||
}
|
||||
throw new Exception($"Failed: {response.StatusCode}! Result: {content}");
|
||||
}
|
||||
|
||||
private T? Get<T>(string url)
|
||||
{
|
||||
var response = Send(new HttpRequestMessage(HttpMethod.Get, url));
|
||||
var stream = response.Content.ReadAsStream();
|
||||
var json = new StreamReader(stream).ReadToEnd();
|
||||
return JsonConvert.DeserializeObject<T>(json);
|
||||
}
|
||||
|
||||
private void Put<T>(string url, T obj)
|
||||
{
|
||||
Send(new HttpRequestMessage(HttpMethod.Put, url)
|
||||
{
|
||||
Content = new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, APP_JSON)
|
||||
});
|
||||
}
|
||||
|
||||
private void Authorize()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(credentials.Email) || credentials.Password.Length == 0)
|
||||
throw new Exception("Email or password is empty! Please do EnterCredentials first!");
|
||||
|
||||
var payload = new
|
||||
{
|
||||
email = credentials.Email,
|
||||
password = credentials.Password
|
||||
};
|
||||
var content = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, APP_JSON);
|
||||
var message = new HttpRequestMessage(HttpMethod.Post, "login") { Content = content };
|
||||
var response = client.Send(message);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
throw new Exception($"EnterCredentials failed: {response.StatusCode}");
|
||||
|
||||
var stream = response.Content.ReadAsStream();
|
||||
var json = new StreamReader(stream).ReadToEnd();
|
||||
var result = JsonConvert.DeserializeObject<LoginResponse>(json);
|
||||
|
||||
if (string.IsNullOrEmpty(result?.Token))
|
||||
throw new Exception("JWT Token not found in response");
|
||||
|
||||
_jwtToken = result.Token;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using LazyCache;
|
||||
|
||||
namespace Azaion.Common.Services;
|
||||
|
||||
public interface ICache
|
||||
{
|
||||
T GetFromCache<T>(string key, Func<T> fetchFunc, TimeSpan? expiration = null);
|
||||
void Invalidate(string key);
|
||||
}
|
||||
|
||||
public class MemoryCache : ICache
|
||||
{
|
||||
private readonly IAppCache _cache = new CachingService();
|
||||
|
||||
public T GetFromCache<T>(string key, Func<T> fetchFunc, TimeSpan? expiration = null)
|
||||
{
|
||||
expiration ??= TimeSpan.FromHours(4);
|
||||
return _cache.GetOrAdd(key, entry =>
|
||||
{
|
||||
var result = fetchFunc();
|
||||
entry.AbsoluteExpirationRelativeToNow = expiration;
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
public void Invalidate(string key) => _cache.Remove(key);
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using Azaion.Common.Database;
|
||||
using Azaion.Common.DTO;
|
||||
using Azaion.Common.DTO.Config;
|
||||
using Azaion.Common.DTO.Queue;
|
||||
using Azaion.Common.Extensions;
|
||||
using Azaion.CommonSecurity.DTO;
|
||||
using Azaion.CommonSecurity.Services;
|
||||
using LinqToDB;
|
||||
using MessagePack;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.IO;
|
||||
using Azaion.CommonSecurity;
|
||||
using Azaion.CommonSecurity.DTO;
|
||||
using Azaion.Common.DTO;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Azaion.Common.Services;
|
||||
|
||||
@@ -9,7 +9,6 @@ using Azaion.Common.DTO;
|
||||
using Azaion.Common.DTO.Config;
|
||||
using Azaion.Common.DTO.Queue;
|
||||
using Azaion.Common.Extensions;
|
||||
using Azaion.CommonSecurity.DTO;
|
||||
using LinqToDB;
|
||||
using LinqToDB.Data;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Azaion.Common.DTO;
|
||||
using Azaion.Common.Events;
|
||||
using Azaion.CommonSecurity;
|
||||
using Azaion.CommonSecurity.DTO;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Azaion.Common.Database;
|
||||
using Azaion.Common.Extensions;
|
||||
using Azaion.CommonSecurity;
|
||||
using Azaion.CommonSecurity.DTO;
|
||||
using Azaion.CommonSecurity.DTO.Commands;
|
||||
using Azaion.CommonSecurity.Exceptions;
|
||||
using Azaion.CommonSecurity.Services;
|
||||
using Azaion.Common.DTO;
|
||||
using MessagePack;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NetMQ;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using Azaion.Common.Database;
|
||||
using Azaion.Common.DTO;
|
||||
using Azaion.Common.DTO.Config;
|
||||
using Azaion.Common.Events;
|
||||
using Azaion.Common.Extensions;
|
||||
using Azaion.CommonSecurity.DTO.Commands;
|
||||
using Azaion.CommonSecurity.Services;
|
||||
using MediatR;
|
||||
using MessagePack;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Azaion.Common.DTO;
|
||||
using MessagePack;
|
||||
using NetMQ;
|
||||
using NetMQ.Sockets;
|
||||
using Serilog;
|
||||
using Exception = System.Exception;
|
||||
|
||||
namespace Azaion.Common.Services;
|
||||
|
||||
public class LoaderClient(LoaderClientConfig config, ILogger logger, CancellationToken ct = default) : IDisposable
|
||||
{
|
||||
private readonly DealerSocket _dealer = new();
|
||||
private readonly Guid _clientId = Guid.NewGuid();
|
||||
|
||||
public void StartClient()
|
||||
{
|
||||
try
|
||||
{
|
||||
using var process = new Process();
|
||||
process.StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = SecurityConstants.EXTERNAL_LOADER_PATH,
|
||||
Arguments = $"--port {config.ZeroMqPort} --api {config.ApiUrl}",
|
||||
//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)
|
||||
{
|
||||
logger.Error(e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
_dealer.Options.Identity = Encoding.UTF8.GetBytes(_clientId.ToString("N"));
|
||||
_dealer.Connect($"tcp://{config.ZeroMqHost}:{config.ZeroMqPort}");
|
||||
}
|
||||
|
||||
public void Login(ApiCredentials credentials)
|
||||
{
|
||||
var result = SendCommand(RemoteCommand.Create(CommandType.Login, credentials));
|
||||
if (result.CommandType != CommandType.Ok)
|
||||
throw new Exception(result.Message);
|
||||
}
|
||||
|
||||
public MemoryStream LoadFile(string filename, string folder)
|
||||
{
|
||||
var result = SendCommand(RemoteCommand.Create(CommandType.Load, new LoadFileData(filename, folder)));
|
||||
if (result.Data?.Length == 0)
|
||||
throw new Exception($"Can't load {filename}. Returns 0 bytes");
|
||||
return new MemoryStream(result.Data!);
|
||||
}
|
||||
|
||||
private RemoteCommand SendCommand(RemoteCommand command, int retryCount = 50, int retryDelayMs = 800)
|
||||
{
|
||||
try
|
||||
{
|
||||
_dealer.SendFrame(MessagePackSerializer.Serialize(command));
|
||||
|
||||
var tryNum = 0;
|
||||
while (!ct.IsCancellationRequested && tryNum++ < retryCount)
|
||||
{
|
||||
if (!_dealer.TryReceiveFrameBytes(TimeSpan.FromMilliseconds(retryDelayMs), out var bytes))
|
||||
continue;
|
||||
var res = MessagePackSerializer.Deserialize<RemoteCommand>(bytes, cancellationToken: ct);
|
||||
if (res.CommandType == CommandType.Error)
|
||||
throw new Exception(res.Message);
|
||||
return res;
|
||||
}
|
||||
|
||||
throw new Exception($"Sent {command} {retryCount} times, with wait time {retryDelayMs}ms for each call. No response from client.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Error(e, e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_dealer.SendFrame(MessagePackSerializer.Serialize(new RemoteCommand(CommandType.Exit)));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_dealer.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ using Azaion.Common.DTO.Config;
|
||||
using Azaion.Common.Events;
|
||||
using Azaion.Common.Extensions;
|
||||
using Azaion.CommonSecurity;
|
||||
using Azaion.CommonSecurity.DTO;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
Reference in New Issue
Block a user