diff --git a/src/BUTR.Site.NexusMods.Server.CrashReport.v13/BUTR.Site.NexusMods.Server.CrashReport.v13.csproj b/src/BUTR.Site.NexusMods.Server.CrashReport.v13/BUTR.Site.NexusMods.Server.CrashReport.v13.csproj new file mode 100644 index 00000000..ac555a68 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.CrashReport.v13/BUTR.Site.NexusMods.Server.CrashReport.v13.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + + + + + + + + + + + + + diff --git a/src/BUTR.Site.NexusMods.Server.CrashReport.v13/CrashReportV13.cs b/src/BUTR.Site.NexusMods.Server.CrashReport.v13/CrashReportV13.cs new file mode 100644 index 00000000..ccca862f --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.CrashReport.v13/CrashReportV13.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text.Json; +using BUTR.CrashReport.Models; +using BUTR.Site.NexusMods.Server.Extensions; +using BUTR.Site.NexusMods.Server.Models; +using BUTR.Site.NexusMods.Server.Models.Database; +using BUTR.Site.NexusMods.Server.Repositories; + +namespace BUTR.Site.NexusMods.Server.CrashReport.v13; + +public static class CrashReportV13 +{ + private static ExceptionTypeId FromException(ExceptionModel exception) + { + var exc = exception; + while (exc.InnerException is not null) + exc = exc.InnerException; + + return ExceptionTypeId.From(exc.Type); + } + + private static string GetException(ExceptionModel? exception, bool inner = false) => exception is null ? string.Empty : $""" + +{(inner ? "Inner " : string.Empty)}Exception information +Type: {exception.Type} +Message: {exception.Message} +CallStack: +{exception.CallStack} + +{GetException(exception.InnerException, true)} +"""; + + public static bool TryFromJson( + IUnitOfWrite unitOfWrite, + TenantId tenant, + CrashReportFileId fileId, + CrashReportUrl url, + DateTime date, + byte version, + string content, + [NotNullWhen(true)] out CrashReportEntity? crashReportEntity, + [NotNullWhen(true)] out CrashReportToMetadataEntity? crashReportToMetadataEntity, + [NotNullWhen(true)] out IList? crashReportToModuleMetadataEntities) + { + if (version != 13) + { + crashReportEntity = null!; + crashReportToMetadataEntity = null!; + crashReportToModuleMetadataEntities = null!; + return false; + } + + var report = JsonSerializer.Deserialize(content); + if (report is null) + { + crashReportEntity = null!; + crashReportToMetadataEntity = null!; + crashReportToModuleMetadataEntities = null!; + return false; + } + + var butrLoaderVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "BUTRLoaderVersion")?.Value; + var blseVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "BLSEVersion")?.Value; + var launcherExVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "LauncherExVersion")?.Value; + + var crashReportId = CrashReportId.From(report.Id); + crashReportEntity = new CrashReportEntity + { + TenantId = tenant, + CrashReportId = crashReportId, + Url = url, + Version = CrashReportVersion.From(report.Version), + GameVersion = GameVersion.From(report.Metadata.GameVersion), + ExceptionTypeId = FromException(report.Exception), + ExceptionType = unitOfWrite.UpsertEntityFactory.GetOrCreateExceptionType(FromException(report.Exception)), + Exception = GetException(report.Exception), + CreatedAt = fileId.Value.Length == 8 ? DateTimeOffset.UnixEpoch.ToUniversalTime() : date.ToUniversalTime(), + }; + crashReportToMetadataEntity = new CrashReportToMetadataEntity + { + TenantId = tenant, + CrashReportId = crashReportId, + LauncherType = string.IsNullOrEmpty(report.Metadata.LauncherType) ? null : report.Metadata.LauncherType, + LauncherVersion = string.IsNullOrEmpty(report.Metadata.LauncherVersion) ? null : report.Metadata.LauncherVersion, + Runtime = string.IsNullOrEmpty(report.Metadata.Runtime) ? null : report.Metadata.Runtime, + BUTRLoaderVersion = butrLoaderVersion, + BLSEVersion = blseVersion, + LauncherExVersion = launcherExVersion, + OperatingSystemType = null, + OperatingSystemVersion = null, + }; + crashReportToModuleMetadataEntities = report.Modules.DistinctBy(x => new { x.Id }).Select(x => new CrashReportToModuleMetadataEntity + { + TenantId = tenant, + CrashReportId = crashReportId, + ModuleId = ModuleId.From(x.Id), + Module = unitOfWrite.UpsertEntityFactory.GetOrCreateModule(ModuleId.From(x.Id)), + Version = ModuleVersion.From(x.Version), + NexusModsModId = NexusModsModId.TryParseUrl(x.Url, out var modId1) ? modId1 : null, + NexusModsMod = NexusModsModId.TryParseUrl(x.Url, out var modId2) ? unitOfWrite.UpsertEntityFactory.GetOrCreateNexusModsMod(modId2) : null, + InvolvedPosition = (byte) (report.InvolvedModules.IndexOf(y => y.ModuleOrLoaderPluginId == x.Id) + 1), + IsInvolved = report.InvolvedModules.Any(y => y.ModuleOrLoaderPluginId == x.Id), + }).ToArray(); + + return true; + } +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.CrashReport.v14/BUTR.Site.NexusMods.Server.CrashReport.v14.csproj b/src/BUTR.Site.NexusMods.Server.CrashReport.v14/BUTR.Site.NexusMods.Server.CrashReport.v14.csproj new file mode 100644 index 00000000..7b38ecc2 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.CrashReport.v14/BUTR.Site.NexusMods.Server.CrashReport.v14.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + + + + + + + + + + + + + diff --git a/src/BUTR.Site.NexusMods.Server.CrashReport.v14/CrashReportV14.cs b/src/BUTR.Site.NexusMods.Server.CrashReport.v14/CrashReportV14.cs new file mode 100644 index 00000000..da48f9b5 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.CrashReport.v14/CrashReportV14.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text.Json; +using BUTR.CrashReport.Bannerlord.Parser; +using BUTR.CrashReport.Models; +using BUTR.Site.NexusMods.Server.Extensions; +using BUTR.Site.NexusMods.Server.Models; +using BUTR.Site.NexusMods.Server.Models.Database; +using BUTR.Site.NexusMods.Server.Repositories; + +namespace BUTR.Site.NexusMods.Server.CrashReport.v14; + +public static class CrashReportV14 +{ + private static ExceptionTypeId FromException(ExceptionModel exception) + { + var exc = exception; + while (exc.InnerException is not null) + exc = exc.InnerException; + + return ExceptionTypeId.From(exc.Type); + } + + private static string GetException(ExceptionModel? exception, bool inner = false) => exception is null ? string.Empty : $""" + +{(inner ? "Inner " : string.Empty)}Exception information +Type: {exception.Type} +Message: {exception.Message} +CallStack: +{exception.CallStack} + +{GetException(exception.InnerException, true)} +"""; + + public static bool TryFromHtml( + IUnitOfWrite unitOfWrite, + TenantId tenant, + CrashReportFileId fileId, + CrashReportUrl url, + DateTime date, + byte version, + string content, + [NotNullWhen(true)] out CrashReportEntity? crashReportEntity, + [NotNullWhen(true)] out CrashReportToMetadataEntity? crashReportToMetadataEntity, + [NotNullWhen(true)] out IList? crashReportToModuleMetadataEntities) + { + var report = CrashReportParser.ParseLegacyHtml(version, content); + if (report is null) + { + crashReportEntity = null!; + crashReportToMetadataEntity = null!; + crashReportToModuleMetadataEntities = null!; + return false; + } + return TryFromModel(unitOfWrite, tenant, fileId, url, date, report, out crashReportEntity, out crashReportToMetadataEntity, out crashReportToModuleMetadataEntities); + } + + public static bool TryFromJson( + IUnitOfWrite unitOfWrite, + TenantId tenant, + CrashReportFileId fileId, + CrashReportUrl url, + DateTime date, + byte version, + string content, + [NotNullWhen(true)] out CrashReportEntity? crashReportEntity, + [NotNullWhen(true)] out CrashReportToMetadataEntity? crashReportToMetadataEntity, + [NotNullWhen(true)] out IList? crashReportToModuleMetadataEntities) + { + if (version != 14) + { + crashReportEntity = null!; + crashReportToMetadataEntity = null!; + crashReportToModuleMetadataEntities = null!; + return false; + } + + var report = JsonSerializer.Deserialize(content); + if (report is null) + { + crashReportEntity = null!; + crashReportToMetadataEntity = null!; + crashReportToModuleMetadataEntities = null!; + return false; + } + + return TryFromModel(unitOfWrite, tenant, fileId, url, date, report, out crashReportEntity, out crashReportToMetadataEntity, out crashReportToModuleMetadataEntities); + } + public static bool TryFromModel( + IUnitOfWrite unitOfWrite, + TenantId tenant, + CrashReportFileId fileId, + CrashReportUrl url, + DateTime date, + CrashReportModel report, + [NotNullWhen(true)] out CrashReportEntity? crashReportEntity, + [NotNullWhen(true)] out CrashReportToMetadataEntity? crashReportToMetadataEntity, + [NotNullWhen(true)] out IList? crashReportToModuleMetadataEntities) + { + var butrLoaderVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "BUTRLoaderVersion")?.Value; + var blseVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "BLSEVersion")?.Value; + var launcherExVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "LauncherExVersion")?.Value; + + var crashReportId = CrashReportId.From(report.Id); + crashReportEntity = new CrashReportEntity + { + TenantId = tenant, + CrashReportId = crashReportId, + Url = url, + Version = CrashReportVersion.From(report.Version), + GameVersion = GameVersion.From(report.Metadata.GameVersion), + ExceptionTypeId = FromException(report.Exception), + ExceptionType = unitOfWrite.UpsertEntityFactory.GetOrCreateExceptionType(FromException(report.Exception)), + Exception = GetException(report.Exception), + CreatedAt = fileId.Value.Length == 8 ? DateTimeOffset.UnixEpoch.ToUniversalTime() : date.ToUniversalTime(), + }; + crashReportToMetadataEntity = new CrashReportToMetadataEntity + { + TenantId = tenant, + CrashReportId = crashReportId, + LauncherType = string.IsNullOrEmpty(report.Metadata.LauncherType) ? null : report.Metadata.LauncherType, + LauncherVersion = string.IsNullOrEmpty(report.Metadata.LauncherVersion) ? null : report.Metadata.LauncherVersion, + Runtime = string.IsNullOrEmpty(report.Metadata.Runtime) ? null : report.Metadata.Runtime, + BUTRLoaderVersion = butrLoaderVersion, + BLSEVersion = blseVersion, + LauncherExVersion = launcherExVersion, + OperatingSystemType = report.Metadata.OperatingSystemType.ToString(), + OperatingSystemVersion = report.Metadata.OperatingSystemVersion, + }; + crashReportToModuleMetadataEntities = report.Modules.DistinctBy(x => new { x.Id }).Select(x => new CrashReportToModuleMetadataEntity + { + TenantId = tenant, + CrashReportId = crashReportId, + ModuleId = ModuleId.From(x.Id), + Module = unitOfWrite.UpsertEntityFactory.GetOrCreateModule(ModuleId.From(x.Id)), + Version = ModuleVersion.From(x.Version), + NexusModsModId = NexusModsModId.TryParseUrl(x.Url, out var modId1) ? modId1 : null, + NexusModsMod = NexusModsModId.TryParseUrl(x.Url, out var modId2) ? unitOfWrite.UpsertEntityFactory.GetOrCreateNexusModsMod(modId2) : null, + InvolvedPosition = (byte) (report.InvolvedModules.IndexOf(y => y.ModuleOrLoaderPluginId == x.Id) + 1), + IsInvolved = report.InvolvedModules.Any(y => y.ModuleOrLoaderPluginId == x.Id), + }).ToArray(); + + return true; + } +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/BUTR.Site.NexusMods.Server.Persistence.csproj b/src/BUTR.Site.NexusMods.Server.Persistence/BUTR.Site.NexusMods.Server.Persistence.csproj new file mode 100644 index 00000000..66b35fac --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/BUTR.Site.NexusMods.Server.Persistence.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + enable + latest + + + + + + + + + + + + + + + + diff --git a/src/BUTR.Site.NexusMods.Server/Models/Filtering.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/API/Filtering.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Filtering.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/API/Filtering.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/FilteringType.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/API/FilteringType.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/FilteringType.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/API/FilteringType.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/API/PaginatedQuery.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/API/PaginatedQuery.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/API/PaginatedQuery.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/API/PaginatedQuery.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/API/PagingMetadata.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/API/PagingMetadata.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/API/PagingMetadata.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/API/PagingMetadata.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Sorting.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/API/Sorting.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Sorting.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/API/Sorting.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/SortingType.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/API/SortingType.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/SortingType.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/API/SortingType.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/AutocompleteEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/AutocompleteEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/AutocompleteEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/AutocompleteEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/CrashReportEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/CrashReportEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/CrashReportEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/CrashReportEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/CrashReportIgnoredFileEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/CrashReportIgnoredFileEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/CrashReportIgnoredFileEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/CrashReportIgnoredFileEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/CrashReportStatus.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/CrashReportStatus.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/CrashReportStatus.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/CrashReportStatus.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/CrashReportToFileIdEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/CrashReportToFileIdEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/CrashReportToFileIdEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/CrashReportToFileIdEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/CrashReportToMetadataEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/CrashReportToMetadataEntity.cs similarity index 86% rename from src/BUTR.Site.NexusMods.Server/Models/Database/CrashReportToMetadataEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/CrashReportToMetadataEntity.cs index fddcbd0e..fa9c9d96 100644 --- a/src/BUTR.Site.NexusMods.Server/Models/Database/CrashReportToMetadataEntity.cs +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/CrashReportToMetadataEntity.cs @@ -18,6 +18,10 @@ public sealed record CrashReportToMetadataEntity : IEntityWithTenant public required string? BLSEVersion { get; init; } public required string? LauncherExVersion { get; init; } + + public required string? OperatingSystemType { get; init; } + public required string? OperatingSystemVersion { get; init; } + public override int GetHashCode() => HashCode.Combine(TenantId, CrashReportId, LauncherType, LauncherVersion, Runtime, BUTRLoaderVersion, BLSEVersion, LauncherExVersion); } \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/CrashReportToModuleMetadataEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/CrashReportToModuleMetadataEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/CrashReportToModuleMetadataEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/CrashReportToModuleMetadataEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/ExceptionTypeEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/ExceptionTypeEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/ExceptionTypeEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/ExceptionTypeEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/IEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/IEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/IEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/IEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/IEntityWithTenant.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/IEntityWithTenant.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/IEntityWithTenant.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/IEntityWithTenant.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/IntegrationDiscordTokensEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/IntegrationDiscordTokensEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/IntegrationDiscordTokensEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/IntegrationDiscordTokensEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/IntegrationGOGToOwnedTenantEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/IntegrationGOGToOwnedTenantEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/IntegrationGOGToOwnedTenantEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/IntegrationGOGToOwnedTenantEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/IntegrationGOGTokensEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/IntegrationGOGTokensEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/IntegrationGOGTokensEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/IntegrationGOGTokensEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/IntegrationGitHubTokensEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/IntegrationGitHubTokensEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/IntegrationGitHubTokensEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/IntegrationGitHubTokensEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/IntegrationSteamToOwnedTenantEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/IntegrationSteamToOwnedTenantEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/IntegrationSteamToOwnedTenantEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/IntegrationSteamToOwnedTenantEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/IntegrationSteamTokensEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/IntegrationSteamTokensEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/IntegrationSteamTokensEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/IntegrationSteamTokensEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/Json/ApplicationVersionRangeModel.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/Json/ApplicationVersionRangeModel.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/Json/ApplicationVersionRangeModel.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/Json/ApplicationVersionRangeModel.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/Json/DependentModuleModel.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/Json/DependentModuleModel.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/Json/DependentModuleModel.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/Json/DependentModuleModel.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/Json/ModuleInfoModel.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/Json/ModuleInfoModel.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/Json/ModuleInfoModel.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/Json/ModuleInfoModel.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/Json/SubModuleInfoModel.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/Json/SubModuleInfoModel.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/Json/SubModuleInfoModel.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/Json/SubModuleInfoModel.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/Json/SubModuleInfoTagModel.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/Json/SubModuleInfoTagModel.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/Json/SubModuleInfoTagModel.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/Json/SubModuleInfoTagModel.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/ModuleEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/ModuleEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/ModuleEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/ModuleEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsArticleEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsArticleEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsArticleEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsArticleEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModToFileUpdateEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModToFileUpdateEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModToFileUpdateEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModToFileUpdateEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModToModuleEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModToModuleEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModToModuleEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModToModuleEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModToModuleInfoHistoryEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModToModuleInfoHistoryEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModToModuleInfoHistoryEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModToModuleInfoHistoryEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModToModuleInfoHistoryGameVersionEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModToModuleInfoHistoryGameVersionEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModToModuleInfoHistoryGameVersionEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModToModuleInfoHistoryGameVersionEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModToModuleLinkType.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModToModuleLinkType.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModToModuleLinkType.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModToModuleLinkType.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModToNameEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModToNameEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsModToNameEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsModToNameEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToCrashReportEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToCrashReportEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToCrashReportEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToCrashReportEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToIntegrationDiscordEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToIntegrationDiscordEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToIntegrationDiscordEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToIntegrationDiscordEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToIntegrationGOGEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToIntegrationGOGEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToIntegrationGOGEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToIntegrationGOGEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToIntegrationGitHubEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToIntegrationGitHubEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToIntegrationGitHubEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToIntegrationGitHubEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToIntegrationSteamEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToIntegrationSteamEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToIntegrationSteamEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToIntegrationSteamEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToModuleEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToModuleEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToModuleEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToModuleEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToModuleLinkType.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToModuleLinkType.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToModuleLinkType.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToModuleLinkType.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToNameEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToNameEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToNameEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToNameEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToNexusModsModEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToNexusModsModEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToNexusModsModEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToNexusModsModEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToNexusModsModLinkType.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToNexusModsModLinkType.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToNexusModsModLinkType.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToNexusModsModLinkType.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToRoleEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToRoleEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/NexusModsUserToRoleEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/NexusModsUserToRoleEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/Paging.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/Paging.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/Paging.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/Paging.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/QuartzExecutionLogDetailEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/QuartzExecutionLogDetailEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/QuartzExecutionLogDetailEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/QuartzExecutionLogDetailEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/QuartzExecutionLogEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/QuartzExecutionLogEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/QuartzExecutionLogEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/QuartzExecutionLogEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/StatisticsCrashScoreInvolvedEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/StatisticsCrashScoreInvolvedEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/StatisticsCrashScoreInvolvedEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/StatisticsCrashScoreInvolvedEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/StatisticsTopExceptionsTypeEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/StatisticsTopExceptionsTypeEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/StatisticsTopExceptionsTypeEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/StatisticsTopExceptionsTypeEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server/Models/Database/TenantEntity.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Entities/TenantEntity.cs similarity index 100% rename from src/BUTR.Site.NexusMods.Server/Models/Database/TenantEntity.cs rename to src/BUTR.Site.NexusMods.Server.Persistence/Entities/TenantEntity.cs diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Extensions/IAsyncEnumerableExtensions.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Extensions/IAsyncEnumerableExtensions.cs new file mode 100644 index 00000000..ce2f8955 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Extensions/IAsyncEnumerableExtensions.cs @@ -0,0 +1,33 @@ +using JetBrains.Annotations; + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Extensions; + +/// +/// Provides extension methods for objects. +/// +public static class IAsyncEnumerableExtensions +{ + public static int IndexOf(this IEnumerable source, Predicate predicate) + { + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(predicate); + + var index = 0; + foreach (var item in source) + { + if (predicate(item)) + return index; + + index += 1; + } + + return -1; + } +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/IRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/IRepository.cs new file mode 100644 index 00000000..2f5fcac7 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/IRepository.cs @@ -0,0 +1,79 @@ +using BUTR.Site.NexusMods.Server.Models; +using BUTR.Site.NexusMods.Server.Models.API; +using BUTR.Site.NexusMods.Server.Models.Database; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +/// +/// Marker interface for repositories. +/// +public interface IRepository; + +public interface IRepositoryRead : IRepository where TEntity : class, IEntity +{ + Task FirstOrDefaultAsync( + Expression>? filter, + Func, IOrderedQueryable>? orderBy, + CancellationToken ct); + Task FirstOrDefaultAsync( + Expression>? filter, + Func, IOrderedQueryable>? orderBy, + Expression> projection, + CancellationToken ct); + + Task LastOrDefaultAsync( + Expression>? filter, + Func, IOrderedQueryable>? orderBy, + CancellationToken ct); + Task LastOrDefaultAsync( + Expression>? filter, + Func, IOrderedQueryable>? orderBy, + Expression> projection, + CancellationToken ct); + + Task> GetAllAsync( + Expression>? filter, + Func, IOrderedQueryable>? orderBy, + CancellationToken ct); + Task> GetAllAsync( + Expression>? filter, + Func, IOrderedQueryable>? orderBy, + Expression> projection, + CancellationToken ct); + + Task> PaginatedAsync( + PaginatedQuery query, + uint maxPageSize = 20, + Sorting? defaultSorting = default, + CancellationToken ct = default); + + Task> PaginatedAsync( + Expression> projection, + PaginatedQuery query, + uint maxPageSize = 20, + Sorting? defaultSorting = default, + CancellationToken ct = default) where TProjection : class; +} + +public interface IRepositoryWrite : IRepositoryRead where TEntity : class, IEntity +{ + void Add(TEntity entity); + void AddRange(IEnumerable entities); + + void Update(TEntity originalEntity, TEntity currentEntity); + + void Upsert(TEntity entity); + void UpsertRange(IEnumerable entities); + + void Remove(TEntity entity); + void RemoveRange(IEnumerable entities); + + int Remove(Expression> filter); +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/IUnitOfRead.cs b/src/BUTR.Site.NexusMods.Server.Persistence/IUnitOfRead.cs new file mode 100644 index 00000000..10aaff99 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/IUnitOfRead.cs @@ -0,0 +1,48 @@ +using System; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IUnitOfRead : IDisposable, IAsyncDisposable +{ + IAutocompleteEntityRepositoryRead Autocompletes { get; } + + IQuartzExecutionLogEntityRepositoryRead QuartzExecutionLogs { get; } + + IExceptionTypeRepositoryRead ExceptionTypes { get; } + + ICrashReportEntityRepositoryRead CrashReports { get; } + ICrashReportToMetadataEntityRepositoryRead CrashReportToMetadatas { get; } + ICrashReportToModuleMetadataEntityRepositoryRead CrashReportModuleInfos { get; } + ICrashReportToFileIdEntityRepositoryRead CrashReportToFileIds { get; } + ICrashReportIgnoredFileEntityRepositoryRead CrashReportIgnoredFileIds { get; } + + IStatisticsTopExceptionsTypeEntityRepositoryRead StatisticsTopExceptionsTypes { get; } + IStatisticsCrashScoreInvolvedEntityRepositoryRead StatisticsCrashScoreInvolveds { get; } + + INexusModsArticleEntityRepositoryRead NexusModsArticles { get; } + + INexusModsModToModuleEntityRepositoryRead NexusModsModModules { get; } + INexusModsModToNameEntityRepositoryRead NexusModsModName { get; } + + INexusModsModToModuleInfoHistoryEntityRepositoryRead NexusModsModToModuleInfoHistory { get; } + INexusModsModToFileUpdateEntityRepositoryRead NexusModsModToFileUpdates { get; } + + INexusModsUserRepositoryRead NexusModsUsers { get; } + INexusModsUserToNameEntityRepositoryRead NexusModsUserToName { get; } + INexusModsUserToCrashReportEntityRepositoryRead NexusModsUserToCrashReports { get; } + INexusModsUserToNexusModsModEntityRepositoryRead NexusModsUserToNexusModsMods { get; } + INexusModsUserToModuleEntityRepositoryRead NexusModsUserToModules { get; } + + + INexusModsUserToIntegrationGitHubEntityRepositoryRead NexusModsUserToGitHub { get; } + INexusModsUserToIntegrationDiscordEntityRepositoryRead NexusModsUserToDiscord { get; } + INexusModsUserToIntegrationGOGEntityRepositoryRead NexusModsUserToGOG { get; } + INexusModsUserToIntegrationSteamEntityRepositoryRead NexusModsUserToSteam { get; } + + IIntegrationGitHubTokensEntityRepositoryRead IntegrationGitHubTokens { get; } + IIntegrationDiscordTokensEntityRepositoryRead IntegrationDiscordTokens { get; } + IIntegrationGOGTokensEntityRepositoryRead IntegrationGOGTokens { get; } + IIntegrationGOGToOwnedTenantEntityRepositoryRead IntegrationGOGToOwnedTenants { get; } + IIntegrationSteamTokensEntityRepositoryRead IntegrationSteamTokens { get; } + IIntegrationSteamToOwnedTenantEntityRepositoryRead IntegrationSteamToOwnedTenants { get; } +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/IUnitOfWorkFactory.cs b/src/BUTR.Site.NexusMods.Server.Persistence/IUnitOfWorkFactory.cs new file mode 100644 index 00000000..7cb6a421 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/IUnitOfWorkFactory.cs @@ -0,0 +1,12 @@ +using BUTR.Site.NexusMods.Server.Models; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IUnitOfWorkFactory +{ + IUnitOfRead CreateUnitOfRead(); + IUnitOfRead CreateUnitOfRead(TenantId tenant); + + IUnitOfWrite CreateUnitOfWrite(); + IUnitOfWrite CreateUnitOfWrite(TenantId tenant); +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/IUnitOfWrite.cs b/src/BUTR.Site.NexusMods.Server.Persistence/IUnitOfWrite.cs new file mode 100644 index 00000000..0f67a7d9 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/IUnitOfWrite.cs @@ -0,0 +1,52 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IUnitOfWrite : IDisposable, IAsyncDisposable +{ + IUpsertEntityFactory UpsertEntityFactory { get; } + + IAutocompleteEntityRepositoryWrite Autocompletes { get; } + + IQuartzExecutionLogEntityRepositoryWrite QuartzExecutionLogs { get; } + + IExceptionTypeRepositoryWrite ExceptionTypes { get; } + + ICrashReportEntityRepositoryWrite CrashReports { get; } + ICrashReportToMetadataEntityRepositoryWrite CrashReportToMetadatas { get; } + ICrashReportToModuleMetadataEntityRepositoryWrite CrashReportModuleInfos { get; } + ICrashReportToFileIdEntityRepositoryWrite CrashReportToFileIds { get; } + ICrashReportIgnoredFileEntityRepositoryWrite CrashReportIgnoredFileIds { get; } + + IStatisticsTopExceptionsTypeEntityRepositoryWrite StatisticsTopExceptionsTypes { get; } + IStatisticsCrashScoreInvolvedEntityRepositoryWrite StatisticsCrashScoreInvolveds { get; } + + INexusModsArticleEntityRepositoryWrite NexusModsArticles { get; } + + INexusModsModToModuleEntityRepositoryWrite NexusModsModModules { get; } + INexusModsModToNameEntityRepositoryWrite NexusModsModName { get; } + INexusModsModToModuleInfoHistoryEntityRepositoryWrite NexusModsModToModuleInfoHistory { get; } + INexusModsModToFileUpdateEntityRepositoryWrite NexusModsModToFileUpdates { get; } + + INexusModsUserRepositoryWrite NexusModsUsers { get; } + INexusModsUserToNameEntityRepositoryWrite NexusModsUserToName { get; } + INexusModsUserToCrashReportEntityRepositoryWrite NexusModsUserToCrashReports { get; } + INexusModsUserToNexusModsModEntityRepositoryWrite NexusModsUserToNexusModsMods { get; } + INexusModsUserToModuleEntityRepositoryWrite NexusModsUserToModules { get; } + + INexusModsUserToIntegrationGitHubEntityRepositoryWrite NexusModsUserToGitHub { get; } + INexusModsUserToIntegrationDiscordEntityRepositoryWrite NexusModsUserToDiscord { get; } + INexusModsUserToIntegrationGOGEntityRepositoryWrite NexusModsUserToGOG { get; } + INexusModsUserToIntegrationSteamEntityRepositoryWrite NexusModsUserToSteam { get; } + + IIntegrationGitHubTokensEntityRepositoryWrite IntegrationGitHubTokens { get; } + IIntegrationDiscordTokensEntityRepositoryWrite IntegrationDiscordTokens { get; } + IIntegrationGOGTokensEntityRepositoryWrite IntegrationGOGTokens { get; } + IIntegrationGOGToOwnedTenantEntityRepositoryWrite IntegrationGOGToOwnedTenants { get; } + IIntegrationSteamTokensEntityRepositoryWrite IntegrationSteamTokens { get; } + IIntegrationSteamToOwnedTenantEntityRepositoryWrite IntegrationSteamToOwnedTenants { get; } + + Task SaveChangesAsync(CancellationToken ct); +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/IUpsertEntityFactory.cs b/src/BUTR.Site.NexusMods.Server.Persistence/IUpsertEntityFactory.cs new file mode 100644 index 00000000..a19e2c72 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/IUpsertEntityFactory.cs @@ -0,0 +1,16 @@ +using System.Threading; +using System.Threading.Tasks; +using BUTR.Site.NexusMods.Server.Models; +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IUpsertEntityFactory +{ + NexusModsUserEntity GetOrCreateNexusModsUser(NexusModsUserId nexusModsUserId); + NexusModsUserEntity GetOrCreateNexusModsUserWithName(NexusModsUserId nexusModsUserId, NexusModsUserName nexusModsUserName); + NexusModsModEntity GetOrCreateNexusModsMod(NexusModsModId nexusModsModId); + ModuleEntity GetOrCreateModule(ModuleId moduleId); + ExceptionTypeEntity GetOrCreateExceptionType(ExceptionTypeId exception); + Task SaveCreatedAsync(CancellationToken ct); +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/AutocompleteEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/AutocompleteEntityRepository.cs new file mode 100644 index 00000000..3f6d46a9 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/AutocompleteEntityRepository.cs @@ -0,0 +1,16 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IAutocompleteEntityRepositoryRead : IRepositoryRead +{ + Task> AutocompleteStartsWithAsync(Expression> property, TParameter value, CancellationToken ct) + where TEntity : class, IEntity; +} +public interface IAutocompleteEntityRepositoryWrite : IRepositoryWrite, IAutocompleteEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportEntityRepository.cs new file mode 100644 index 00000000..45bdb6db --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportEntityRepository.cs @@ -0,0 +1,43 @@ +using BUTR.Site.NexusMods.Server.Models; +using BUTR.Site.NexusMods.Server.Models.API; +using BUTR.Site.NexusMods.Server.Models.Database; + +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public sealed record ModuleIdToVersionModel +{ + public required ModuleId ModuleId { get; init; } + public required ModuleVersion Version { get; init; } +} +public sealed record UserCrashReportModel +{ + public required CrashReportId Id { get; init; } + public required CrashReportVersion Version { get; init; } + public required GameVersion GameVersion { get; init; } + public required ExceptionTypeId ExceptionType { get; init; } + public required string Exception { get; init; } + public required DateTimeOffset CreatedAt { get; init; } + //public required ModuleId[] ModuleIds { get; init; } + //public required ModuleIdToVersionModel[] ModuleIdToVersion { get; init; } + public required ModuleId? TopInvolvedModuleId { get; init; } // Used for FE search + public required ModuleId[] InvolvedModuleIds { get; init; } + //public required NexusModsModId[] NexusModsModIds { get; init; } + public required CrashReportUrl Url { get; init; } + + public required CrashReportStatus Status { get; init; } + public required string? Comment { get; init; } +} + +public interface ICrashReportEntityRepositoryRead : IRepositoryRead +{ + Task> GetCrashReportsPaginatedAsync(NexusModsUserEntity user, PaginatedQuery query, ApplicationRole applicationRole, CancellationToken ct); +} + +public interface ICrashReportEntityRepositoryWrite : IRepositoryWrite, ICrashReportEntityRepositoryRead +{ + Task GenerateAutoCompleteForGameVersionsAsync(CancellationToken ct); +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportIgnoredFileEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportIgnoredFileEntityRepository.cs new file mode 100644 index 00000000..fded4cae --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportIgnoredFileEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface ICrashReportIgnoredFileEntityRepositoryRead : IRepositoryRead; +public interface ICrashReportIgnoredFileEntityRepositoryWrite : IRepositoryWrite, ICrashReportIgnoredFileEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportToFileIdEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportToFileIdEntityRepository.cs new file mode 100644 index 00000000..de6dd698 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportToFileIdEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface ICrashReportToFileIdEntityRepositoryRead : IRepositoryRead; +public interface ICrashReportToFileIdEntityRepositoryWrite : IRepositoryWrite, ICrashReportToFileIdEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportToMetadataEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportToMetadataEntityRepository.cs new file mode 100644 index 00000000..e4d80e56 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportToMetadataEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface ICrashReportToMetadataEntityRepositoryRead : IRepositoryRead; +public interface ICrashReportToMetadataEntityRepositoryWrite : IRepositoryWrite, ICrashReportToMetadataEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportToModuleMetadataEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportToModuleMetadataEntityRepository.cs new file mode 100644 index 00000000..4afc8e61 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/CrashReportToModuleMetadataEntityRepository.cs @@ -0,0 +1,30 @@ +using BUTR.Site.NexusMods.Server.Models; +using BUTR.Site.NexusMods.Server.Models.Database; + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public sealed record StatisticsCrashReport +{ + public required GameVersion GameVersion { get; init; } + public required ModuleId ModuleId { get; init; } + public required ModuleVersion ModuleVersion { get; init; } + public required int InvolvedCount { get; init; } + public required int NotInvolvedCount { get; init; } + public required int TotalCount { get; init; } + public required int Value { get; init; } + public required double CrashScore { get; init; } +} + +public interface ICrashReportToModuleMetadataEntityRepositoryRead : IRepositoryRead +{ + Task> GetAllStatisticsAsync(CancellationToken ct); +} + +public interface ICrashReportToModuleMetadataEntityRepositoryWrite : IRepositoryWrite, ICrashReportToModuleMetadataEntityRepositoryRead +{ + Task GenerateAutoCompleteForModuleIdsAsync(CancellationToken ct); +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/ExceptionTypeRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/ExceptionTypeRepository.cs new file mode 100644 index 00000000..7217e547 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/ExceptionTypeRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IExceptionTypeRepositoryRead : IRepositoryRead; +public interface IExceptionTypeRepositoryWrite : IRepositoryWrite, IExceptionTypeRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationDiscordTokensEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationDiscordTokensEntityRepository.cs new file mode 100644 index 00000000..5cbf8fd6 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationDiscordTokensEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IIntegrationDiscordTokensEntityRepositoryRead : IRepositoryRead; +public interface IIntegrationDiscordTokensEntityRepositoryWrite : IRepositoryWrite, IIntegrationDiscordTokensEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationGOGToOwnedTenantEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationGOGToOwnedTenantEntityRepository.cs new file mode 100644 index 00000000..b45cdaa2 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationGOGToOwnedTenantEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IIntegrationGOGToOwnedTenantEntityRepositoryRead : IRepositoryRead; +public interface IIntegrationGOGToOwnedTenantEntityRepositoryWrite : IRepositoryWrite, IIntegrationGOGToOwnedTenantEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationGOGTokensEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationGOGTokensEntityRepository.cs new file mode 100644 index 00000000..9c463923 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationGOGTokensEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IIntegrationGOGTokensEntityRepositoryRead : IRepositoryRead; +public interface IIntegrationGOGTokensEntityRepositoryWrite : IRepositoryWrite, IIntegrationGOGTokensEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationGitHubTokensEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationGitHubTokensEntityRepository.cs new file mode 100644 index 00000000..8cd70012 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationGitHubTokensEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IIntegrationGitHubTokensEntityRepositoryRead : IRepositoryRead; +public interface IIntegrationGitHubTokensEntityRepositoryWrite : IRepositoryWrite, IIntegrationGitHubTokensEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationSteamToOwnedTenantEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationSteamToOwnedTenantEntityRepository.cs new file mode 100644 index 00000000..63483550 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationSteamToOwnedTenantEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IIntegrationSteamToOwnedTenantEntityRepositoryRead : IRepositoryRead; +public interface IIntegrationSteamToOwnedTenantEntityRepositoryWrite : IRepositoryWrite, IIntegrationSteamToOwnedTenantEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationSteamTokensEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationSteamTokensEntityRepository.cs new file mode 100644 index 00000000..26972811 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/IntegrationSteamTokensEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IIntegrationSteamTokensEntityRepositoryRead : IRepositoryRead; +public interface IIntegrationSteamTokensEntityRepositoryWrite : IRepositoryWrite, IIntegrationSteamTokensEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsArticleEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsArticleEntityRepository.cs new file mode 100644 index 00000000..753da7e7 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsArticleEntityRepository.cs @@ -0,0 +1,17 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface INexusModsArticleEntityRepositoryRead : IRepositoryRead +{ + Task> GetAllModuleIdsAsync(string authorName, CancellationToken ct); +} + +public interface INexusModsArticleEntityRepositoryWrite : IRepositoryWrite, INexusModsArticleEntityRepositoryRead +{ + Task GenerateAutoCompleteForAuthorNameAsync(CancellationToken ct); +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsModToFileUpdateEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsModToFileUpdateEntityRepository.cs new file mode 100644 index 00000000..eda4b687 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsModToFileUpdateEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface INexusModsModToFileUpdateEntityRepositoryRead : IRepositoryRead; +public interface INexusModsModToFileUpdateEntityRepositoryWrite : IRepositoryWrite, INexusModsModToFileUpdateEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsModToModuleEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsModToModuleEntityRepository.cs new file mode 100644 index 00000000..60ad0e85 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsModToModuleEntityRepository.cs @@ -0,0 +1,41 @@ +using BUTR.Site.NexusMods.Server.Models; +using BUTR.Site.NexusMods.Server.Models.API; +using BUTR.Site.NexusMods.Server.Models.Database; + +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public sealed record LinkedByStaffNexusModsModModel +{ + public NexusModsModId NexusModsModId { get; init; } + public DateTimeOffset LastCheckedDate { get; init; } +} + +public sealed record LinkedByStaffModuleNexusModsModsModel +{ + public required ModuleId ModuleId { get; init; } + public required LinkedByStaffNexusModsModModel[] NexusModsMods { get; init; } +} + +public sealed record LinkedByExposureModuleModel +{ + public required ModuleId ModuleId { get; init; } + public required DateTimeOffset LastCheckedDate { get; init; } +} + +public sealed record LinkedByExposureNexusModsModModelsModel +{ + public required NexusModsModId NexusModsModId { get; init; } + public required LinkedByExposureModuleModel[] Modules { get; init; } +} + +public interface INexusModsModToModuleEntityRepositoryRead : IRepositoryRead +{ + Task> GetByStaffPaginatedAsync(PaginatedQuery query, CancellationToken ct); + + Task> GetExposedPaginatedAsync(PaginatedQuery query, CancellationToken ct); +} +public interface INexusModsModToModuleEntityRepositoryWrite : IRepositoryWrite, INexusModsModToModuleEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsModToModuleInfoHistoryEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsModToModuleInfoHistoryEntityRepository.cs new file mode 100644 index 00000000..6cd67ef6 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsModToModuleInfoHistoryEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface INexusModsModToModuleInfoHistoryEntityRepositoryRead : IRepositoryRead; +public interface INexusModsModToModuleInfoHistoryEntityRepositoryWrite : IRepositoryWrite, INexusModsModToModuleInfoHistoryEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsModToNameEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsModToNameEntityRepository.cs new file mode 100644 index 00000000..d788fc70 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsModToNameEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface INexusModsModToNameEntityRepositoryRead : IRepositoryRead; +public interface INexusModsModToNameEntityRepositoryWrite : IRepositoryWrite, INexusModsModToNameEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserRepository.cs new file mode 100644 index 00000000..9ace00a0 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserRepository.cs @@ -0,0 +1,38 @@ +using BUTR.Site.NexusMods.Server.Models; +using BUTR.Site.NexusMods.Server.Models.API; +using BUTR.Site.NexusMods.Server.Models.Database; + +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public sealed record UserAvailableModModel +{ + public required NexusModsModId NexusModsModId { get; init; } + public required string Name { get; init; } +} + +public sealed record UserLinkedModModel +{ + public required NexusModsModId NexusModsModId { get; init; } + public required string Name { get; init; } + public required NexusModsUserId[] OwnerNexusModsUserIds { get; init; } + public required NexusModsUserId[] AllowedNexusModsUserIds { get; init; } + public required NexusModsUserId[] ManuallyLinkedNexusModsUserIds { get; init; } + public required ModuleId[] ManuallyLinkedModuleIds { get; init; } + public required ModuleId[] KnownModuleIds { get; init; } +} + +public interface INexusModsUserRepositoryRead : IRepositoryRead +{ + Task GetUserWithIntegrationsAsync(NexusModsUserId userId, CancellationToken ct); + Task GetUserAsync(NexusModsUserId userId, CancellationToken ct); + + Task> GetNexusModsModsPaginatedAsync(NexusModsUserId userId, PaginatedQuery query, CancellationToken ct); + + Task> GetAvailableModsPaginatedAsync(NexusModsUserId userId, PaginatedQuery query, CancellationToken ct); + + Task GetLinkedModCountAsync(NexusModsUserId userId, CancellationToken ct); +} +public interface INexusModsUserRepositoryWrite : IRepositoryWrite, INexusModsUserRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToCrashReportEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToCrashReportEntityRepository.cs new file mode 100644 index 00000000..1cce3e94 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToCrashReportEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface INexusModsUserToCrashReportEntityRepositoryRead : IRepositoryRead; +public interface INexusModsUserToCrashReportEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToCrashReportEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToIntegrationDiscordEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToIntegrationDiscordEntityRepository.cs new file mode 100644 index 00000000..8ab304d1 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToIntegrationDiscordEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface INexusModsUserToIntegrationDiscordEntityRepositoryRead : IRepositoryRead; +public interface INexusModsUserToIntegrationDiscordEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToIntegrationDiscordEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToIntegrationGOGEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToIntegrationGOGEntityRepository.cs new file mode 100644 index 00000000..f0cd2ea3 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToIntegrationGOGEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface INexusModsUserToIntegrationGOGEntityRepositoryRead : IRepositoryRead; +public interface INexusModsUserToIntegrationGOGEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToIntegrationGOGEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToIntegrationGitHubEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToIntegrationGitHubEntityRepository.cs new file mode 100644 index 00000000..ab2185ec --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToIntegrationGitHubEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface INexusModsUserToIntegrationGitHubEntityRepositoryRead : IRepositoryRead; +public interface INexusModsUserToIntegrationGitHubEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToIntegrationGitHubEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToIntegrationSteamEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToIntegrationSteamEntityRepository.cs new file mode 100644 index 00000000..c8242ccd --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToIntegrationSteamEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface INexusModsUserToIntegrationSteamEntityRepositoryRead : IRepositoryRead; +public interface INexusModsUserToIntegrationSteamEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToIntegrationSteamEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToModuleEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToModuleEntityRepository.cs new file mode 100644 index 00000000..e13abe55 --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToModuleEntityRepository.cs @@ -0,0 +1,21 @@ +using BUTR.Site.NexusMods.Server.Models; +using BUTR.Site.NexusMods.Server.Models.API; +using BUTR.Site.NexusMods.Server.Models.Database; + +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public sealed record UserManuallyLinkedModuleModel +{ + public required NexusModsUserId NexusModsUserId { get; init; } + public required NexusModsUserName NexusModsUsername { get; init; } + public required ModuleId[] ModuleIds { get; init; } +} + +public interface INexusModsUserToModuleEntityRepositoryRead : IRepositoryRead +{ + Task> GetManuallyLinkedModuleIdsPaginatedAsync(PaginatedQuery query, NexusModsUserToModuleLinkType linkType, CancellationToken ct); +} +public interface INexusModsUserToModuleEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToModuleEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToNameEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToNameEntityRepository.cs new file mode 100644 index 00000000..9800e74f --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToNameEntityRepository.cs @@ -0,0 +1,6 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface INexusModsUserToNameEntityRepositoryRead : IRepositoryRead; +public interface INexusModsUserToNameEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToNameEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToNexusModsModEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToNexusModsModEntityRepository.cs new file mode 100644 index 00000000..7ee04b7e --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/NexusModsUserToNexusModsModEntityRepository.cs @@ -0,0 +1,25 @@ +using BUTR.Site.NexusMods.Server.Models; +using BUTR.Site.NexusMods.Server.Models.API; +using BUTR.Site.NexusMods.Server.Models.Database; + +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public sealed record UserManuallyLinkedModUserModel +{ + public required NexusModsUserId NexusModsUserId { get; init; } + public required NexusModsUserName NexusModsUsername { get; init; } +} +public sealed record UserManuallyLinkedModModel +{ + public required NexusModsModId NexusModsModId { get; init; } + public required UserManuallyLinkedModUserModel[] NexusModsUsers { get; init; } +} + +public interface INexusModsUserToNexusModsModEntityRepositoryRead : IRepositoryRead +{ + Task> GetManuallyLinkedPaginatedAsync(NexusModsUserId userId, PaginatedQuery query, CancellationToken ct); +} +public interface INexusModsUserToNexusModsModEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToNexusModsModEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/QuartzExecutionLogEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/QuartzExecutionLogEntityRepository.cs new file mode 100644 index 00000000..65f16c3a --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/QuartzExecutionLogEntityRepository.cs @@ -0,0 +1,13 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IQuartzExecutionLogEntityRepositoryRead : IRepositoryRead; + +public interface IQuartzExecutionLogEntityRepositoryWrite : IRepositoryWrite, IQuartzExecutionLogEntityRepositoryRead +{ + Task MarkIncompleteAsync(CancellationToken ct); +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/StatisticsCrashScoreInvolvedEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/StatisticsCrashScoreInvolvedEntityRepository.cs new file mode 100644 index 00000000..102d1dae --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/StatisticsCrashScoreInvolvedEntityRepository.cs @@ -0,0 +1,56 @@ +using BUTR.Site.NexusMods.Server.Models; +using BUTR.Site.NexusMods.Server.Models.Database; + +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public sealed record VersionScoreModel +{ + public required ModuleVersion Version { get; init; } + public required double Score { get; init; } + public required double Value { get; init; } + public required int CountStable { get; init; } + public required int CountUnstable { get; init; } + public double Count => CountStable + CountUnstable; +} +public sealed record VersionStorageModel +{ + public required ModuleVersion Version { get; init; } + public required VersionScoreModel[] Scores { get; init; } + public double MeanScore => Scores.Length == 0 ? 0 : 1 - (Scores.Sum(x => x.Value) / (double) Scores.Sum(x => x.Count)); +}; +public sealed record ModuleStorageModel +{ + public required ModuleId ModuleId { get; init; } + public required VersionStorageModel[] Versions { get; init; } +}; +public sealed record StatisticsInvolvedModuleScoresForGameVersionModel +{ + public required GameVersion GameVersion { get; init; } + public required ModuleStorageModel[] Modules { get; init; } +} + +public sealed record RawScoreForModuleVersionModel +{ + public required ModuleVersion ModuleVersion { get; init; } + public required double RawScore { get; init; } + public required int TotalCount { get; init; } +} + +public sealed record StatisticsRawScoresForModuleModel +{ + public required ModuleId ModuleId { get; init; } + public required RawScoreForModuleVersionModel[] RawScores { get; init; } +} + +public interface IStatisticsCrashScoreInvolvedEntityRepositoryRead : IRepositoryRead +{ + Task> GetAllInvolvedModuleScoresForGameVersionAsync(GameVersion[]? gameVersions, ModuleId[]? moduleIds, ModuleVersion[]? moduleVersions, CancellationToken ct); + Task> GetAllRawScoresForAllModulesAsync(GameVersion gameVersion, ModuleId[] moduleIds, CancellationToken ct); + +} +public interface IStatisticsCrashScoreInvolvedEntityRepositoryWrite : IRepositoryWrite, IStatisticsCrashScoreInvolvedEntityRepositoryRead; \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/StatisticsTopExceptionsTypeEntityRepository.cs b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/StatisticsTopExceptionsTypeEntityRepository.cs new file mode 100644 index 00000000..0173b8db --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server.Persistence/Repositories/StatisticsTopExceptionsTypeEntityRepository.cs @@ -0,0 +1,12 @@ +using BUTR.Site.NexusMods.Server.Models.Database; + +using System.Threading; +using System.Threading.Tasks; + +namespace BUTR.Site.NexusMods.Server.Repositories; + +public interface IStatisticsTopExceptionsTypeEntityRepositoryRead : IRepositoryRead; +public interface IStatisticsTopExceptionsTypeEntityRepositoryWrite : IRepositoryWrite, IStatisticsTopExceptionsTypeEntityRepositoryRead +{ + Task CalculateAsync(CancellationToken ct); +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server.ValueObjects.Vogen/BUTR.Site.NexusMods.Server.ValueObjects.Vogen.csproj b/src/BUTR.Site.NexusMods.Server.ValueObjects.Vogen/BUTR.Site.NexusMods.Server.ValueObjects.Vogen.csproj index 0ae53fc4..b79b3a36 100644 --- a/src/BUTR.Site.NexusMods.Server.ValueObjects.Vogen/BUTR.Site.NexusMods.Server.ValueObjects.Vogen.csproj +++ b/src/BUTR.Site.NexusMods.Server.ValueObjects.Vogen/BUTR.Site.NexusMods.Server.ValueObjects.Vogen.csproj @@ -9,10 +9,9 @@ - - + diff --git a/src/BUTR.Site.NexusMods.Server.ValueObjects.Vogen/Models/ExceptionTypeId.cs b/src/BUTR.Site.NexusMods.Server.ValueObjects.Vogen/Models/ExceptionTypeId.cs index bb06d653..2ee6cdfb 100644 --- a/src/BUTR.Site.NexusMods.Server.ValueObjects.Vogen/Models/ExceptionTypeId.cs +++ b/src/BUTR.Site.NexusMods.Server.ValueObjects.Vogen/Models/ExceptionTypeId.cs @@ -1,5 +1,3 @@ -using BUTR.CrashReport.Models; - namespace BUTR.Site.NexusMods.Server.Models; using TType = ExceptionTypeId; @@ -8,14 +6,6 @@ namespace BUTR.Site.NexusMods.Server.Models; [ValueObject(conversions: Conversions.EfCoreValueConverter | Conversions.SystemTextJson | Conversions.TypeConverter)] public readonly partial struct ExceptionTypeId { - public static TType FromException(ExceptionModel exception) - { - var exc = exception; - while (exc.InnerException is not null) - exc = exc.InnerException; - - return From(exc.Type); - } public static bool TryParseFromException(TValueType exception, out TType value) { Span dest = stackalloc Range[32]; diff --git a/src/BUTR.Site.NexusMods.Server/BUTR.Site.NexusMods.Server.csproj b/src/BUTR.Site.NexusMods.Server/BUTR.Site.NexusMods.Server.csproj index a8a831a3..a01c9b4a 100644 --- a/src/BUTR.Site.NexusMods.Server/BUTR.Site.NexusMods.Server.csproj +++ b/src/BUTR.Site.NexusMods.Server/BUTR.Site.NexusMods.Server.csproj @@ -17,21 +17,16 @@ - - - + - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + @@ -70,6 +65,9 @@ + + + diff --git a/src/BUTR.Site.NexusMods.Server/Contexts/Configs/CrashReportToMetadataEntityConfiguration.cs b/src/BUTR.Site.NexusMods.Server/Contexts/Configs/CrashReportToMetadataEntityConfiguration.cs index 276b57e4..173ec6e4 100644 --- a/src/BUTR.Site.NexusMods.Server/Contexts/Configs/CrashReportToMetadataEntityConfiguration.cs +++ b/src/BUTR.Site.NexusMods.Server/Contexts/Configs/CrashReportToMetadataEntityConfiguration.cs @@ -19,6 +19,8 @@ protected override void ConfigureModel(EntityTypeBuilder x.BUTRLoaderVersion).HasColumnName("butrloader_version"); builder.Property(x => x.BLSEVersion).HasColumnName("blse_version"); builder.Property(x => x.LauncherExVersion).HasColumnName("launcherex_version"); + builder.Property(x => x.OperatingSystemType).HasColumnName("operating_system_type"); + builder.Property(x => x.OperatingSystemVersion).HasColumnName("operating_system_version"); builder.ToTable("crash_report_metadata", "crashreport").HasKey(x => new { x.TenantId, diff --git a/src/BUTR.Site.NexusMods.Server/Contexts/UpsertEntityFactory.cs b/src/BUTR.Site.NexusMods.Server/Contexts/UpsertEntityFactory.cs index dbb83dcc..43ede89b 100644 --- a/src/BUTR.Site.NexusMods.Server/Contexts/UpsertEntityFactory.cs +++ b/src/BUTR.Site.NexusMods.Server/Contexts/UpsertEntityFactory.cs @@ -7,6 +7,7 @@ using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; +using BUTR.Site.NexusMods.Server.Repositories; namespace BUTR.Site.NexusMods.Server.Contexts; @@ -14,7 +15,7 @@ namespace BUTR.Site.NexusMods.Server.Contexts; /// Upsert is a pain in the ass, especially the graph inclusion. /// Instead, we manually track such entities and save them manually /// -public sealed class UpsertEntityFactory +public sealed class UpsertEntityFactory : IUpsertEntityFactory { private readonly ITenantContextAccessor _tenantContextAccessor; private readonly AppDbContextWrite _dbContextWrite; diff --git a/src/BUTR.Site.NexusMods.Server/Controllers/AuthenticationController.cs b/src/BUTR.Site.NexusMods.Server/Controllers/AuthenticationController.cs index ef8cd7fe..be42986b 100644 --- a/src/BUTR.Site.NexusMods.Server/Controllers/AuthenticationController.cs +++ b/src/BUTR.Site.NexusMods.Server/Controllers/AuthenticationController.cs @@ -189,7 +189,7 @@ public AuthenticationController( UserId = (uint) nexusModsUserId.Value, Name = userInfo.Name.Value, EMail = userInfo.Email.Value, - ProfileUrl = userInfo.AvatarUrl, + ProfileUrl = userInfo.AvatarUrl ?? "", IsSupporter = userInfo.MembershipRoles.Contains("supporter"), IsPremium = userInfo.MembershipRoles.Contains("premium"), APIKey = null, diff --git a/src/BUTR.Site.NexusMods.Server/Extensions/IAsyncEnumerableExtensions.cs b/src/BUTR.Site.NexusMods.Server/Extensions/IAsyncEnumerableExtensions.cs index f620cc27..8bf1b0d5 100644 --- a/src/BUTR.Site.NexusMods.Server/Extensions/IAsyncEnumerableExtensions.cs +++ b/src/BUTR.Site.NexusMods.Server/Extensions/IAsyncEnumerableExtensions.cs @@ -14,23 +14,6 @@ namespace BUTR.Site.NexusMods.Server.Extensions; /// public static class IAsyncEnumerableExtensions { - public static int IndexOf(this IEnumerable source, Predicate predicate) - { - ArgumentNullException.ThrowIfNull(source); - ArgumentNullException.ThrowIfNull(predicate); - - var index = 0; - foreach (var item in source) - { - if (predicate(item)) - return index; - - index += 1; - } - - return -1; - } - /// /// Configures an async enumerator with a cancellation token and a flag indicating whether to continue on a captured context. /// diff --git a/src/BUTR.Site.NexusMods.Server/Options/OtlpOptions.cs b/src/BUTR.Site.NexusMods.Server/Options/OtlpOptions.cs new file mode 100644 index 00000000..debb23ee --- /dev/null +++ b/src/BUTR.Site.NexusMods.Server/Options/OtlpOptions.cs @@ -0,0 +1,25 @@ +using Aragas.Extensions.Options.FluentValidation.Extensions; +using FluentValidation; +using OpenTelemetry.Exporter; + +namespace BUTR.Site.NexusMods.Server.Options; + +public sealed class OtlpOptionsValidator : AbstractValidator +{ + public OtlpOptionsValidator() + { + RuleFor(static x => x.LoggingEndpoint).IsUri().IsUrlTcpEndpointAvailable().When(static x => !string.IsNullOrEmpty(x.LoggingEndpoint)); + RuleFor(static x => x.TracingEndpoint).IsUri().IsUrlTcpEndpointAvailable().When(static x => !string.IsNullOrEmpty(x.TracingEndpoint)); + RuleFor(static x => x.MetricsEndpoint).IsUri().IsUrlTcpEndpointAvailable().When(static x => !string.IsNullOrEmpty(x.MetricsEndpoint)); + } +} + +public sealed record OtlpOptions +{ + public required string LoggingEndpoint { get; init; } = default!; + public required OtlpExportProtocol LoggingProtocol { get; init; } = default!; + public required string TracingEndpoint { get; init; } = default!; + public required OtlpExportProtocol TracingProtocol { get; init; } = default!; + public required string MetricsEndpoint { get; init; } = default!; + public required OtlpExportProtocol MetricsProtocol { get; init; } = default!; +} \ No newline at end of file diff --git a/src/BUTR.Site.NexusMods.Server/Program.cs b/src/BUTR.Site.NexusMods.Server/Program.cs index da932569..d928d745 100644 --- a/src/BUTR.Site.NexusMods.Server/Program.cs +++ b/src/BUTR.Site.NexusMods.Server/Program.cs @@ -1,5 +1,6 @@ using BUTR.Site.NexusMods.Server.Contexts; using BUTR.Site.NexusMods.Server.Extensions; +using BUTR.Site.NexusMods.Server.Options; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -16,8 +17,6 @@ using OpenTelemetry.Resources; using OpenTelemetry.Trace; -using Quartz; - using Serilog; using Serilog.Events; @@ -28,6 +27,8 @@ namespace BUTR.Site.NexusMods.Server; public static class Program { + private const string OltpSectionName = "Oltp"; + public static async Task Main(string[] args) { Log.Logger = new LoggerConfiguration() @@ -60,9 +61,14 @@ public static IHostBuilder CreateHostBuilder(string[] args) => Host .CreateDefaultBuilder(args) .ConfigureServices((ctx, services) => { - if (ctx.Configuration.GetSection("Oltp") is { } oltpSection) + var openTelemetry = services.AddOpenTelemetry() + .WithMetrics() + .WithTracing() + .WithLogging(); + + if (ctx.Configuration.GetSection(OltpSectionName) is { } oltpSection) { - var openTelemetry = services.AddOpenTelemetry() + openTelemetry .ConfigureResource(builder => { builder.AddDetector(new ContainerResourceDetector()); @@ -75,9 +81,9 @@ public static IHostBuilder CreateHostBuilder(string[] args) => Host builder.AddTelemetrySdk(); }); - if (oltpSection.GetValue("MetricsEndpoint") is { } metricsEndpoint) + if (oltpSection.GetValue(nameof(OtlpOptions.MetricsEndpoint)) is { } metricsEndpoint) { - var metricsProtocol = oltpSection.GetValue("MetricsProtocol"); + var metricsProtocol = oltpSection.GetValue(nameof(OtlpOptions.MetricsProtocol)); openTelemetry.WithMetrics(builder => builder .AddProcessInstrumentation() .AddRuntimeInstrumentation(instrumentationOptions => @@ -93,9 +99,9 @@ public static IHostBuilder CreateHostBuilder(string[] args) => Host })); } - if (oltpSection.GetValue("TracingEndpoint") is { } tracingEndpoint) + if (oltpSection.GetValue(nameof(OtlpOptions.TracingEndpoint)) is { } tracingEndpoint) { - var tracingProtocol = oltpSection.GetValue("TracingProtocol"); + var tracingProtocol = oltpSection.GetValue(nameof(OtlpOptions.TracingProtocol)); openTelemetry.WithTracing(builder => builder .AddEntityFrameworkCoreInstrumentation(instrumentationOptions => { @@ -103,11 +109,11 @@ public static IHostBuilder CreateHostBuilder(string[] args) => Host }) .AddNpgsql(instrumentationOptions => { - + }) .AddGrpcClientInstrumentation(instrumentationOptions => { - + }) .AddHttpClientInstrumentation(instrumentationOptions => { @@ -141,12 +147,12 @@ public static IHostBuilder CreateHostBuilder(string[] args) => Host }, writeToProviders: true) .ConfigureLogging((ctx, builder) => { - var oltpSection = ctx.Configuration.GetSection("Oltp"); + var oltpSection = ctx.Configuration.GetSection(OltpSectionName); if (oltpSection == null!) return; - var loggingEndpoint = oltpSection.GetValue("LoggingEndpoint"); + var loggingEndpoint = oltpSection.GetValue(nameof(OtlpOptions.LoggingEndpoint)); if (loggingEndpoint is null) return; - var loggingProtocol = oltpSection.GetValue("LoggingProtocol"); + var loggingProtocol = oltpSection.GetValue(nameof(OtlpOptions.LoggingProtocol)); builder.AddOpenTelemetry(o => { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/AutocompleteEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/AutocompleteEntityRepository.cs index 96ecae16..fd6e0020 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/AutocompleteEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/AutocompleteEntityRepository.cs @@ -14,13 +14,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface IAutocompleteEntityRepositoryRead : IRepositoryRead -{ - Task> AutocompleteStartsWithAsync(Expression> property, TParameter value, CancellationToken ct) - where TEntity : class, IEntity; -} -public interface IAutocompleteEntityRepositoryWrite : IRepositoryWrite, IAutocompleteEntityRepositoryRead; - [ScopedService] internal class AutocompleteEntityRepository : Repository, IAutocompleteEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportEntityRepository.cs index 8650d980..a29ff0bb 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportEntityRepository.cs @@ -19,40 +19,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public sealed record ModuleIdToVersionModel -{ - public required ModuleId ModuleId { get; init; } - public required ModuleVersion Version { get; init; } -} -public sealed record UserCrashReportModel -{ - public required CrashReportId Id { get; init; } - public required CrashReportVersion Version { get; init; } - public required GameVersion GameVersion { get; init; } - public required ExceptionTypeId ExceptionType { get; init; } - public required string Exception { get; init; } - public required DateTimeOffset CreatedAt { get; init; } - //public required ModuleId[] ModuleIds { get; init; } - //public required ModuleIdToVersionModel[] ModuleIdToVersion { get; init; } - public required ModuleId? TopInvolvedModuleId { get; init; } // Used for FE search - public required ModuleId[] InvolvedModuleIds { get; init; } - //public required NexusModsModId[] NexusModsModIds { get; init; } - public required CrashReportUrl Url { get; init; } - - public required CrashReportStatus Status { get; init; } - public required string? Comment { get; init; } -} - -public interface ICrashReportEntityRepositoryRead : IRepositoryRead -{ - Task> GetCrashReportsPaginatedAsync(NexusModsUserEntity user, PaginatedQuery query, ApplicationRole applicationRole, CancellationToken ct); -} - -public interface ICrashReportEntityRepositoryWrite : IRepositoryWrite, ICrashReportEntityRepositoryRead -{ - Task GenerateAutoCompleteForGameVersionsAsync(CancellationToken ct); -} - [ScopedService] internal class CrashReportEntityRepository : Repository, ICrashReportEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportIgnoredFileEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportIgnoredFileEntityRepository.cs index 3dda1b5d..80218d02 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportIgnoredFileEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportIgnoredFileEntityRepository.cs @@ -6,9 +6,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface ICrashReportIgnoredFileEntityRepositoryRead : IRepositoryRead; -public interface ICrashReportIgnoredFileEntityRepositoryWrite : IRepositoryWrite, ICrashReportIgnoredFileEntityRepositoryRead; - [ScopedService] internal class CrashReportIgnoredFileEntityRepository : Repository, ICrashReportIgnoredFileEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportToFileIdEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportToFileIdEntityRepository.cs index a6e97589..2562ee87 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportToFileIdEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportToFileIdEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface ICrashReportToFileIdEntityRepositoryRead : IRepositoryRead; -public interface ICrashReportToFileIdEntityRepositoryWrite : IRepositoryWrite, ICrashReportToFileIdEntityRepositoryRead; - [ScopedService] internal class CrashReportToFileIdEntityRepository : Repository, ICrashReportToFileIdEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportToMetadataEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportToMetadataEntityRepository.cs index 28a8a919..d34a2595 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportToMetadataEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportToMetadataEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface ICrashReportToMetadataEntityRepositoryRead : IRepositoryRead; -public interface ICrashReportToMetadataEntityRepositoryWrite : IRepositoryWrite, ICrashReportToMetadataEntityRepositoryRead; - [ScopedService] internal class CrashReportToMetadataEntityRepository : Repository, ICrashReportToMetadataEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportToModuleMetadataEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportToModuleMetadataEntityRepository.cs index 5e797d4b..34acabd0 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportToModuleMetadataEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportToModuleMetadataEntityRepository.cs @@ -15,28 +15,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public sealed record StatisticsCrashReport -{ - public required GameVersion GameVersion { get; init; } - public required ModuleId ModuleId { get; init; } - public required ModuleVersion ModuleVersion { get; init; } - public required int InvolvedCount { get; init; } - public required int NotInvolvedCount { get; init; } - public required int TotalCount { get; init; } - public required int Value { get; init; } - public required double CrashScore { get; init; } -} - -public interface ICrashReportToModuleMetadataEntityRepositoryRead : IRepositoryRead -{ - Task> GetAllStatisticsAsync(CancellationToken ct); -} - -public interface ICrashReportToModuleMetadataEntityRepositoryWrite : IRepositoryWrite, ICrashReportToModuleMetadataEntityRepositoryRead -{ - Task GenerateAutoCompleteForModuleIdsAsync(CancellationToken ct); -} - [ScopedService] internal class CrashReportToModuleMetadataEntityRepository : Repository, ICrashReportToModuleMetadataEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/ExceptionTypeRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/ExceptionTypeRepository.cs index 3792207e..3bcdf20a 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/ExceptionTypeRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/ExceptionTypeRepository.cs @@ -6,9 +6,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface IExceptionTypeRepositoryRead : IRepositoryRead; -public interface IExceptionTypeRepositoryWrite : IRepositoryWrite, IExceptionTypeRepositoryRead; - [ScopedService] internal class ExceptionTypeRepository : Repository, IExceptionTypeRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/IRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/IRepository.cs index a050cd3b..e4d5c701 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/IRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/IRepository.cs @@ -17,73 +17,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -/// -/// Marker interface for repositories. -/// -public interface IRepository; - -public interface IRepositoryRead : IRepository where TEntity : class, IEntity -{ - Task FirstOrDefaultAsync( - Expression>? filter, - Func, IOrderedQueryable>? orderBy, - CancellationToken ct); - Task FirstOrDefaultAsync( - Expression>? filter, - Func, IOrderedQueryable>? orderBy, - Expression> projection, - CancellationToken ct); - - Task LastOrDefaultAsync( - Expression>? filter, - Func, IOrderedQueryable>? orderBy, - CancellationToken ct); - Task LastOrDefaultAsync( - Expression>? filter, - Func, IOrderedQueryable>? orderBy, - Expression> projection, - CancellationToken ct); - - Task> GetAllAsync( - Expression>? filter, - Func, IOrderedQueryable>? orderBy, - CancellationToken ct); - Task> GetAllAsync( - Expression>? filter, - Func, IOrderedQueryable>? orderBy, - Expression> projection, - CancellationToken ct); - - Task> PaginatedAsync( - PaginatedQuery query, - uint maxPageSize = 20, - Sorting? defaultSorting = default, - CancellationToken ct = default); - - Task> PaginatedAsync( - Expression> projection, - PaginatedQuery query, - uint maxPageSize = 20, - Sorting? defaultSorting = default, - CancellationToken ct = default) where TProjection : class; -} - -public interface IRepositoryWrite : IRepositoryRead where TEntity : class, IEntity -{ - void Add(TEntity entity); - void AddRange(IEnumerable entities); - - void Update(TEntity originalEntity, TEntity currentEntity); - - void Upsert(TEntity entity); - void UpsertRange(IEnumerable entities); - - void Remove(TEntity entity); - void RemoveRange(IEnumerable entities); - - int Remove(Expression> filter); -} - internal abstract class Repository : IRepositoryWrite where TEntity : class, IEntity { protected readonly BaseAppDbContext _dbContext; diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/IUnitOfRead.cs b/src/BUTR.Site.NexusMods.Server/Repositories/IUnitOfRead.cs index 41fa8d35..b5a29fe4 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/IUnitOfRead.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/IUnitOfRead.cs @@ -9,51 +9,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface IUnitOfRead : IDisposable, IAsyncDisposable -{ - IAutocompleteEntityRepositoryRead Autocompletes { get; } - - IQuartzExecutionLogEntityRepositoryRead QuartzExecutionLogs { get; } - - IExceptionTypeRepositoryRead ExceptionTypes { get; } - - ICrashReportEntityRepositoryRead CrashReports { get; } - ICrashReportToMetadataEntityRepositoryRead CrashReportToMetadatas { get; } - ICrashReportToModuleMetadataEntityRepositoryRead CrashReportModuleInfos { get; } - ICrashReportToFileIdEntityRepositoryRead CrashReportToFileIds { get; } - ICrashReportIgnoredFileEntityRepositoryRead CrashReportIgnoredFileIds { get; } - - IStatisticsTopExceptionsTypeEntityRepositoryRead StatisticsTopExceptionsTypes { get; } - IStatisticsCrashScoreInvolvedEntityRepositoryRead StatisticsCrashScoreInvolveds { get; } - - INexusModsArticleEntityRepositoryRead NexusModsArticles { get; } - - INexusModsModToModuleEntityRepositoryRead NexusModsModModules { get; } - INexusModsModToNameEntityRepositoryRead NexusModsModName { get; } - - INexusModsModToModuleInfoHistoryEntityRepositoryRead NexusModsModToModuleInfoHistory { get; } - INexusModsModToFileUpdateEntityRepositoryRead NexusModsModToFileUpdates { get; } - - INexusModsUserRepositoryRead NexusModsUsers { get; } - INexusModsUserToNameEntityRepositoryRead NexusModsUserToName { get; } - INexusModsUserToCrashReportEntityRepositoryRead NexusModsUserToCrashReports { get; } - INexusModsUserToNexusModsModEntityRepositoryRead NexusModsUserToNexusModsMods { get; } - INexusModsUserToModuleEntityRepositoryRead NexusModsUserToModules { get; } - - - INexusModsUserToIntegrationGitHubEntityRepositoryRead NexusModsUserToGitHub { get; } - INexusModsUserToIntegrationDiscordEntityRepositoryRead NexusModsUserToDiscord { get; } - INexusModsUserToIntegrationGOGEntityRepositoryRead NexusModsUserToGOG { get; } - INexusModsUserToIntegrationSteamEntityRepositoryRead NexusModsUserToSteam { get; } - - IIntegrationGitHubTokensEntityRepositoryRead IntegrationGitHubTokens { get; } - IIntegrationDiscordTokensEntityRepositoryRead IntegrationDiscordTokens { get; } - IIntegrationGOGTokensEntityRepositoryRead IntegrationGOGTokens { get; } - IIntegrationGOGToOwnedTenantEntityRepositoryRead IntegrationGOGToOwnedTenants { get; } - IIntegrationSteamTokensEntityRepositoryRead IntegrationSteamTokens { get; } - IIntegrationSteamToOwnedTenantEntityRepositoryRead IntegrationSteamToOwnedTenants { get; } -} - [TransientService] internal class UnitOfRead : IUnitOfRead { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/IUnitOfWorkFactory.cs b/src/BUTR.Site.NexusMods.Server/Repositories/IUnitOfWorkFactory.cs index a24e691a..cb30e57e 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/IUnitOfWorkFactory.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/IUnitOfWorkFactory.cs @@ -8,15 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface IUnitOfWorkFactory -{ - IUnitOfRead CreateUnitOfRead(); - IUnitOfRead CreateUnitOfRead(TenantId tenant); - - IUnitOfWrite CreateUnitOfWrite(); - IUnitOfWrite CreateUnitOfWrite(TenantId tenant); -} - [ScopedService] internal class UnitOfWorkFactory : IUnitOfWorkFactory { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/IUnitOfWrite.cs b/src/BUTR.Site.NexusMods.Server/Repositories/IUnitOfWrite.cs index 3a42d3b6..73bc5422 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/IUnitOfWrite.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/IUnitOfWrite.cs @@ -11,53 +11,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface IUnitOfWrite : IDisposable, IAsyncDisposable -{ - UpsertEntityFactory UpsertEntityFactory { get; } - - IAutocompleteEntityRepositoryWrite Autocompletes { get; } - - IQuartzExecutionLogEntityRepositoryWrite QuartzExecutionLogs { get; } - - IExceptionTypeRepositoryWrite ExceptionTypes { get; } - - ICrashReportEntityRepositoryWrite CrashReports { get; } - ICrashReportToMetadataEntityRepositoryWrite CrashReportToMetadatas { get; } - ICrashReportToModuleMetadataEntityRepositoryWrite CrashReportModuleInfos { get; } - ICrashReportToFileIdEntityRepositoryWrite CrashReportToFileIds { get; } - ICrashReportIgnoredFileEntityRepositoryWrite CrashReportIgnoredFileIds { get; } - - IStatisticsTopExceptionsTypeEntityRepositoryWrite StatisticsTopExceptionsTypes { get; } - IStatisticsCrashScoreInvolvedEntityRepositoryWrite StatisticsCrashScoreInvolveds { get; } - - INexusModsArticleEntityRepositoryWrite NexusModsArticles { get; } - - INexusModsModToModuleEntityRepositoryWrite NexusModsModModules { get; } - INexusModsModToNameEntityRepositoryWrite NexusModsModName { get; } - INexusModsModToModuleInfoHistoryEntityRepositoryWrite NexusModsModToModuleInfoHistory { get; } - INexusModsModToFileUpdateEntityRepositoryWrite NexusModsModToFileUpdates { get; } - - INexusModsUserRepositoryWrite NexusModsUsers { get; } - INexusModsUserToNameEntityRepositoryWrite NexusModsUserToName { get; } - INexusModsUserToCrashReportEntityRepositoryWrite NexusModsUserToCrashReports { get; } - INexusModsUserToNexusModsModEntityRepositoryWrite NexusModsUserToNexusModsMods { get; } - INexusModsUserToModuleEntityRepositoryWrite NexusModsUserToModules { get; } - - INexusModsUserToIntegrationGitHubEntityRepositoryWrite NexusModsUserToGitHub { get; } - INexusModsUserToIntegrationDiscordEntityRepositoryWrite NexusModsUserToDiscord { get; } - INexusModsUserToIntegrationGOGEntityRepositoryWrite NexusModsUserToGOG { get; } - INexusModsUserToIntegrationSteamEntityRepositoryWrite NexusModsUserToSteam { get; } - - IIntegrationGitHubTokensEntityRepositoryWrite IntegrationGitHubTokens { get; } - IIntegrationDiscordTokensEntityRepositoryWrite IntegrationDiscordTokens { get; } - IIntegrationGOGTokensEntityRepositoryWrite IntegrationGOGTokens { get; } - IIntegrationGOGToOwnedTenantEntityRepositoryWrite IntegrationGOGToOwnedTenants { get; } - IIntegrationSteamTokensEntityRepositoryWrite IntegrationSteamTokens { get; } - IIntegrationSteamToOwnedTenantEntityRepositoryWrite IntegrationSteamToOwnedTenants { get; } - - Task SaveChangesAsync(CancellationToken ct); -} - [TransientService] internal class UnitOfWrite : IUnitOfWrite { @@ -66,7 +19,7 @@ internal class UnitOfWrite : IUnitOfWrite private IDbContextTransaction _dbContextTransaction; - public UpsertEntityFactory UpsertEntityFactory { get; private set; } + public IUpsertEntityFactory UpsertEntityFactory { get; private set; } public IAutocompleteEntityRepositoryWrite Autocompletes { get; } diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationDiscordTokensEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationDiscordTokensEntityRepository.cs index 7e29fc3d..20f5a142 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationDiscordTokensEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationDiscordTokensEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface IIntegrationDiscordTokensEntityRepositoryRead : IRepositoryRead; -public interface IIntegrationDiscordTokensEntityRepositoryWrite : IRepositoryWrite, IIntegrationDiscordTokensEntityRepositoryRead; - [ScopedService] internal class IntegrationDiscordTokensEntityRepository : Repository, IIntegrationDiscordTokensEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationGOGToOwnedTenantEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationGOGToOwnedTenantEntityRepository.cs index 78fb19bb..6ee6af62 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationGOGToOwnedTenantEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationGOGToOwnedTenantEntityRepository.cs @@ -6,9 +6,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface IIntegrationGOGToOwnedTenantEntityRepositoryRead : IRepositoryRead; -public interface IIntegrationGOGToOwnedTenantEntityRepositoryWrite : IRepositoryWrite, IIntegrationGOGToOwnedTenantEntityRepositoryRead; - [ScopedService] internal class IntegrationGOGToOwnedTenantEntityRepository : Repository, IIntegrationGOGToOwnedTenantEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationGOGTokensEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationGOGTokensEntityRepository.cs index 58887c93..2e36aa54 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationGOGTokensEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationGOGTokensEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface IIntegrationGOGTokensEntityRepositoryRead : IRepositoryRead; -public interface IIntegrationGOGTokensEntityRepositoryWrite : IRepositoryWrite, IIntegrationGOGTokensEntityRepositoryRead; - [ScopedService] internal class IntegrationGOGTokensEntityRepository : Repository, IIntegrationGOGTokensEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationGitHubTokensEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationGitHubTokensEntityRepository.cs index 7ebdb6b8..7a4b90bb 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationGitHubTokensEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationGitHubTokensEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface IIntegrationGitHubTokensEntityRepositoryRead : IRepositoryRead; -public interface IIntegrationGitHubTokensEntityRepositoryWrite : IRepositoryWrite, IIntegrationGitHubTokensEntityRepositoryRead; - [ScopedService] internal class IntegrationGitHubTokensEntityRepository : Repository, IIntegrationGitHubTokensEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationSteamToOwnedTenantEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationSteamToOwnedTenantEntityRepository.cs index b9755460..507fdd5a 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationSteamToOwnedTenantEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationSteamToOwnedTenantEntityRepository.cs @@ -6,9 +6,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface IIntegrationSteamToOwnedTenantEntityRepositoryRead : IRepositoryRead; -public interface IIntegrationSteamToOwnedTenantEntityRepositoryWrite : IRepositoryWrite, IIntegrationSteamToOwnedTenantEntityRepositoryRead; - [ScopedService] internal class IntegrationSteamToOwnedTenantEntityRepository : Repository, IIntegrationSteamToOwnedTenantEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationSteamTokensEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationSteamTokensEntityRepository.cs index bf960da3..961ab31c 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationSteamTokensEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/IntegrationSteamTokensEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface IIntegrationSteamTokensEntityRepositoryRead : IRepositoryRead; -public interface IIntegrationSteamTokensEntityRepositoryWrite : IRepositoryWrite, IIntegrationSteamTokensEntityRepositoryRead; - [ScopedService] internal class IntegrationSteamTokensEntityRepository : Repository, IIntegrationSteamTokensEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsArticleEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsArticleEntityRepository.cs index b3245b3b..6740dd79 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsArticleEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsArticleEntityRepository.cs @@ -15,16 +15,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface INexusModsArticleEntityRepositoryRead : IRepositoryRead -{ - Task> GetAllModuleIdsAsync(string authorName, CancellationToken ct); -} - -public interface INexusModsArticleEntityRepositoryWrite : IRepositoryWrite, INexusModsArticleEntityRepositoryRead -{ - Task GenerateAutoCompleteForAuthorNameAsync(CancellationToken ct); -} - [ScopedService] internal class NexusModsArticleEntityRepository : Repository, INexusModsArticleEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToFileUpdateEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToFileUpdateEntityRepository.cs index 628ac849..28d99f81 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToFileUpdateEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToFileUpdateEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface INexusModsModToFileUpdateEntityRepositoryRead : IRepositoryRead; -public interface INexusModsModToFileUpdateEntityRepositoryWrite : IRepositoryWrite, INexusModsModToFileUpdateEntityRepositoryRead; - [ScopedService] internal class NexusModsModToFileUpdateEntityRepository : Repository, INexusModsModToFileUpdateEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToModuleEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToModuleEntityRepository.cs index 3664eeb5..46866e8e 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToModuleEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToModuleEntityRepository.cs @@ -14,38 +14,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public sealed record LinkedByStaffNexusModsModModel -{ - public NexusModsModId NexusModsModId { get; init; } - public DateTimeOffset LastCheckedDate { get; init; } -} - -public sealed record LinkedByStaffModuleNexusModsModsModel -{ - public required ModuleId ModuleId { get; init; } - public required LinkedByStaffNexusModsModModel[] NexusModsMods { get; init; } -} - -public sealed record LinkedByExposureModuleModel -{ - public required ModuleId ModuleId { get; init; } - public required DateTimeOffset LastCheckedDate { get; init; } -} - -public sealed record LinkedByExposureNexusModsModModelsModel -{ - public required NexusModsModId NexusModsModId { get; init; } - public required LinkedByExposureModuleModel[] Modules { get; init; } -} - -public interface INexusModsModToModuleEntityRepositoryRead : IRepositoryRead -{ - Task> GetByStaffPaginatedAsync(PaginatedQuery query, CancellationToken ct); - - Task> GetExposedPaginatedAsync(PaginatedQuery query, CancellationToken ct); -} -public interface INexusModsModToModuleEntityRepositoryWrite : IRepositoryWrite, INexusModsModToModuleEntityRepositoryRead; - [ScopedService] internal class NexusModsModToModuleEntityRepository : Repository, INexusModsModToModuleEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToModuleInfoHistoryEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToModuleInfoHistoryEntityRepository.cs index bf5c2929..c4eb87c1 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToModuleInfoHistoryEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToModuleInfoHistoryEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface INexusModsModToModuleInfoHistoryEntityRepositoryRead : IRepositoryRead; -public interface INexusModsModToModuleInfoHistoryEntityRepositoryWrite : IRepositoryWrite, INexusModsModToModuleInfoHistoryEntityRepositoryRead; - [ScopedService] internal class NexusModsModToModuleInfoHistoryEntityRepository : Repository, INexusModsModToModuleInfoHistoryEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToNameEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToNameEntityRepository.cs index 326a2bfa..5a9f8381 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToNameEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToNameEntityRepository.cs @@ -8,11 +8,7 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface INexusModsModToNameEntityRepositoryRead : IRepositoryRead; -public interface INexusModsModToNameEntityRepositoryWrite : IRepositoryWrite, INexusModsModToNameEntityRepositoryRead; - [ScopedService] - internal class NexusModsModToNameEntityRepository : Repository, INexusModsModToNameEntityRepositoryWrite { protected override IQueryable InternalQuery => base.InternalQuery diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserRepository.cs index d5853053..16ae4f5d 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserRepository.cs @@ -13,36 +13,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public sealed record UserAvailableModModel -{ - public required NexusModsModId NexusModsModId { get; init; } - public required string Name { get; init; } -} - -public sealed record UserLinkedModModel -{ - public required NexusModsModId NexusModsModId { get; init; } - public required string Name { get; init; } - public required NexusModsUserId[] OwnerNexusModsUserIds { get; init; } - public required NexusModsUserId[] AllowedNexusModsUserIds { get; init; } - public required NexusModsUserId[] ManuallyLinkedNexusModsUserIds { get; init; } - public required ModuleId[] ManuallyLinkedModuleIds { get; init; } - public required ModuleId[] KnownModuleIds { get; init; } -} - -public interface INexusModsUserRepositoryRead : IRepositoryRead -{ - Task GetUserWithIntegrationsAsync(NexusModsUserId userId, CancellationToken ct); - Task GetUserAsync(NexusModsUserId userId, CancellationToken ct); - - Task> GetNexusModsModsPaginatedAsync(NexusModsUserId userId, PaginatedQuery query, CancellationToken ct); - - Task> GetAvailableModsPaginatedAsync(NexusModsUserId userId, PaginatedQuery query, CancellationToken ct); - - Task GetLinkedModCountAsync(NexusModsUserId userId, CancellationToken ct); -} -public interface INexusModsUserRepositoryWrite : IRepositoryWrite, INexusModsUserRepositoryRead; - [ScopedService] internal class NexusModsUserRepository : Repository, INexusModsUserRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToCrashReportEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToCrashReportEntityRepository.cs index 890d0b05..febc47ee 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToCrashReportEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToCrashReportEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface INexusModsUserToCrashReportEntityRepositoryRead : IRepositoryRead; -public interface INexusModsUserToCrashReportEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToCrashReportEntityRepositoryRead; - [ScopedService] internal class NexusModsUserToCrashReportEntityRepository : Repository, INexusModsUserToCrashReportEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationDiscordEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationDiscordEntityRepository.cs index 649fce0b..5d873a6e 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationDiscordEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationDiscordEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface INexusModsUserToIntegrationDiscordEntityRepositoryRead : IRepositoryRead; -public interface INexusModsUserToIntegrationDiscordEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToIntegrationDiscordEntityRepositoryRead; - [ScopedService] internal class NexusModsUserToIntegrationDiscordEntityRepository : Repository, INexusModsUserToIntegrationDiscordEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationGOGEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationGOGEntityRepository.cs index 9fee5325..ca391ce2 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationGOGEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationGOGEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface INexusModsUserToIntegrationGOGEntityRepositoryRead : IRepositoryRead; -public interface INexusModsUserToIntegrationGOGEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToIntegrationGOGEntityRepositoryRead; - [ScopedService] internal class NexusModsUserToIntegrationGOGEntityRepository : Repository, INexusModsUserToIntegrationGOGEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationGitHubEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationGitHubEntityRepository.cs index 2e790d1f..960d2db1 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationGitHubEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationGitHubEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface INexusModsUserToIntegrationGitHubEntityRepositoryRead : IRepositoryRead; -public interface INexusModsUserToIntegrationGitHubEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToIntegrationGitHubEntityRepositoryRead; - [ScopedService] internal class NexusModsUserToIntegrationGitHubEntityRepository : Repository, INexusModsUserToIntegrationGitHubEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationSteamEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationSteamEntityRepository.cs index d74d4b3c..cfa6720f 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationSteamEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToIntegrationSteamEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface INexusModsUserToIntegrationSteamEntityRepositoryRead : IRepositoryRead; -public interface INexusModsUserToIntegrationSteamEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToIntegrationSteamEntityRepositoryRead; - [ScopedService] internal class NexusModsUserToIntegrationSteamEntityRepository : Repository, INexusModsUserToIntegrationSteamEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToModuleEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToModuleEntityRepository.cs index 49a4801a..cc2dc24a 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToModuleEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToModuleEntityRepository.cs @@ -13,19 +13,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public sealed record UserManuallyLinkedModuleModel -{ - public required NexusModsUserId NexusModsUserId { get; init; } - public required NexusModsUserName NexusModsUsername { get; init; } - public required ModuleId[] ModuleIds { get; init; } -} - -public interface INexusModsUserToModuleEntityRepositoryRead : IRepositoryRead -{ - Task> GetManuallyLinkedModuleIdsPaginatedAsync(PaginatedQuery query, NexusModsUserToModuleLinkType linkType, CancellationToken ct); -} -public interface INexusModsUserToModuleEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToModuleEntityRepositoryRead; - [ScopedService] internal class NexusModsUserToModuleEntityRepository : Repository, INexusModsUserToModuleEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToNameEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToNameEntityRepository.cs index 7924a0e6..ac283ba1 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToNameEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToNameEntityRepository.cs @@ -8,9 +8,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface INexusModsUserToNameEntityRepositoryRead : IRepositoryRead; -public interface INexusModsUserToNameEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToNameEntityRepositoryRead; - [ScopedService] internal class NexusModsUserToNameEntityRepository : Repository, INexusModsUserToNameEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToNexusModsModEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToNexusModsModEntityRepository.cs index 2448ba0b..06c25eb1 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToNexusModsModEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserToNexusModsModEntityRepository.cs @@ -13,23 +13,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public sealed record UserManuallyLinkedModUserModel -{ - public required NexusModsUserId NexusModsUserId { get; init; } - public required NexusModsUserName NexusModsUsername { get; init; } -} -public sealed record UserManuallyLinkedModModel -{ - public required NexusModsModId NexusModsModId { get; init; } - public required UserManuallyLinkedModUserModel[] NexusModsUsers { get; init; } -} - -public interface INexusModsUserToNexusModsModEntityRepositoryRead : IRepositoryRead -{ - Task> GetManuallyLinkedPaginatedAsync(NexusModsUserId userId, PaginatedQuery query, CancellationToken ct); -} -public interface INexusModsUserToNexusModsModEntityRepositoryWrite : IRepositoryWrite, INexusModsUserToNexusModsModEntityRepositoryRead; - [ScopedService] internal class NexusModsUserToNexusModsModEntityRepository : Repository, INexusModsUserToNexusModsModEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/QuartzExecutionLogEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/QuartzExecutionLogEntityRepository.cs index 3fdcdebb..eb74b875 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/QuartzExecutionLogEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/QuartzExecutionLogEntityRepository.cs @@ -11,13 +11,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface IQuartzExecutionLogEntityRepositoryRead : IRepositoryRead; - -public interface IQuartzExecutionLogEntityRepositoryWrite : IRepositoryWrite, IQuartzExecutionLogEntityRepositoryRead -{ - Task MarkIncompleteAsync(CancellationToken ct); -} - [ScopedService] internal class QuartzExecutionLogEntityRepository : Repository, IQuartzExecutionLogEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/StatisticsCrashScoreInvolvedEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/StatisticsCrashScoreInvolvedEntityRepository.cs index e916402f..201178e4 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/StatisticsCrashScoreInvolvedEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/StatisticsCrashScoreInvolvedEntityRepository.cs @@ -13,53 +13,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public sealed record VersionScoreModel -{ - public required ModuleVersion Version { get; init; } - public required double Score { get; init; } - public required double Value { get; init; } - public required int CountStable { get; init; } - public required int CountUnstable { get; init; } - public double Count => CountStable + CountUnstable; -} -public sealed record VersionStorageModel -{ - public required ModuleVersion Version { get; init; } - public required VersionScoreModel[] Scores { get; init; } - public double MeanScore => Scores.Length == 0 ? 0 : 1 - (Scores.Sum(x => x.Value) / (double) Scores.Sum(x => x.Count)); -}; -public sealed record ModuleStorageModel -{ - public required ModuleId ModuleId { get; init; } - public required VersionStorageModel[] Versions { get; init; } -}; -public sealed record StatisticsInvolvedModuleScoresForGameVersionModel -{ - public required GameVersion GameVersion { get; init; } - public required ModuleStorageModel[] Modules { get; init; } -} - -public sealed record RawScoreForModuleVersionModel -{ - public required ModuleVersion ModuleVersion { get; init; } - public required double RawScore { get; init; } - public required int TotalCount { get; init; } -} - -public sealed record StatisticsRawScoresForModuleModel -{ - public required ModuleId ModuleId { get; init; } - public required RawScoreForModuleVersionModel[] RawScores { get; init; } -} - -public interface IStatisticsCrashScoreInvolvedEntityRepositoryRead : IRepositoryRead -{ - Task> GetAllInvolvedModuleScoresForGameVersionAsync(GameVersion[]? gameVersions, ModuleId[]? moduleIds, ModuleVersion[]? moduleVersions, CancellationToken ct); - Task> GetAllRawScoresForAllModulesAsync(GameVersion gameVersion, ModuleId[] moduleIds, CancellationToken ct); - -} -public interface IStatisticsCrashScoreInvolvedEntityRepositoryWrite : IRepositoryWrite, IStatisticsCrashScoreInvolvedEntityRepositoryRead; - [ScopedService] internal class StatisticsCrashScoreInvolvedEntityRepository : Repository, IStatisticsCrashScoreInvolvedEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/StatisticsTopExceptionsTypeEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/StatisticsTopExceptionsTypeEntityRepository.cs index 434eefd3..f975c2f9 100644 --- a/src/BUTR.Site.NexusMods.Server/Repositories/StatisticsTopExceptionsTypeEntityRepository.cs +++ b/src/BUTR.Site.NexusMods.Server/Repositories/StatisticsTopExceptionsTypeEntityRepository.cs @@ -12,12 +12,6 @@ namespace BUTR.Site.NexusMods.Server.Repositories; -public interface IStatisticsTopExceptionsTypeEntityRepositoryRead : IRepositoryRead; -public interface IStatisticsTopExceptionsTypeEntityRepositoryWrite : IRepositoryWrite, IStatisticsTopExceptionsTypeEntityRepositoryRead -{ - Task CalculateAsync(CancellationToken ct); -} - [ScopedService] internal class StatisticsTopExceptionsTypeEntityRepository : Repository, IStatisticsTopExceptionsTypeEntityRepositoryWrite { diff --git a/src/BUTR.Site.NexusMods.Server/Services/General/ICrashReportBatchedHandler.cs b/src/BUTR.Site.NexusMods.Server/Services/General/ICrashReportBatchedHandler.cs index 1d3bac02..51983de1 100644 --- a/src/BUTR.Site.NexusMods.Server/Services/General/ICrashReportBatchedHandler.cs +++ b/src/BUTR.Site.NexusMods.Server/Services/General/ICrashReportBatchedHandler.cs @@ -1,8 +1,5 @@ -using BUTR.CrashReport.Bannerlord.Parser; -using BUTR.CrashReport.Models; using BUTR.Site.NexusMods.DependencyInjection; using BUTR.Site.NexusMods.Server.Contexts; -using BUTR.Site.NexusMods.Server.Extensions; using BUTR.Site.NexusMods.Server.Models; using BUTR.Site.NexusMods.Server.Models.Database; using BUTR.Site.NexusMods.Server.Options; @@ -19,6 +16,8 @@ using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; +using BUTR.Site.NexusMods.Server.CrashReport.v13; +using BUTR.Site.NexusMods.Server.CrashReport.v14; namespace BUTR.Site.NexusMods.Server.Services; @@ -30,21 +29,10 @@ public interface ICrashReportBatchedHandler : IAsyncDisposable [ScopedService] public sealed class CrashReportBatchedHandler : ICrashReportBatchedHandler { - private record HttpResultEntry(CrashReportFileId FileId, DateTime Date, CrashReportModel? CrashReport); + private record HttpResultEntry(CrashReportFileId FileId, DateTime Date, byte Version, string? CrashReportContent); private static readonly int ParallelCount = Environment.ProcessorCount / 2; - private static string GetException(ExceptionModel? exception, bool inner = false) => exception is null ? string.Empty : $""" - -{(inner ? "Inner " : string.Empty)}Exception information -Type: {exception.Type} -Message: {exception.Message} -CallStack: -{exception.CallStack} - -{GetException(exception.InnerException, true)} -"""; - private Channel _toDownloadChannel = Channel.CreateBounded(ParallelCount * 2); private Channel _httpResultChannel = Channel.CreateBounded(ParallelCount * 2); private Channel _linkedCrashReportsChannel = Channel.CreateUnbounded(); @@ -167,33 +155,26 @@ await Parallel.ForEachAsync(_toDownloadChannel.Reader.ReadAllAsync(ct), options, { var (fileId, _, version, date) = entry; - CrashReportModel? model; - if (version <= 12) + string? content; + try { - var content = await _client.GetCrashReportAsync(fileId, ct2); - - try + if (version <= 12) { - model = CrashReportParser.ParseLegacyHtml(version, content); + content = await _client.GetCrashReportAsync(fileId, ct2); } - catch (Exception e) + else { - _logger.LogError(e, "Exception while parsing Legacy HTML report {FileId}", fileId); - model = null; + content = await _client.GetCrashReportJsonAsync(fileId, ct2); } } - else + catch (Exception e) { - model = await _client.GetCrashReportModelAsync(fileId, ct2); - } - - if (model is null) - { - _logger.LogError("Failed to parse {FileId}", fileId); + _logger.LogError(e, "Failed to download {FileId}", fileId); + content = null; } await _httpResultChannel.Writer.WaitToWriteAsync(ct2); - await _httpResultChannel.Writer.WriteAsync(new(fileId, date, model), ct2); + await _httpResultChannel.Writer.WriteAsync(new(fileId, date, version, content), ct2); } catch (Exception e) { @@ -223,17 +204,85 @@ private async Task WriteCrashReportsToDatabaseAsync(CancellationToken ct) var crashReportsBuilder = ImmutableArray.CreateBuilder(); var crashReportMetadatasBuilder = ImmutableArray.CreateBuilder(); var crashReportModulesBuilder = ImmutableArray.CreateBuilder(); - await foreach (var (fileId, date, report) in _httpResultChannel.Reader.ReadAllAsync(ct)) + await foreach (var (fileId, date, version, content) in _httpResultChannel.Reader.ReadAllAsync(ct)) { - if (report is null) + if (content is null) { failedCrashReportFileIds.Add(fileId); continue; } - var crashReportId = CrashReportId.From(report.Id); + CrashReportEntity? crashReportEntity = null; + CrashReportToMetadataEntity? crashReportToMetadataEntity = null; + IList? crashReportToModuleMetadataEntities = null; + + var url = CrashReportUrl.From(new Uri(new Uri(_options.Endpoint), fileId.ToString())); + + if (version <= 12) + { + var result = CrashReportV14.TryFromHtml( + unitOfWrite, + tenant, + fileId, + url, + date, + version, + content, + out crashReportEntity, + out crashReportToMetadataEntity, + out crashReportToModuleMetadataEntities); + if (!result) + { + failedCrashReportFileIds.Add(fileId); + continue; + } + } + if (version == 13) + { + var result = CrashReportV13.TryFromJson( + unitOfWrite, + tenant, + fileId, + url, + date, + version, + content, + out crashReportEntity, + out crashReportToMetadataEntity, + out crashReportToModuleMetadataEntities); + if (!result) + { + failedCrashReportFileIds.Add(fileId); + continue; + } + } + if (version == 14) + { + var result = CrashReportV14.TryFromJson( + unitOfWrite, + tenant, + fileId, + url, + date, + version, + content, + out crashReportEntity, + out crashReportToMetadataEntity, + out crashReportToModuleMetadataEntities); + if (!result) + { + failedCrashReportFileIds.Add(fileId); + continue; + } + } + + if (crashReportEntity is null || crashReportToMetadataEntity is null || crashReportToModuleMetadataEntities is null) + { + failedCrashReportFileIds.Add(fileId); + continue; + } - if (uniqueCrashReportIds.Contains(crashReportId)) + if (!uniqueCrashReportIds.Add(crashReportEntity.CrashReportId)) { ignoredCrashReportFileEntities.Add(new CrashReportIgnoredFileEntity { @@ -243,48 +292,9 @@ private async Task WriteCrashReportsToDatabaseAsync(CancellationToken ct) continue; } - uniqueCrashReportIds.Add(crashReportId); - - // TODO: - var butrLoaderVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "BUTRLoaderVersion")?.Value; - var blseVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "BLSEVersion")?.Value; - var launcherExVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "LauncherExVersion")?.Value; - - crashReportsBuilder.Add(new CrashReportEntity - { - TenantId = tenant, - CrashReportId = crashReportId, - Url = CrashReportUrl.From(new Uri(new Uri(_options.Endpoint), fileId.ToString())), - Version = CrashReportVersion.From(report.Version), - GameVersion = GameVersion.From(report.Metadata.GameVersion), - ExceptionTypeId = ExceptionTypeId.FromException(report.Exception), - ExceptionType = unitOfWrite.UpsertEntityFactory.GetOrCreateExceptionType(ExceptionTypeId.FromException(report.Exception)), - Exception = GetException(report.Exception), - CreatedAt = fileId.Value.Length == 8 ? DateTimeOffset.UnixEpoch.ToUniversalTime() : date.ToUniversalTime(), - }); - crashReportMetadatasBuilder.Add(new CrashReportToMetadataEntity - { - TenantId = tenant, - CrashReportId = crashReportId, - LauncherType = string.IsNullOrEmpty(report.Metadata.LauncherType) ? null : report.Metadata.LauncherType, - LauncherVersion = string.IsNullOrEmpty(report.Metadata.LauncherVersion) ? null : report.Metadata.LauncherVersion, - Runtime = string.IsNullOrEmpty(report.Metadata.Runtime) ? null : report.Metadata.Runtime, - BUTRLoaderVersion = butrLoaderVersion, - BLSEVersion = blseVersion, - LauncherExVersion = launcherExVersion, - }); - crashReportModulesBuilder.AddRange(report.Modules.DistinctBy(x => new { x.Id }).Select(x => new CrashReportToModuleMetadataEntity - { - TenantId = tenant, - CrashReportId = crashReportId, - ModuleId = ModuleId.From(x.Id), - Module = unitOfWrite.UpsertEntityFactory.GetOrCreateModule(ModuleId.From(x.Id)), - Version = ModuleVersion.From(x.Version), - NexusModsModId = NexusModsModId.TryParseUrl(x.Url, out var modId1) ? modId1 : null, - NexusModsMod = NexusModsModId.TryParseUrl(x.Url, out var modId2) ? unitOfWrite.UpsertEntityFactory.GetOrCreateNexusModsMod(modId2) : null, - InvolvedPosition = (byte) (report.InvolvedModules.IndexOf(y => y.ModuleOrLoaderPluginId == x.Id) + 1), - IsInvolved = report.InvolvedModules.Any(y => y.ModuleOrLoaderPluginId == x.Id), - }).ToArray()); + crashReportsBuilder.Add(crashReportEntity); + crashReportMetadatasBuilder.Add(crashReportToMetadataEntity); + crashReportModulesBuilder.AddRange(crashReportToModuleMetadataEntities); } var linkedCrashReports = _linkedCrashReportsChannel.Reader.ReadAllAsync(ct) diff --git a/src/BUTR.Site.NexusMods.Server/Services/HttpClients/ICrashReporterClient.cs b/src/BUTR.Site.NexusMods.Server/Services/HttpClients/ICrashReporterClient.cs index e2d7eade..4790fda7 100644 --- a/src/BUTR.Site.NexusMods.Server/Services/HttpClients/ICrashReporterClient.cs +++ b/src/BUTR.Site.NexusMods.Server/Services/HttpClients/ICrashReporterClient.cs @@ -1,4 +1,3 @@ -using BUTR.CrashReport.Models; using BUTR.Site.NexusMods.Server.Models; using Microsoft.Extensions.Options; @@ -17,7 +16,7 @@ namespace BUTR.Site.NexusMods.Server.Services; public interface ICrashReporterClient { Task GetCrashReportAsync(CrashReportFileId id, CancellationToken ct); - Task GetCrashReportModelAsync(CrashReportFileId id, CancellationToken ct); + Task GetCrashReportJsonAsync(CrashReportFileId id, CancellationToken ct); IAsyncEnumerable GetNewCrashReportMetadatasAsync(DateTime dateTime, CancellationToken ct); IAsyncEnumerable GetCrashReportMetadatasAsync(IEnumerable filenames, CancellationToken ct); } @@ -34,13 +33,7 @@ public CrashReporterClient(HttpClient httpClient, IOptions GetCrashReportAsync(CrashReportFileId id, CancellationToken ct) => await _httpClient.GetStringAsync($"{id}.html", ct); - public async Task GetCrashReportModelAsync(CrashReportFileId id, CancellationToken ct) - { - using var request = new HttpRequestMessage(HttpMethod.Get, $"{id}.json"); - using var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, ct); - if (!response.IsSuccessStatusCode) return null; - return await JsonSerializer.DeserializeAsync(await response.Content.ReadAsStreamAsync(ct), _jsonSerializerOptions, ct); - } + public async Task GetCrashReportJsonAsync(CrashReportFileId id, CancellationToken ct) => await _httpClient.GetStringAsync($"{id}.json", ct); public async IAsyncEnumerable GetNewCrashReportMetadatasAsync(DateTime dateTime, [EnumeratorCancellation] CancellationToken ct) { diff --git a/src/BUTR.Site.NexusMods.Shared/BUTR.Site.NexusMods.Shared.csproj b/src/BUTR.Site.NexusMods.Shared/BUTR.Site.NexusMods.Shared.csproj index 635695db..9f827f15 100644 --- a/src/BUTR.Site.NexusMods.Shared/BUTR.Site.NexusMods.Shared.csproj +++ b/src/BUTR.Site.NexusMods.Shared/BUTR.Site.NexusMods.Shared.csproj @@ -6,15 +6,9 @@ - - all - runtime; build; native; contentfiles; analyzers - + - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/src/BUTR.Site.NexusMods.sln b/src/BUTR.Site.NexusMods.sln index 6cfdd1c0..dc475bf5 100644 --- a/src/BUTR.Site.NexusMods.sln +++ b/src/BUTR.Site.NexusMods.sln @@ -49,6 +49,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BUTR.Site.NexusMods.Depende EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "utils", "utils", "{9F0855BC-D944-428F-8769-6D9B72654EAF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BUTR.Site.NexusMods.Server.CrashReport.v13", "BUTR.Site.NexusMods.Server.CrashReport.v13\BUTR.Site.NexusMods.Server.CrashReport.v13.csproj", "{508B69A9-AB30-4E14-BC57-145134982092}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BUTR.Site.NexusMods.Server.CrashReport.v14", "BUTR.Site.NexusMods.Server.CrashReport.v14\BUTR.Site.NexusMods.Server.CrashReport.v14.csproj", "{AC03984B-D923-4CE6-8B08-1175427285EA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BUTR.Site.NexusMods.Server.Persistence", "BUTR.Site.NexusMods.Server.Persistence\BUTR.Site.NexusMods.Server.Persistence.csproj", "{DCCEF4EA-02B3-41DC-A6A7-669F68036DA8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -87,6 +93,18 @@ Global {775BCF37-ACA2-4BED-996A-EBD0F5955A6F}.Debug|Any CPU.Build.0 = Debug|Any CPU {775BCF37-ACA2-4BED-996A-EBD0F5955A6F}.Release|Any CPU.ActiveCfg = Release|Any CPU {775BCF37-ACA2-4BED-996A-EBD0F5955A6F}.Release|Any CPU.Build.0 = Release|Any CPU + {508B69A9-AB30-4E14-BC57-145134982092}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {508B69A9-AB30-4E14-BC57-145134982092}.Debug|Any CPU.Build.0 = Debug|Any CPU + {508B69A9-AB30-4E14-BC57-145134982092}.Release|Any CPU.ActiveCfg = Release|Any CPU + {508B69A9-AB30-4E14-BC57-145134982092}.Release|Any CPU.Build.0 = Release|Any CPU + {AC03984B-D923-4CE6-8B08-1175427285EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC03984B-D923-4CE6-8B08-1175427285EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC03984B-D923-4CE6-8B08-1175427285EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AC03984B-D923-4CE6-8B08-1175427285EA}.Release|Any CPU.Build.0 = Release|Any CPU + {DCCEF4EA-02B3-41DC-A6A7-669F68036DA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DCCEF4EA-02B3-41DC-A6A7-669F68036DA8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DCCEF4EA-02B3-41DC-A6A7-669F68036DA8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DCCEF4EA-02B3-41DC-A6A7-669F68036DA8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -105,6 +123,9 @@ Global {26AE4C2C-03BF-44B1-872F-8FD1573C9E90} = {9F0855BC-D944-428F-8769-6D9B72654EAF} {72FFDBF7-742C-4DCD-B98A-F2B15F099775} = {9F0855BC-D944-428F-8769-6D9B72654EAF} {39C2FBEB-7E1A-430C-82C0-01EE2A02F0A4} = {9F0855BC-D944-428F-8769-6D9B72654EAF} + {AC03984B-D923-4CE6-8B08-1175427285EA} = {9F0855BC-D944-428F-8769-6D9B72654EAF} + {508B69A9-AB30-4E14-BC57-145134982092} = {9F0855BC-D944-428F-8769-6D9B72654EAF} + {DCCEF4EA-02B3-41DC-A6A7-669F68036DA8} = {9F0855BC-D944-428F-8769-6D9B72654EAF} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {5CC1A63D-E570-4BEB-8282-0BD9B24B5C5C}