add redis for character identification

This commit is contained in:
rootdarkarchon
2022-09-13 11:45:09 +02:00
parent ea48fb3947
commit 1f66b2c980
16 changed files with 356 additions and 175 deletions

View File

@@ -45,7 +45,7 @@ public class MareDbContext : DbContext
{
modelBuilder.Entity<Auth>().ToTable("auth");
modelBuilder.Entity<User>().ToTable("users");
modelBuilder.Entity<User>().HasIndex(c => c.CharacterIdentification);
//modelBuilder.Entity<User>().HasIndex(c => c.CharacterIdentification);
modelBuilder.Entity<FileCache>().ToTable("file_caches");
modelBuilder.Entity<FileCache>().HasIndex(c => c.UploaderUID);
modelBuilder.Entity<ClientPair>().ToTable("client_pairs");

View File

@@ -30,6 +30,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.8" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.6" />
<PackageReference Include="prometheus-net" Version="6.0.0" />
</ItemGroup>

View File

@@ -7,8 +7,8 @@ namespace MareSynchronosShared.Models
[Key]
[MaxLength(10)]
public string UID { get; set; }
[MaxLength(100)]
public string CharacterIdentification { get; set; }
//[MaxLength(100)]
//public string CharacterIdentification { get; set; }
[Timestamp]
public byte[] Timestamp { get; set; }

View File

@@ -0,0 +1,62 @@
using System.Collections.Concurrent;
using MareSynchronosShared.Metrics;
namespace MareSynchronosShared.Services;
public abstract class BaseClientIdentificationService : IClientIdentificationService
{
private readonly MareMetrics metrics;
protected ConcurrentDictionary<string, string> OnlineClients = new();
protected BaseClientIdentificationService(MareMetrics metrics)
{
this.metrics = metrics;
}
public virtual int GetOnlineUsers()
{
return OnlineClients.Count;
}
public string? GetUidForCharacterIdent(string characterIdent)
{
var result = OnlineClients.SingleOrDefault(u =>
string.Compare(u.Value, characterIdent, StringComparison.InvariantCultureIgnoreCase) == 0);
return result.Equals(new KeyValuePair<string, string>()) ? null : result.Key;
}
public virtual string? GetCharacterIdentForUid(string uid)
{
if (!OnlineClients.TryGetValue(uid, out var result))
{
return null;
}
return result;
}
public virtual void MarkUserOnline(string uid, string charaIdent)
{
OnlineClients[uid] = charaIdent;
metrics.SetGaugeTo(MetricsAPI.GaugeAuthorizedConnections, OnlineClients.Count);
}
public virtual void MarkUserOffline(string uid)
{
if (OnlineClients.TryRemove(uid, out _))
{
metrics.SetGaugeTo(MetricsAPI.GaugeAuthorizedConnections, OnlineClients.Count);
}
}
public Task StartAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public virtual Task StopAsync(CancellationToken cancellationToken)
{
metrics.SetGaugeTo(MetricsAPI.GaugeAuthorizedConnections, 0);
OnlineClients = new();
return Task.CompletedTask;
}
}

View File

@@ -0,0 +1,57 @@
using System.Text;
using MareSynchronosShared.Metrics;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Configuration;
using StackExchange.Redis;
namespace MareSynchronosShared.Services;
public class DistributedClientIdentificationService : BaseClientIdentificationService
{
private readonly IDistributedCache distributedCache;
private readonly IConfiguration configuration;
private const string RedisPrefix = "uidcache:";
public DistributedClientIdentificationService(MareMetrics metrics, IDistributedCache distributedCache, IConfiguration configuration) : base(metrics)
{
this.distributedCache = distributedCache;
this.configuration = configuration.GetSection("MareSynchronos");
}
public override int GetOnlineUsers()
{
var redis = configuration.GetValue<string>("RedisConnectionString");
var conn = ConnectionMultiplexer.Connect(redis);
var endpoint = conn.GetEndPoints().First();
return conn.GetServer(endpoint).Keys(pattern: RedisPrefix + "*").Count();
}
public override string? GetCharacterIdentForUid(string uid)
{
var localIdent = base.GetCharacterIdentForUid(uid);
if (localIdent != null) return localIdent;
var cachedIdent = distributedCache.Get(RedisPrefix + uid);
return cachedIdent == null ? null : Encoding.UTF8.GetString(cachedIdent);
}
public override void MarkUserOffline(string uid)
{
base.MarkUserOffline(uid);
distributedCache.Remove(RedisPrefix + uid);
}
public override void MarkUserOnline(string uid, string charaIdent)
{
base.MarkUserOnline(uid, charaIdent);
distributedCache.Set(RedisPrefix + uid, Encoding.UTF8.GetBytes(charaIdent));
}
public override Task StopAsync(CancellationToken cancellationToken)
{
foreach (var uid in OnlineClients)
{
distributedCache.Remove(RedisPrefix + uid.Key);
}
return base.StopAsync(cancellationToken);
}
}

View File

@@ -0,0 +1,12 @@
using Microsoft.Extensions.Hosting;
namespace MareSynchronosShared.Services;
public interface IClientIdentificationService : IHostedService
{
int GetOnlineUsers();
string? GetUidForCharacterIdent(string characterIdent);
string? GetCharacterIdentForUid(string uid);
void MarkUserOnline(string uid, string charaIdent);
void MarkUserOffline(string uid);
}

View File

@@ -0,0 +1,10 @@
using MareSynchronosShared.Metrics;
namespace MareSynchronosShared.Services;
public class LocalClientIdentificationService : BaseClientIdentificationService
{
public LocalClientIdentificationService(MareMetrics metrics) : base(metrics)
{
}
}