Skip to content

Commit

Permalink
Crah Report Multitenant support
Browse files Browse the repository at this point in the history
  • Loading branch information
Aragas committed Oct 10, 2024
1 parent 93b5363 commit 6f08b34
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/BUTR.Site.NexusMods.Client/Shared/Footer.razor
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
</Div>

<Div Flex="Flex.JustifyContent.Center">
© 2022-2023 BUTR
© 2022-2024 BUTR
</Div>
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BUTR.Site.NexusMods.Server.Utils.BindingSources;

namespace BUTR.Site.NexusMods.Server.Controllers;

Expand All @@ -39,15 +40,15 @@ public RecreateStacktraceController(ILogger<RecreateStacktraceController> logger

[HttpGet("Json")]
[Produces("application/json")]
public async Task<ApiResult<IEnumerable<RecreatedStacktrace>?>> GetJsonAsync([FromQuery] CrashReportFileId id, CancellationToken ct)
public async Task<ApiResult<IEnumerable<RecreatedStacktrace>?>> GetJsonAsync([BindTenant] TenantId tenant, [FromQuery] CrashReportFileId id, CancellationToken ct)
{
if (!HttpContext.OwnsTenantGame())
return ApiResultError("Game is not owned!", StatusCodes.Status401Unauthorized);

string crashReportContent;
try
{
crashReportContent = await _crashReporterClient.GetCrashReportAsync(id, ct);
crashReportContent = await _crashReporterClient.GetCrashReportAsync(tenant, id, ct);
}
catch (HttpRequestException e) when (e.StatusCode == HttpStatusCode.NotFound)
{
Expand Down Expand Up @@ -76,15 +77,15 @@ public RecreateStacktraceController(ILogger<RecreateStacktraceController> logger

[HttpGet("Html")]
[Produces("text/plain")]
public async Task<ActionResult<string>> GetHtmlAsync([FromQuery] CrashReportFileId id, CancellationToken ct)
public async Task<ActionResult<string>> GetHtmlAsync([BindTenant] TenantId tenant, [FromQuery] CrashReportFileId id, CancellationToken ct)
{
if (!HttpContext.OwnsTenantGame())
return Unauthorized();

string crashReportContent;
try
{
crashReportContent = await _crashReporterClient.GetCrashReportAsync(id, ct);
crashReportContent = await _crashReporterClient.GetCrashReportAsync(tenant, id, ct);
}
catch (HttpRequestException e) when (e.StatusCode == HttpStatusCode.NotFound)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

using System.Threading;
using System.Threading.Tasks;
using BUTR.Site.NexusMods.Server.Utils.BindingSources;

namespace BUTR.Site.NexusMods.Server.Controllers;

Expand All @@ -27,7 +28,10 @@ public ReportsController(ILogger<ReportsController> logger, ICrashReporterClient

[HttpGet("{id}.html")]
[Produces("text/html")]
public async Task<ActionResult<string>> GetAllAsync(CrashReportFileId id, CancellationToken ct) => Ok(await _crashReporterClient.GetCrashReportAsync(id, ct));
public async Task<ActionResult<string>> GetAllAsync([BindTenant] TenantId tenant, CrashReportFileId id, CancellationToken ct)
{
return Ok(await _crashReporterClient.GetCrashReportAsync(tenant, id, ct));
}

// Just so we have ApiResult type in swagger.json
[HttpGet("BlankRequest")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public async Task Execute(IJobExecutionContext context)
{
await using var scope = _serviceScopeFactory.CreateAsyncScope().WithTenant(tenant);
var crashReportBatchedHandler = scope.ServiceProvider.GetRequiredService<ICrashReportBatchedHandler>();
await foreach (var batch in _crashReporterClient.GetNewCrashReportMetadatasAsync(DateTime.UtcNow.AddDays(-2), ct).OfType<CrashReportFileMetadata>().ChunkAsync(100).WithCancellation(ct))
await foreach (var batch in _crashReporterClient.GetNewCrashReportMetadatasAsync(tenant, DateTime.UtcNow.AddDays(-2), ct).OfType<CrashReportFileMetadata>().ChunkAsync(100).WithCancellation(ct))
processed += await crashReportBatchedHandler.HandleBatchAsync(batch, ct);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ await _ignoredCrashReportsChannel.Writer.WriteAsync(new CrashReportIgnoredFileEn

private async Task DownloadCrashReportsAsync(CancellationToken ct)
{
var tenant = _tenantContextAccessor.Current;

try
{
var exceptions = new ConcurrentQueue<Exception>();
Expand All @@ -163,11 +165,11 @@ await Parallel.ForEachAsync(_toDownloadChannel.Reader.ReadAllAsync(ct), options,
{
if (version <= 12)
{
content = await _client.GetCrashReportAsync(fileId, ct2);
content = await _client.GetCrashReportAsync(tenant, fileId, ct2);
}
else
{
content = await _client.GetCrashReportJsonAsync(fileId, ct2);
content = await _client.GetCrashReportJsonAsync(tenant, fileId, ct2);
}
}
catch (Exception e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ namespace BUTR.Site.NexusMods.Server.Services;

public interface ICrashReporterClient
{
Task<string> GetCrashReportAsync(CrashReportFileId id, CancellationToken ct);
Task<string> GetCrashReportJsonAsync(CrashReportFileId id, CancellationToken ct);
IAsyncEnumerable<CrashReportFileMetadata?> GetNewCrashReportMetadatasAsync(DateTime dateTime, CancellationToken ct);
IAsyncEnumerable<CrashReportFileMetadata?> GetCrashReportMetadatasAsync(IEnumerable<CrashReportFileId> filenames, CancellationToken ct);
Task<string> GetCrashReportAsync(TenantId tenant, CrashReportFileId id, CancellationToken ct);
Task<string> GetCrashReportJsonAsync(TenantId tenant, CrashReportFileId id, CancellationToken ct);
IAsyncEnumerable<CrashReportFileMetadata?> GetNewCrashReportMetadatasAsync(TenantId tenant, DateTime dateTime, CancellationToken ct);
IAsyncEnumerable<CrashReportFileMetadata?> GetCrashReportMetadatasAsync(TenantId tenant, IEnumerable<CrashReportFileId> filenames, CancellationToken ct);
}

public sealed class CrashReporterClient : ICrashReporterClient
Expand All @@ -32,20 +32,20 @@ public CrashReporterClient(HttpClient httpClient, IOptions<JsonSerializerOptions
_jsonSerializerOptions = jsonSerializerOptions.Value;
}

public async Task<string> GetCrashReportAsync(CrashReportFileId id, CancellationToken ct) => await _httpClient.GetStringAsync($"{id}.html", ct);
public async Task<string> GetCrashReportJsonAsync(CrashReportFileId id, CancellationToken ct) => await _httpClient.GetStringAsync($"{id}.json", ct);
public async Task<string> GetCrashReportAsync(TenantId tenant, CrashReportFileId id, CancellationToken ct) => await _httpClient.GetStringAsync($"{tenant}/{id}.html", ct);
public async Task<string> GetCrashReportJsonAsync(TenantId tenant, CrashReportFileId id, CancellationToken ct) => await _httpClient.GetStringAsync($"{tenant}/{id}.json", ct);

public async IAsyncEnumerable<CrashReportFileMetadata?> GetNewCrashReportMetadatasAsync(DateTime dateTime, [EnumeratorCancellation] CancellationToken ct)
public async IAsyncEnumerable<CrashReportFileMetadata?> GetNewCrashReportMetadatasAsync(TenantId tenant, DateTime dateTime, [EnumeratorCancellation] CancellationToken ct)
{
using var request = new HttpRequestMessage(HttpMethod.Post, "getnewcrashreports");
using var request = new HttpRequestMessage(HttpMethod.Post, $"{tenant}/getnewcrashreports");
request.Content = JsonContent.Create(new { DateTime = dateTime.ToString("o") }, options: _jsonSerializerOptions);
using var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, ct);
await foreach (var entry in JsonSerializer.DeserializeAsyncEnumerable<CrashReportFileMetadata>(await response.Content.ReadAsStreamAsync(ct), _jsonSerializerOptions, ct))
yield return entry;
}
public async IAsyncEnumerable<CrashReportFileMetadata?> GetCrashReportMetadatasAsync(IEnumerable<CrashReportFileId> filenames, [EnumeratorCancellation] CancellationToken ct)
public async IAsyncEnumerable<CrashReportFileMetadata?> GetCrashReportMetadatasAsync(TenantId tenant, IEnumerable<CrashReportFileId> filenames, [EnumeratorCancellation] CancellationToken ct)
{
using var request = new HttpRequestMessage(HttpMethod.Post, "getmetadata");
using var request = new HttpRequestMessage(HttpMethod.Post, $"{tenant}/getmetadata");
request.Content = JsonContent.Create(filenames, options: _jsonSerializerOptions);
using var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, ct);
await foreach (var entry in JsonSerializer.DeserializeAsyncEnumerable<CrashReportFileMetadata>(await response.Content.ReadAsStreamAsync(ct), _jsonSerializerOptions, ct))
Expand Down

0 comments on commit 6f08b34

Please sign in to comment.