mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-05-08 19:42:27 +00:00
Fix StatisticsHelper concurrent exception
This commit is contained in:
parent
cf5369d372
commit
eb7cda8997
9 changed files with 65 additions and 44 deletions
|
@ -10,6 +10,14 @@ namespace LBPUnion.ProjectLighthouse.Servers.API.Controllers;
|
|||
/// </summary>
|
||||
public class StatisticsEndpoints : ApiEndpointController
|
||||
{
|
||||
|
||||
private readonly Database database;
|
||||
|
||||
public StatisticsEndpoints(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets everything that StatisticsHelper provides.
|
||||
/// </summary>
|
||||
|
@ -21,11 +29,11 @@ public class StatisticsEndpoints : ApiEndpointController
|
|||
(
|
||||
new StatisticsResponse
|
||||
{
|
||||
Photos = await StatisticsHelper.PhotoCount(),
|
||||
Slots = await StatisticsHelper.SlotCount(),
|
||||
Users = await StatisticsHelper.UserCount(),
|
||||
RecentMatches = await StatisticsHelper.RecentMatches(),
|
||||
TeamPicks = await StatisticsHelper.TeamPickCount(),
|
||||
Photos = await StatisticsHelper.PhotoCount(this.database),
|
||||
Slots = await StatisticsHelper.SlotCount(this.database),
|
||||
Users = await StatisticsHelper.UserCount(this.database),
|
||||
RecentMatches = await StatisticsHelper.RecentMatches(this.database),
|
||||
TeamPicks = await StatisticsHelper.TeamPickCount(this.database),
|
||||
}
|
||||
);
|
||||
}
|
|
@ -206,8 +206,9 @@ public class ScoreController : ControllerBase
|
|||
// This is hella ugly but it technically assigns the proper rank to a score
|
||||
// var needed for Anonymous type returned from SELECT
|
||||
var rankedScores = this.database.Scores
|
||||
.Where(s => playerIds == null || playerIds.Contains(s.MainPlayer))
|
||||
.Where(s => s.SlotId == slotId && s.Type == type)
|
||||
.AsEnumerable()
|
||||
.Where(s => playerIds == null || playerIds.Any(id => s.PlayerIdCollection.Contains(id)))
|
||||
.OrderByDescending(s => s.Points)
|
||||
.ThenBy(s => s.ScoreId)
|
||||
.ToList()
|
||||
|
|
|
@ -182,7 +182,7 @@ public class SlotsController : ControllerBase
|
|||
|
||||
string response = Enumerable.Aggregate(slots, string.Empty, (current, slot) => current + slot.Serialize(gameVersion));
|
||||
int start = pageStart + Math.Min(pageSize, ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots);
|
||||
int total = await StatisticsHelper.SlotCount();
|
||||
int total = await StatisticsHelper.SlotCountForGame(this.database, token.GameVersion);
|
||||
return this.Ok(generateSlotsResponse(response, start, total));
|
||||
}
|
||||
|
||||
|
@ -238,9 +238,9 @@ public class SlotsController : ControllerBase
|
|||
.Skip(Math.Max(0, pageStart - 1))
|
||||
.Take(Math.Min(pageSize, 30));
|
||||
|
||||
string response = Enumerable.Aggregate(slots, string.Empty, (current, slot) => current + slot.Serialize(gameVersion));
|
||||
string response = slots.Aggregate(string.Empty, (current, slot) => current + slot.Serialize(gameVersion));
|
||||
int start = pageStart + Math.Min(pageSize, ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots);
|
||||
int total = await StatisticsHelper.SlotCount();
|
||||
int total = await StatisticsHelper.SlotCount(this.database);
|
||||
|
||||
return this.Ok(generateSlotsResponse(response, start, total));
|
||||
}
|
||||
|
@ -290,7 +290,7 @@ public class SlotsController : ControllerBase
|
|||
.Take(Math.Min(pageSize, 30));
|
||||
string response = Enumerable.Aggregate(slots, string.Empty, (current, slot) => current + slot.Serialize(gameVersion));
|
||||
int start = pageStart + Math.Min(pageSize, ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots);
|
||||
int total = await StatisticsHelper.TeamPickCount();
|
||||
int total = await StatisticsHelper.TeamPickCount(this.database);
|
||||
|
||||
return this.Ok(generateSlotsResponse(response, start, total));
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ public class SlotsController : ControllerBase
|
|||
|
||||
string response = slots.Aggregate(string.Empty, (current, slot) => current + slot.Serialize(gameVersion));
|
||||
int start = pageStart + Math.Min(pageSize, ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots);
|
||||
int total = await StatisticsHelper.SlotCount();
|
||||
int total = await StatisticsHelper.SlotCountForGame(this.database, token.GameVersion);
|
||||
|
||||
return this.Ok(generateSlotsResponse(response, start, total));
|
||||
}
|
||||
|
@ -341,7 +341,7 @@ public class SlotsController : ControllerBase
|
|||
|
||||
string response = slots.Aggregate(string.Empty, (current, slot) => current + slot.Serialize(token.GameVersion));
|
||||
int start = pageStart + Math.Min(pageSize, ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots);
|
||||
int total = await StatisticsHelper.SlotCount();
|
||||
int total = await StatisticsHelper.SlotCountForGame(this.database, token.GameVersion);
|
||||
|
||||
return this.Ok(generateSlotsResponse(response, start, total));
|
||||
}
|
||||
|
@ -387,7 +387,7 @@ public class SlotsController : ControllerBase
|
|||
|
||||
string response = slots.Aggregate(string.Empty, (current, slot) => current + slot.Serialize(token.GameVersion));
|
||||
int start = pageStart + Math.Min(pageSize, ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots);
|
||||
int total = await StatisticsHelper.SlotCount();
|
||||
int total = await StatisticsHelper.SlotCountForGame(this.database, token.GameVersion);
|
||||
|
||||
return this.Ok(generateSlotsResponse(response, start, total));
|
||||
}
|
||||
|
@ -419,7 +419,7 @@ public class SlotsController : ControllerBase
|
|||
|
||||
string response = slots.Aggregate(string.Empty, (current, slot) => current + slot.Serialize(token.GameVersion));
|
||||
int start = pageStart + Math.Min(pageSize, ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots);
|
||||
int total = await StatisticsHelper.SlotCount();
|
||||
int total = await StatisticsHelper.SlotCountForGame(this.database, token.GameVersion);
|
||||
|
||||
return this.Ok(generateSlotsResponse(response, start, total));
|
||||
}
|
||||
|
|
|
@ -9,15 +9,23 @@ namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
|
|||
[Produces("text/plain")]
|
||||
public class StatisticsController : ControllerBase
|
||||
{
|
||||
|
||||
private readonly Database database;
|
||||
|
||||
public StatisticsController(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
[HttpGet("playersInPodCount")]
|
||||
[HttpGet("totalPlayerCount")]
|
||||
public async Task<IActionResult> TotalPlayerCount() => this.Ok((await StatisticsHelper.RecentMatches()).ToString()!);
|
||||
public async Task<IActionResult> TotalPlayerCount() => this.Ok((await StatisticsHelper.RecentMatches(this.database)).ToString());
|
||||
|
||||
[HttpGet("planetStats")]
|
||||
public async Task<IActionResult> PlanetStats()
|
||||
{
|
||||
int totalSlotCount = await StatisticsHelper.SlotCount();
|
||||
int mmPicksCount = await StatisticsHelper.TeamPickCount();
|
||||
int totalSlotCount = await StatisticsHelper.SlotCount(this.database);
|
||||
int mmPicksCount = await StatisticsHelper.TeamPickCount(this.database);
|
||||
|
||||
return this.Ok
|
||||
(
|
||||
|
@ -27,5 +35,5 @@ public class StatisticsController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpGet("planetStats/totalLevelCount")]
|
||||
public async Task<IActionResult> TotalLevelCount() => this.Ok((await StatisticsHelper.SlotCount()).ToString());
|
||||
public async Task<IActionResult> TotalLevelCount() => this.Ok((await StatisticsHelper.SlotCount(this.database)).ToString());
|
||||
}
|
|
@ -27,10 +27,10 @@ public class AdminPanelPage : BaseLayout
|
|||
if (user == null) return this.Redirect("~/login");
|
||||
if (!user.IsAdmin) return this.NotFound();
|
||||
|
||||
this.Statistics.Add(new AdminPanelStatistic("Users", await StatisticsHelper.UserCount(), "/admin/users"));
|
||||
this.Statistics.Add(new AdminPanelStatistic("Slots", await StatisticsHelper.SlotCount()));
|
||||
this.Statistics.Add(new AdminPanelStatistic("Photos", await StatisticsHelper.PhotoCount()));
|
||||
this.Statistics.Add(new AdminPanelStatistic("API Keys", await StatisticsHelper.APIKeyCount(), "/admin/keys"));
|
||||
this.Statistics.Add(new AdminPanelStatistic("Users", await StatisticsHelper.UserCount(this.Database), "/admin/users"));
|
||||
this.Statistics.Add(new AdminPanelStatistic("Slots", await StatisticsHelper.SlotCount(this.Database)));
|
||||
this.Statistics.Add(new AdminPanelStatistic("Photos", await StatisticsHelper.PhotoCount(this.Database)));
|
||||
this.Statistics.Add(new AdminPanelStatistic("API Keys", await StatisticsHelper.APIKeyCount(this.Database), "/admin/keys"));
|
||||
|
||||
if (!string.IsNullOrEmpty(command))
|
||||
{
|
||||
|
|
|
@ -21,15 +21,15 @@ public class ModPanelPage : BaseLayout
|
|||
|
||||
this.Statistics.Add(new AdminPanelStatistic(
|
||||
statisticNamePlural: "Reports",
|
||||
count: await StatisticsHelper.ReportCount(),
|
||||
count: await StatisticsHelper.ReportCount(this.Database),
|
||||
viewAllEndpoint: "/moderation/reports/0")
|
||||
);
|
||||
|
||||
this.Statistics.Add(new AdminPanelStatistic(
|
||||
statisticNamePlural: "Cases",
|
||||
count: await StatisticsHelper.DismissedCaseCount(),
|
||||
count: await StatisticsHelper.DismissedCaseCount(this.Database),
|
||||
viewAllEndpoint: "/moderation/cases/0",
|
||||
secondStatistic: await StatisticsHelper.CaseCount())
|
||||
secondStatistic: await StatisticsHelper.CaseCount(this.Database))
|
||||
);
|
||||
|
||||
return this.Page();
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Net.Http;
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using LBPUnion.ProjectLighthouse;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.PlayerData;
|
||||
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
|
||||
|
@ -47,14 +48,16 @@ public class MatchTests : LighthouseServerTest<GameServerTestStartup>
|
|||
|
||||
await semaphore.WaitAsync();
|
||||
|
||||
int oldPlayerCount = await StatisticsHelper.RecentMatches();
|
||||
await using Database database = new();
|
||||
|
||||
int oldPlayerCount = await StatisticsHelper.RecentMatches(database);
|
||||
|
||||
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest
|
||||
("LITTLEBIGPLANETPS3_XML/match", Encoding.ASCII.GetBytes("[UpdateMyPlayerData,[\"Player\":\"1984\"]]"), loginResult.AuthTicket);
|
||||
|
||||
Assert.True(result.IsSuccessStatusCode);
|
||||
|
||||
int playerCount = await StatisticsHelper.RecentMatches();
|
||||
int playerCount = await StatisticsHelper.RecentMatches(database);
|
||||
|
||||
semaphore.Release();
|
||||
Assert.Equal(oldPlayerCount + 1, playerCount);
|
||||
|
|
|
@ -9,7 +9,6 @@ using LBPUnion.ProjectLighthouse.Configuration;
|
|||
using LBPUnion.ProjectLighthouse.Extensions;
|
||||
using LBPUnion.ProjectLighthouse.Logging;
|
||||
using LBPUnion.ProjectLighthouse.PlayerData;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers;
|
||||
|
||||
|
@ -27,20 +26,21 @@ public static class InfluxHelper
|
|||
GameVersion.LittleBigPlanetPSP,
|
||||
};
|
||||
|
||||
public static async void Log()
|
||||
private static async void Log()
|
||||
{
|
||||
try
|
||||
{
|
||||
await using Database database = new();
|
||||
using WriteApi writeApi = Client.GetWriteApi();
|
||||
PointData point = PointData.Measurement("lighthouse")
|
||||
.Field("playerCount", await StatisticsHelper.RecentMatches())
|
||||
.Field("slotCount", await StatisticsHelper.SlotCount());
|
||||
.Field("playerCount", await StatisticsHelper.RecentMatches(database))
|
||||
.Field("slotCount", await StatisticsHelper.SlotCount(database));
|
||||
|
||||
foreach (GameVersion gameVersion in gameVersions)
|
||||
{
|
||||
PointData gamePoint = PointData.Measurement("lighthouse")
|
||||
.Tag("game", gameVersion.ToString())
|
||||
.Field("playerCountGame", await StatisticsHelper.RecentMatchesForGame(gameVersion));
|
||||
.Field("playerCountGame", await StatisticsHelper.RecentMatchesForGame(database, gameVersion));
|
||||
|
||||
writeApi.WritePoint(gamePoint, ServerConfiguration.Instance.InfluxDB.Bucket, ServerConfiguration.Instance.InfluxDB.Organization);
|
||||
}
|
||||
|
|
|
@ -1,35 +1,36 @@
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using LBPUnion.ProjectLighthouse.Administration;
|
||||
using LBPUnion.ProjectLighthouse.Extensions;
|
||||
using LBPUnion.ProjectLighthouse.Levels;
|
||||
using LBPUnion.ProjectLighthouse.PlayerData;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Helpers;
|
||||
|
||||
public static class StatisticsHelper
|
||||
{
|
||||
private static readonly Database database = new();
|
||||
|
||||
public static async Task<int> RecentMatches() => await database.LastContacts.Where(l => TimeHelper.Timestamp - l.Timestamp < 300).CountAsync();
|
||||
public static async Task<int> RecentMatches(Database database) => await database.LastContacts.Where(l => TimeHelper.Timestamp - l.Timestamp < 300).CountAsync();
|
||||
|
||||
public static async Task<int> RecentMatchesForGame(GameVersion gameVersion)
|
||||
public static async Task<int> RecentMatchesForGame(Database database, GameVersion gameVersion)
|
||||
=> await database.LastContacts.Where(l => TimeHelper.Timestamp - l.Timestamp < 300 && l.GameVersion == gameVersion).CountAsync();
|
||||
|
||||
public static async Task<int> SlotCount() => await database.Slots.Where(s => s.Type == SlotType.User).CountAsync();
|
||||
public static async Task<int> SlotCount(Database database) => await database.Slots.Where(s => s.Type == SlotType.User).CountAsync();
|
||||
|
||||
public static async Task<int> UserCount() => await database.Users.CountAsync(u => u.PermissionLevel != PermissionLevel.Banned);
|
||||
public static async Task<int> SlotCountForGame(Database database, GameVersion gameVersion, bool includeSublevels = false) => await database.Slots.ByGameVersion(gameVersion, includeSublevels).CountAsync();
|
||||
|
||||
public static async Task<int> TeamPickCount() => await database.Slots.CountAsync(s => s.TeamPick);
|
||||
public static async Task<int> UserCount(Database database) => await database.Users.CountAsync(u => u.PermissionLevel != PermissionLevel.Banned);
|
||||
|
||||
public static async Task<int> PhotoCount() => await database.Photos.CountAsync();
|
||||
public static async Task<int> TeamPickCount(Database database) => await database.Slots.CountAsync(s => s.TeamPick);
|
||||
|
||||
public static async Task<int> PhotoCount(Database database) => await database.Photos.CountAsync();
|
||||
|
||||
#region Moderator/Admin specific
|
||||
public static async Task<int> ReportCount() => await database.Reports.CountAsync();
|
||||
public static async Task<int> CaseCount() => await database.Cases.CountAsync();
|
||||
public static async Task<int> DismissedCaseCount() => await database.Cases.CountAsync(c => c.DismissedAt != null);
|
||||
public static async Task<int> ReportCount(Database database) => await database.Reports.CountAsync();
|
||||
public static async Task<int> CaseCount(Database database) => await database.Cases.CountAsync();
|
||||
public static async Task<int> DismissedCaseCount(Database database) => await database.Cases.CountAsync(c => c.DismissedAt != null);
|
||||
#endregion
|
||||
|
||||
public static async Task<int> APIKeyCount() => await database.APIKeys.CountAsync();
|
||||
public static async Task<int> APIKeyCount(Database database) => await database.APIKeys.CountAsync();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue