This commit is contained in:
Mikhail Kuznetsov
2026-05-28 16:56:54 +10:00
12 changed files with 251 additions and 149 deletions

View File

@@ -0,0 +1,156 @@
namespace PARR.Domain.Cache
{
/// <summary>
/// Ключи для кэша
/// </summary>
public static class CacheKeys
{
#region Пример
// Пример для русских букв
//public static class Test
//{
// // Если нужно конвертировать русские буквы
// public static (string[], string[]) Ttt(string workGroup) => (["shortcode"], [workGroup]);
//}
#endregion
/// <summary>
/// Имя bucket
/// </summary>
private const string BucketName = "bucket";
/// <summary>
/// Авторизация пользователей, сессии
/// </summary>
public static class UserAuth
{
/// <summary>
/// Авторизированный пользователь
/// </summary>
/// <param name="ipAddress"></param>
/// <returns></returns>
public static string[] Session(string ipAddress) => ["user", "session", ipAddress];
/// <summary>
/// Заблокированный пользователь
/// </summary>
/// <param name="ipAddress"></param>
/// <returns></returns>
public static string[] Banned(string ipAddress) => ["user", "banned", ipAddress];
}
/// <summary>
/// Отчеты о загруженности
/// </summary>
public static class Workload
{
/// <summary>
/// Ключ для Template Hash
/// </summary>
/// <returns></returns>
public static string[] TemplateHash() => ["template", "report", "params"];
/// <summary>
/// Ключ Template внутри Hash
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public static string[] Template(Guid id) => [id.ToString()];
/// <summary>
/// Отчет о загруженности, все ЗО
/// </summary>
/// <returns></returns>
public static string[] WorkloadResponseAreaAll() => ["workload", "response-area", "all"];
/// <summary>
/// Отчет о загруженности, одна ЗО
/// </summary>
/// <returns></returns>
public static string[] WorkloadResponseAreaItem() => ["workload", "response-area", "item"];
/// <summary>
/// Отчет о загруженности, все РГ
/// </summary>
/// <returns></returns>
public static string[] WorkloadWorkGroupAll() => ["workload", "work-group", "all"];
/// <summary>
/// Отчет о загруженности, одна РГ
/// </summary>
public static string[] WorkloadWorkGroupItem() => ["workload", "work group", "item"];
}
/// <summary>
/// Юниты
/// </summary>
public static class Unit
{
/// <summary>
/// Ключ для Unit Hash с bucket
/// </summary>
/// <param name="unitId"></param>
/// <returns></returns>
public static string[] UnitHashWithBucket(Guid unitId) => ["unit", BucketName, GetBucketKey(unitId)];
/// <summary>
/// Ключ Unit внутри Hash
/// </summary>
/// <param name="unitId"></param>
/// <returns></returns>
public static string[] UnitItem(Guid unitId) => [unitId.ToString()];
}
#region Helpers
/// <summary>
/// Получить имя (номер) bucket по id.
/// Оптимальное кол-во элементов в бакете 512-1000 (если больше, оптимизировать настройки Redis).
/// </summary>
/// <param name="id"></param>
/// <param name="bucketSize">Кол-во bucket`ов</param>
/// <returns></returns>
private static string GetBucketKey(Guid id, BucketSize bucketSize = BucketSize.Size256)
{
// Получаем GUID в виде строки без дефисов (32 символа)
string guidString = id.ToString("N");
//4096
// Берем первые xx символа как срез памяти (без аллокации новой строки)
ReadOnlySpan<char> hexPart = guidString.AsSpan(0, (int)bucketSize);
// Конвертируем Hex в обычное число byte
if (!int.TryParse(hexPart, System.Globalization.NumberStyles.HexNumber, null, out int bucketId))
{
// На случай непредвиденных сбоев, хотя для валидного GUID это невозможно
bucketId = 0;
}
return bucketId.ToString();
}
/// <summary>
/// Кол-во возможных bucket.
/// В bucket оптимально размещать до 1000 записей, если больше, то требуется переконфигурация redis
/// </summary>
private enum BucketSize
{
/// <summary>
/// Для 256 bucket`ов - берем 2 символа
/// </summary>
Size256 = 2,
/// <summary>
/// Для 4096 bucket`ов - берем 3 символа
/// </summary>
Size4096 = 3
}
#endregion
}
}