Skip to content

Commit

Permalink
1
Browse files Browse the repository at this point in the history
  • Loading branch information
akbaramd committed Dec 14, 2024
1 parent 9d1308f commit 9d8b84d
Show file tree
Hide file tree
Showing 109 changed files with 2,448 additions and 236 deletions.
45 changes: 45 additions & 0 deletions New/Payeh.SharedKernel/Consul/ConsulExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Consul;

namespace Payeh.SharedKernel.Consul;

public static class ConsulServiceExtensions
{
// Extension method to add Consul registration background service
public static IServiceCollection AddConsulServiceRegistration(
this IServiceCollection services,
string serviceId,
string serviceName,
string host , // میزبان (Host) پیش‌فرض
int port ) // پورت پیش‌فرض
{

// افزودن سرویس Consul Registration
services.AddSingleton<IHostedService>(serviceProvider =>
new ConsulRegistrationBackgroundService(
serviceProvider.GetRequiredService<IConsulClient>(), // سرویس ConsulClient
serviceProvider.GetRequiredService<ILogger<ConsulRegistrationBackgroundService>>() ,
serviceId,
serviceName,
host,
port
));

return services;
}

// Extension method to configure Consul client
public static IServiceCollection AddConsulClient(
this IServiceCollection services,
Action<ConsulClientConfiguration> consulClientConfiguration)
{
services.AddSingleton<IConsulService, ConsulService>();
services.AddSingleton<IConsulClient>(provider =>
{
var config = new ConsulClientConfiguration();
consulClientConfiguration(config);
return new ConsulClient(config);
});

return services;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using Consul;

namespace Payeh.SharedKernel.Consul;

public class ConsulRegistrationBackgroundService : BackgroundService
{
private readonly IConsulClient _consulClient;
private readonly ILogger<ConsulRegistrationBackgroundService> _logger;
private readonly string _serviceId;
private readonly string _serviceName;
private readonly string _host;
private readonly int _port;
private readonly string _healthCheckUrl;

public ConsulRegistrationBackgroundService(
IConsulClient consulClient,
ILogger<ConsulRegistrationBackgroundService> logger,
string serviceId,
string serviceName,
string host,
int port,
string healthCheckUrl = "/health") // Default health check endpoint
{
_consulClient = consulClient;
_logger = logger;
_serviceId = serviceId;
_serviceName = serviceName;
_host = host;
_port = port;
_healthCheckUrl = healthCheckUrl; // Assign health check URL
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
// Register the service with Consul along with health check
var registration = new AgentServiceRegistration
{
ID = _serviceId,
Name = _serviceName,
Address = _host,
Port = _port,
};

_logger.LogInformation("Registering service {ServiceName} with ID {ServiceId} at {Host}:{Port}", _serviceName, _serviceId, _host, _port);
await _consulClient.Agent.ServiceRegister(registration, stoppingToken);

await Task.Delay(Timeout.Infinite, stoppingToken); // Keep the service registered until cancellation
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while registering service {ServiceName} with ID {ServiceId}.", _serviceName, _serviceId);
}
}

public override async Task StopAsync(CancellationToken cancellationToken)
{
try
{
_logger.LogInformation("Deregistering service {ServiceName} with ID {ServiceId}", _serviceName, _serviceId);
await _consulClient.Agent.ServiceDeregister(_serviceId);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while deregistering service {ServiceName} with ID {ServiceId}.", _serviceName, _serviceId);
}
}
}
65 changes: 65 additions & 0 deletions New/Payeh.SharedKernel/Consul/ConsulService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using Consul;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Payeh.SharedKernel.Consul
{
public class ConsulService : IConsulService
{
private readonly IConsulClient _consulClient;

public ConsulService(IConsulClient consulClient)
{
_consulClient = consulClient;
}

// دریافت تمام سرویس‌های ثبت‌شده در Consul
public async Task<IEnumerable<AgentService>> GetAllServicesAsync()
{
var services = await _consulClient.Agent.Services();
return services.Response.Values; // تمام سرویس‌ها را برمی‌گرداند
}

// دریافت جزئیات یک سرویس خاص با نام آن
public async Task<AgentService> GetServiceDetailsAsync(string serviceName)
{
var services = await _consulClient.Agent.Services();

var service = services.Response.Values.FirstOrDefault(s => s.Service.Equals(serviceName, StringComparison.OrdinalIgnoreCase));
return service; // اگر سرویس پیدا شد، آن را برمی‌گرداند
}

// دریافت وضعیت سلامت یک سرویس خاص
public async Task<ServiceEntry[]> GetServiceHealthAsync(string serviceName)
{
// گرفتن وضعیت سلامت سرویس خاص از Consul
var healthCheck = await _consulClient.Health.Service(serviceName);

// HealthServiceResponse شامل اطلاعات وضعیت سلامت می‌باشد
return healthCheck.Response; // اگر وضعیت سلامت پیدا شد، آن را برمی‌گرداند
}

// دریافت وضعیت سلامت تمام سرویس‌ها


// دریافت وضعیت سلامت نود کنونی
public async Task<List<ServiceEntry>> GetCurrentNodeHealthAsync()
{
// دریافت اطلاعات مربوط به نودها از Consul
var ser = await _consulClient.Agent.Services();

List<ServiceEntry> healthChecks = new List<ServiceEntry>();;
foreach (var value in ser.Response.Values)
{
var health = await _consulClient.Health.Service(value.Service); // وضعیت سلامت نود کنونی را می‌گیریم

healthChecks.AddRange(health.Response);

}


return healthChecks; // بازگشت وضعیت سلامت سرویس‌ها برای نود
}
}
}
13 changes: 13 additions & 0 deletions New/Payeh.SharedKernel/Consul/IConsulService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Consul;

namespace Payeh.SharedKernel.Consul;

public interface IConsulService
{
Task<IEnumerable<AgentService>> GetAllServicesAsync(); // برای دریافت تمام سرویس‌ها
Task<AgentService> GetServiceDetailsAsync(string serviceName); // برای دریافت جزئیات یک سرویس خاص

Task<ServiceEntry[]> GetServiceHealthAsync(string serviceName);
// دریافت وضعیت سلامت تمام سرویس‌ها
Task<List<ServiceEntry>> GetCurrentNodeHealthAsync();
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
namespace Payeh.SharedKernel.Domain.ValueObjects;

/// <summary>
/// Generic JSON converter for BusinessId to handle serialization and deserialization.
/// Generic JSON converter for GuidBusinessId to handle serialization and deserialization.
/// </summary>
public class BusinessIdJsonConverter<T, TKey> : JsonConverter<BusinessId<T, TKey>>
where T : BusinessId<T, TKey>, new()
Expand All @@ -20,7 +20,7 @@ public override BusinessId<T, TKey> Read(ref Utf8JsonReader reader, Type typeToC

if (typeof(TKey) == typeof(Guid) && Guid.TryParse(value, out var guid))
{
return BusinessId<T, TKey>.FromValue((TKey)(object)guid);
return BusinessId<T, TKey>.NewId((TKey)(object)guid);
}

throw new JsonException("Invalid format for Business ID.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
namespace Payeh.SharedKernel.Domain.ValueObjects;

/// <summary>
/// JSON converter factory for BusinessId to handle various generic instantiations.
/// JSON converter factory for GuidBusinessId to handle various generic instantiations.
/// </summary>
public class BusinessIdJsonConverterFactory : JsonConverterFactory
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,9 @@ namespace Payeh.SharedKernel.Domain.ValueObjects;
public abstract class BusinessId<T, TKey> : ValueObject, IEquatable<BusinessId<T, TKey>>
where T : BusinessId<T, TKey>, new()
{
/// <summary>
/// Protected constructor for derived classes.
/// </summary>
protected BusinessId()
{
}

/// <summary>
/// Initializes a new instance of the <see cref="BusinessId{T, TKey}" /> class with a specific value.
/// </summary>
/// <param name="value">The value of the business ID.</param>
protected BusinessId(TKey value)
{
if (value == null || value.Equals(default(TKey)))
Expand All @@ -42,16 +34,6 @@ public bool Equals(BusinessId<T, TKey>? other)
return EqualityComparer<TKey>.Default.Equals(Value, other.Value);
}

/// <summary>
/// Factory method to create an instance of the derived class from an existing value.
/// </summary>
public static T FromValue(TKey value)
{
if (value == null || value.Equals(default(TKey)))
throw new ArgumentException($"The value of {nameof(value)} cannot be null or default.", nameof(value));

return NewId(value);
}

/// <summary>
/// Helper method to create an instance of the derived class.
Expand All @@ -76,9 +58,6 @@ public override int GetHashCode()
return Value?.GetHashCode() ?? 0;
}

/// <summary>
/// Overrides equality operators for value comparison.
/// </summary>
public static bool operator ==(BusinessId<T, TKey>? left, BusinessId<T, TKey>? right)
{
if (left is null && right is null) return true;
Expand All @@ -97,17 +76,11 @@ public override string ToString()
return Value?.ToString() ?? string.Empty;
}

/// <summary>
/// Overrides equality components for comparing value objects.
/// </summary>
protected override IEnumerable<object?> GetEqualityComponents()
{
yield return Value;
}

/// <summary>
/// Provides a custom value comparer for EF Core.
/// </summary>
public static ValueComparer<T> GetValueComparer()
{
return new ValueComparer<T>(
Expand All @@ -121,33 +94,14 @@ public static ValueComparer<T> GetValueComparer()
/// <summary>
/// Represents a specialized implementation of BusinessId with a GUID as the key type.
/// </summary>
public abstract class BusinessId<T> : BusinessId<T, Guid> where T : BusinessId<T>, new()
public abstract class GuidBusinessId<T> : BusinessId<T, Guid> where T : GuidBusinessId<T>, new()
{
/// <summary>
/// Initializes a new instance of the BusinessId class with a new GUID.
/// </summary>
public BusinessId() : base(Guid.NewGuid())
{
}
public GuidBusinessId() : base(Guid.NewGuid()) { }

/// <summary>
/// Initializes a new instance of the BusinessId class with a specific GUID value.
/// </summary>
public BusinessId(Guid value) : base(value)
{
}
public GuidBusinessId(Guid value) : base(value) { }

/// <summary>
/// Factory method to create a new BusinessId with a new GUID.
/// </summary>
public static T NewId()
{
return FromValue(Guid.NewGuid());
}
public static T NewId() => NewId(Guid.NewGuid());

/// <summary>
/// Factory method to create a BusinessId from a string representation of a GUID.
/// </summary>
public static T FromString(string value)
{
if (string.IsNullOrWhiteSpace(value))
Expand All @@ -156,6 +110,44 @@ public static T FromString(string value)
if (!Guid.TryParse(value, out var parsedGuid))
throw new ArgumentException("Invalid GUID format.", nameof(value));

return FromValue(parsedGuid);
return NewId(parsedGuid);
}
}
}

/// <summary>
/// Represents a specialized implementation of BusinessId with an integer as the key type.
/// </summary>
public abstract class IntBusinessId<T> : BusinessId<T, int> where T : IntBusinessId<T>, new()
{
public IntBusinessId() : base(0) { }

public IntBusinessId(int value) : base(value) { }




public static T FromString(string value)
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("Business ID cannot be empty or whitespace.", nameof(value));

if (!int.TryParse(value, out var parsedInt))
throw new ArgumentException("Invalid integer format.", nameof(value));

return NewId(parsedInt);
}
}

/// <summary>
/// Represents a specialized implementation of BusinessId with a string as the key type.
/// </summary>
public abstract class StringBusinessId<T> : BusinessId<T, string> where T : StringBusinessId<T>, new()
{
public StringBusinessId() : base(string.Empty) { }

public StringBusinessId(string value) : base(value) { }



public static T FromString(string value) => NewId(value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ namespace Payeh.SharedKernel.EntityFrameworkCore.Domain;
{
public BusinessIdConverter()
: base(
id => id.Value, // Convert BusinessId<T> to string for database storage
str => (T)BusinessId<T,TKey>.FromValue(str)) // Convert string back to BusinessId<T>
id => id.Value, // Convert GuidBusinessId<T> to string for database storage
str => (T)BusinessId<T,TKey>.NewId(str)) // Convert string back to GuidBusinessId<T>
{
}
}

public class BusinessIdConverter<T> :BusinessIdConverter<T,Guid> where T : BusinessId<T>, new()
public class BusinessIdConverter<T> :BusinessIdConverter<T,Guid> where T : GuidBusinessId<T>, new()
{}
Loading

0 comments on commit 9d8b84d

Please sign in to comment.