mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-05-06 18:52:27 +00:00
Abstract Redis away from room & friends
This commit is contained in:
parent
fb1a2e564d
commit
9ee2778595
13 changed files with 297 additions and 110 deletions
|
@ -2,6 +2,8 @@
|
|||
using System.Xml.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.StorableLists;
|
||||
using LBPUnion.ProjectLighthouse.StorableLists.Stores;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
@ -53,13 +55,13 @@ public class FriendsController : ControllerBase
|
|||
blockedUsers.Add(blockedUser.UserId);
|
||||
}
|
||||
|
||||
UserFriendStore? friendStore = Redis.GetUserFriendStore(user.UserId);
|
||||
if (friendStore == null) friendStore = Redis.CreateUserFriendStore(user.UserId);
|
||||
UserFriendData? friendStore = UserFriendStore.GetUserFriendData(user.UserId);
|
||||
if (friendStore == null) friendStore = UserFriendStore.CreateUserFriendData(user.UserId);
|
||||
|
||||
friendStore.FriendIds = friends.Select(u => u.UserId).ToList();
|
||||
friendStore.BlockedIds = blockedUsers;
|
||||
|
||||
Redis.UpdateFriendStore(friendStore);
|
||||
UserFriendStore.UpdateFriendData(friendStore);
|
||||
|
||||
string friendsSerialized = friends.Aggregate(string.Empty, (current, user1) => current + LbpSerializer.StringElement("npHandle", user1.Username));
|
||||
|
||||
|
@ -77,7 +79,7 @@ public class FriendsController : ControllerBase
|
|||
User user = userAndToken.Value.Item1;
|
||||
GameToken gameToken = userAndToken.Value.Item2;
|
||||
|
||||
UserFriendStore? friendStore = Redis.GetUserFriendStore(user.UserId);
|
||||
UserFriendData? friendStore = UserFriendStore.GetUserFriendData(user.UserId);
|
||||
|
||||
if (friendStore == null)
|
||||
return this.Ok(LbpSerializer.BlankElement("myFriends"));
|
||||
|
|
|
@ -40,7 +40,7 @@ public class RoomVisualizerController : ControllerBase
|
|||
#if !DEBUG
|
||||
return this.NotFound();
|
||||
#else
|
||||
RoomHelper.Rooms.DeleteAll();
|
||||
RoomHelper.Rooms.RemoveAll();
|
||||
return this.Redirect("/debug/roomVisualizer");
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -7,21 +7,5 @@ namespace LBPUnion.ProjectLighthouse.Extensions;
|
|||
[SuppressMessage("ReSharper", "LoopCanBePartlyConvertedToQuery")]
|
||||
public static class RedisCollectionExtensions
|
||||
{
|
||||
public static void DeleteAll<T>(this IRedisCollection<T> collection, Func<T, bool> predicate)
|
||||
{
|
||||
foreach (T item in collection)
|
||||
{
|
||||
if (!predicate.Invoke(item)) continue;
|
||||
|
||||
collection.DeleteSync(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DeleteAll<T>(this IRedisCollection<T> collection)
|
||||
{
|
||||
foreach (T item in collection)
|
||||
{
|
||||
collection.DeleteSync(item);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,18 +5,18 @@ using System.Linq;
|
|||
using System.Threading.Tasks;
|
||||
using LBPUnion.ProjectLighthouse.Extensions;
|
||||
using LBPUnion.ProjectLighthouse.Logging;
|
||||
using LBPUnion.ProjectLighthouse.StorableLists;
|
||||
using LBPUnion.ProjectLighthouse.StorableLists.Stores;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||
using LBPUnion.ProjectLighthouse.Types.Match;
|
||||
using LBPUnion.ProjectLighthouse.Types.Profiles;
|
||||
using Redis.OM;
|
||||
using Redis.OM.Searching;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers;
|
||||
|
||||
public class RoomHelper
|
||||
{
|
||||
public static readonly IRedisCollection<Room> Rooms = Redis.GetRooms();
|
||||
public static readonly StorableList<Room> Rooms = RoomStore.GetRooms();
|
||||
|
||||
public static readonly RoomSlot PodSlot = new()
|
||||
{
|
||||
|
@ -169,7 +169,7 @@ public class RoomHelper
|
|||
};
|
||||
|
||||
CleanupRooms(room.HostId, room);
|
||||
lock(Rooms) Rooms.Insert(room);
|
||||
lock(Rooms) Rooms.Add(room);
|
||||
Logger.LogInfo($"Created room (id: {room.RoomId}) for host {room.HostId}", LogArea.Match);
|
||||
|
||||
return room;
|
||||
|
@ -201,7 +201,6 @@ public class RoomHelper
|
|||
[SuppressMessage("ReSharper", "InvertIf")]
|
||||
public static void CleanupRooms(int? hostId = null, Room? newRoom = null, Database? database = null)
|
||||
{
|
||||
// return;
|
||||
lock(Rooms)
|
||||
{
|
||||
int roomCountBeforeCleanup = Rooms.Count();
|
||||
|
@ -220,7 +219,7 @@ public class RoomHelper
|
|||
if (hostId != null)
|
||||
try
|
||||
{
|
||||
Rooms.DeleteAll(r => r.HostId == hostId);
|
||||
Rooms.RemoveAll(r => r.HostId == hostId);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -236,8 +235,8 @@ public class RoomHelper
|
|||
foreach (int newRoomPlayer in newRoom.PlayerIds) room.PlayerIds.RemoveAll(p => p == newRoomPlayer);
|
||||
}
|
||||
|
||||
Rooms.DeleteAll(r => r.PlayerIds.Count == 0); // Remove empty rooms
|
||||
Rooms.DeleteAll(r => r.PlayerIds.Count > 4); // Remove obviously bogus rooms
|
||||
Rooms.RemoveAll(r => r.PlayerIds.Count == 0); // Remove empty rooms
|
||||
Rooms.RemoveAll(r => r.PlayerIds.Count > 4); // Remove obviously bogus rooms
|
||||
|
||||
int roomCountAfterCleanup = Rooms.Count();
|
||||
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
#nullable enable
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using LBPUnion.ProjectLighthouse.Extensions;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Logging;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using LBPUnion.ProjectLighthouse.Types.Match;
|
||||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||
using Redis.OM;
|
||||
using Redis.OM.Contracts;
|
||||
using Redis.OM.Searching;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse;
|
||||
|
||||
public static class Redis
|
||||
{
|
||||
private static readonly RedisConnectionProvider provider;
|
||||
|
||||
static Redis()
|
||||
{
|
||||
provider = new RedisConnectionProvider(ServerConfiguration.Instance.RedisConnectionString);
|
||||
}
|
||||
|
||||
private static bool initialized;
|
||||
public static async Task Initialize()
|
||||
{
|
||||
if (initialized) throw new InvalidOperationException("Redis has already been initialized.");
|
||||
|
||||
IRedisConnection connection = getConnection();
|
||||
|
||||
string pong = (await connection.ExecuteAsync("PING")).ToString(CultureInfo.InvariantCulture);
|
||||
if (pong != "PONG")
|
||||
{
|
||||
Logger.LogError("Could not ping, ping returned " + pong, LogArea.Redis);
|
||||
return;
|
||||
}
|
||||
|
||||
await connection.RecreateIndexAsync(typeof(Room));
|
||||
await connection.RecreateIndexAsync(typeof(UserFriendStore));
|
||||
|
||||
initialized = true;
|
||||
Logger.LogSuccess("Initialized Redis.", LogArea.Redis);
|
||||
}
|
||||
|
||||
private static IRedisConnection getConnection()
|
||||
{
|
||||
Logger.LogDebug("Getting a Redis connection", LogArea.Redis);
|
||||
return provider.Connection;
|
||||
}
|
||||
|
||||
public static IRedisCollection<Room> GetRooms() => provider.RedisCollection<Room>();
|
||||
|
||||
private static IRedisCollection<UserFriendStore> userFriendStoreCollection => provider.RedisCollection<UserFriendStore>();
|
||||
|
||||
public static UserFriendStore? GetUserFriendStore(int userId) =>
|
||||
userFriendStoreCollection.FirstOrDefault(s => s.UserId == userId);
|
||||
|
||||
public static UserFriendStore CreateUserFriendStore(int userId)
|
||||
{
|
||||
UserFriendStore friendStore = new()
|
||||
{
|
||||
UserId = userId,
|
||||
};
|
||||
|
||||
userFriendStoreCollection.Insert(friendStore);
|
||||
return friendStore;
|
||||
}
|
||||
|
||||
public static void UpdateFriendStore(UserFriendStore friendStore)
|
||||
{
|
||||
userFriendStoreCollection.UpdateSync(friendStore);
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ using LBPUnion.ProjectLighthouse.Helpers;
|
|||
using LBPUnion.ProjectLighthouse.Logging;
|
||||
using LBPUnion.ProjectLighthouse.Logging.Loggers;
|
||||
using LBPUnion.ProjectLighthouse.Startup;
|
||||
using LBPUnion.ProjectLighthouse.StorableLists;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
@ -77,7 +78,7 @@ public static class StartupTasks
|
|||
RoomHelper.StartCleanupThread();
|
||||
|
||||
Logger.LogInfo("Initializing Redis...", LogArea.Startup);
|
||||
Redis.Initialize().Wait();
|
||||
RedisDatabase.Initialize().Wait();
|
||||
|
||||
stopwatch.Stop();
|
||||
Logger.LogSuccess($"Ready! Startup took {stopwatch.ElapsedMilliseconds}ms. Passing off control to ASP.NET...", LogArea.Startup);
|
||||
|
|
60
ProjectLighthouse/StorableLists/NormalStorableList.cs
Normal file
60
ProjectLighthouse/StorableLists/NormalStorableList.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.StorableLists;
|
||||
|
||||
public class NormalStorableList<T> : StorableList<T>
|
||||
{
|
||||
private readonly List<T> list;
|
||||
public NormalStorableList(List<T> normalCollection) : base(normalCollection)
|
||||
{
|
||||
this.list = normalCollection;
|
||||
}
|
||||
|
||||
public override void Add(T item)
|
||||
{
|
||||
this.list.Add(item);
|
||||
}
|
||||
|
||||
public override Task AddAsync(T item)
|
||||
{
|
||||
this.list.Add(item);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override void RemoveAll(Predicate<T> predicate)
|
||||
{
|
||||
this.list.RemoveAll(predicate);
|
||||
}
|
||||
|
||||
public override Task RemoveAllAsync(Predicate<T> predicate)
|
||||
{
|
||||
this.list.RemoveAll(predicate);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task RemoveAllAsync()
|
||||
{
|
||||
this.list.RemoveAll(_ => true);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override void RemoveAll()
|
||||
{
|
||||
this.list.RemoveAll(_ => true);
|
||||
}
|
||||
|
||||
public override void Remove(T item)
|
||||
{
|
||||
this.list.Remove(item);
|
||||
}
|
||||
|
||||
public override Task RemoveAsync(T item)
|
||||
{
|
||||
this.list.Remove(item);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
public override void Update(T item) {}
|
||||
public override Task UpdateAsync(T item) => Task.CompletedTask;
|
||||
}
|
65
ProjectLighthouse/StorableLists/RedisDatabase.cs
Normal file
65
ProjectLighthouse/StorableLists/RedisDatabase.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
#nullable enable
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using LBPUnion.ProjectLighthouse.Extensions;
|
||||
using LBPUnion.ProjectLighthouse.Logging;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using LBPUnion.ProjectLighthouse.Types.Match;
|
||||
using LBPUnion.ProjectLighthouse.Types.Settings;
|
||||
using Redis.OM;
|
||||
using Redis.OM.Contracts;
|
||||
using Redis.OM.Searching;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.StorableLists;
|
||||
|
||||
public static class RedisDatabase
|
||||
{
|
||||
private static readonly RedisConnectionProvider provider;
|
||||
|
||||
static RedisDatabase()
|
||||
{
|
||||
provider = new RedisConnectionProvider(ServerConfiguration.Instance.RedisConnectionString);
|
||||
}
|
||||
|
||||
public static bool Initialized { get; private set; }
|
||||
public static async Task Initialize()
|
||||
{
|
||||
if (Initialized) throw new InvalidOperationException("Redis has already been initialized.");
|
||||
|
||||
try
|
||||
{
|
||||
IRedisConnection connection = getConnection();
|
||||
|
||||
string pong = (await connection.ExecuteAsync("PING")).ToString(CultureInfo.InvariantCulture);
|
||||
if (pong != "PONG")
|
||||
{
|
||||
Logger.LogError("Could not ping, ping returned " + pong,
|
||||
LogArea.Redis);
|
||||
return;
|
||||
}
|
||||
|
||||
await connection.RecreateIndexAsync(typeof(Room));
|
||||
await connection.RecreateIndexAsync(typeof(UserFriendData));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logger.LogError("Could not initialize Redis:\n" + e, LogArea.Redis);
|
||||
return;
|
||||
}
|
||||
|
||||
Initialized = true;
|
||||
Logger.LogSuccess("Initialized Redis.", LogArea.Redis);
|
||||
}
|
||||
|
||||
private static IRedisConnection getConnection()
|
||||
{
|
||||
Logger.LogDebug("Getting a Redis connection", LogArea.Redis);
|
||||
return provider.Connection;
|
||||
}
|
||||
|
||||
public static IRedisCollection<UserFriendData> UserFriendStoreCollection => provider.RedisCollection<UserFriendData>();
|
||||
|
||||
internal static IRedisCollection<Room> GetRooms() => provider.RedisCollection<Room>();
|
||||
}
|
31
ProjectLighthouse/StorableLists/RedisStorableList.cs
Normal file
31
ProjectLighthouse/StorableLists/RedisStorableList.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
using System.Threading.Tasks;
|
||||
using Redis.OM.Searching;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.StorableLists;
|
||||
|
||||
public class RedisStorableList<T> : StorableList<T>
|
||||
{
|
||||
private readonly IRedisCollection<T> redisNormalCollection;
|
||||
public RedisStorableList(IRedisCollection<T> normalCollection) : base(normalCollection)
|
||||
{
|
||||
this.redisNormalCollection = normalCollection;
|
||||
}
|
||||
|
||||
public override Task AddAsync(T item) => this.redisNormalCollection.InsertAsync(item);
|
||||
public override void Add(T item)
|
||||
{
|
||||
this.redisNormalCollection.Insert(item);
|
||||
}
|
||||
|
||||
public override Task RemoveAsync(T item) => this.redisNormalCollection.Delete(item);
|
||||
public override void Remove(T item)
|
||||
{
|
||||
this.redisNormalCollection.DeleteSync(item);
|
||||
}
|
||||
|
||||
public override Task UpdateAsync(T item) => this.redisNormalCollection.Update(item);
|
||||
public override void Update(T item)
|
||||
{
|
||||
this.redisNormalCollection.UpdateSync(item);
|
||||
}
|
||||
}
|
61
ProjectLighthouse/StorableLists/StorableList.cs
Normal file
61
ProjectLighthouse/StorableLists/StorableList.cs
Normal file
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.StorableLists;
|
||||
|
||||
public abstract class StorableList<T> : IEnumerable<T>
|
||||
{
|
||||
private protected readonly IEnumerable<T> NormalCollection;
|
||||
protected StorableList(IEnumerable<T> normalCollection)
|
||||
{
|
||||
this.NormalCollection = normalCollection;
|
||||
}
|
||||
|
||||
public abstract void Add(T item);
|
||||
public abstract Task AddAsync(T item);
|
||||
public abstract void Remove(T item);
|
||||
public abstract Task RemoveAsync(T item);
|
||||
public abstract void Update(T item);
|
||||
public abstract Task UpdateAsync(T item);
|
||||
|
||||
public virtual void RemoveAll(Predicate<T> predicate)
|
||||
{
|
||||
foreach (T item in this.NormalCollection)
|
||||
{
|
||||
if (!predicate.Invoke(item)) continue;
|
||||
|
||||
this.Remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual async Task RemoveAllAsync(Predicate<T> predicate)
|
||||
{
|
||||
foreach (T item in this.NormalCollection)
|
||||
{
|
||||
if (!predicate.Invoke(item)) continue;
|
||||
|
||||
await this.RemoveAsync(item);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void RemoveAll()
|
||||
{
|
||||
foreach (T item in this.NormalCollection)
|
||||
{
|
||||
this.Remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual async Task RemoveAllAsync()
|
||||
{
|
||||
foreach (T item in this.NormalCollection)
|
||||
{
|
||||
await this.RemoveAsync(item);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => this.NormalCollection.GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
|
||||
}
|
21
ProjectLighthouse/StorableLists/Stores/RoomStore.cs
Normal file
21
ProjectLighthouse/StorableLists/Stores/RoomStore.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using LBPUnion.ProjectLighthouse.Types.Match;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.StorableLists.Stores;
|
||||
|
||||
public static class RoomStore
|
||||
{
|
||||
private static List<Room>? rooms;
|
||||
|
||||
public static StorableList<Room> GetRooms()
|
||||
{
|
||||
if (RedisDatabase.Initialized)
|
||||
{
|
||||
return new RedisStorableList<Room>(RedisDatabase.GetRooms());
|
||||
}
|
||||
|
||||
rooms ??= new List<Room>();
|
||||
return new NormalStorableList<Room>(rooms);
|
||||
}
|
||||
}
|
40
ProjectLighthouse/StorableLists/Stores/UserFriendStore.cs
Normal file
40
ProjectLighthouse/StorableLists/Stores/UserFriendStore.cs
Normal file
|
@ -0,0 +1,40 @@
|
|||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.StorableLists.Stores;
|
||||
|
||||
public static class UserFriendStore
|
||||
{
|
||||
private static List<UserFriendData>? friendDataStore;
|
||||
|
||||
private static StorableList<UserFriendData> getStorableFriendData()
|
||||
{
|
||||
if (RedisDatabase.Initialized)
|
||||
{
|
||||
return new RedisStorableList<UserFriendData>(RedisDatabase.UserFriendStoreCollection);
|
||||
}
|
||||
|
||||
friendDataStore ??= new List<UserFriendData>();
|
||||
return new NormalStorableList<UserFriendData>(friendDataStore);
|
||||
}
|
||||
|
||||
public static UserFriendData? GetUserFriendData(int userId) => getStorableFriendData().FirstOrDefault(s => s.UserId == userId);
|
||||
|
||||
public static UserFriendData CreateUserFriendData(int userId)
|
||||
{
|
||||
UserFriendData friendData = new()
|
||||
{
|
||||
UserId = userId,
|
||||
};
|
||||
|
||||
getStorableFriendData().Add(friendData);
|
||||
return friendData;
|
||||
}
|
||||
|
||||
public static void UpdateFriendData(UserFriendData friendData)
|
||||
{
|
||||
getStorableFriendData().Update(friendData);
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ namespace LBPUnion.ProjectLighthouse.Types;
|
|||
|
||||
[SuppressMessage("ReSharper", "CollectionNeverQueried.Global")]
|
||||
[Document(StorageType = StorageType.Json)]
|
||||
public class UserFriendStore
|
||||
public class UserFriendData
|
||||
{
|
||||
private int userId;
|
||||
public int UserId {
|
Loading…
Add table
Add a link
Reference in a new issue