Skip to content

Commit

Permalink
Using the external id generator since SQLite will do an error
Browse files Browse the repository at this point in the history
  • Loading branch information
Aragas committed Feb 24, 2024
1 parent 4ef807a commit e3b0346
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 37 deletions.
25 changes: 13 additions & 12 deletions src/BUTR.CrashReportServer/Controllers/CrashUploadController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.IO.Pipelines;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
Expand All @@ -36,6 +37,7 @@ public sealed record CrashReportUploadBody(CrashReportModel CrashReport, ICollec
private readonly JsonSerializerOptions _jsonSerializerOptions;
private readonly AppDbContext _dbContext;
private readonly GZipCompressor _gZipCompressor;
private readonly HexGenerator _hexGenerator;

private readonly Counter<int> _reportVersion;

Expand All @@ -45,6 +47,7 @@ public CrashUploadController(
IOptionsSnapshot<JsonSerializerOptions> jsonSerializerOptions,
AppDbContext dbContext,
GZipCompressor gZipCompressor,
HexGenerator hexGenerator,
IMeterFactory meterFactory)
{
var meter = meterFactory.Create("BUTR.CrashReportServer.Controllers.CrashUploadController", "1.0.0");
Expand All @@ -56,25 +59,23 @@ public CrashUploadController(
_options = options.Value ?? throw new ArgumentNullException(nameof(options));
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
_gZipCompressor = gZipCompressor ?? throw new ArgumentNullException(nameof(gZipCompressor));
_hexGenerator = hexGenerator ?? throw new ArgumentNullException(nameof(hexGenerator));
}

/*
private async Task<string> GenerateFileId(CancellationToken ct)
private string GenerateFileId(CancellationToken ct)
{
const int count = 100;
const int count = 300;
var fileId = string.Empty;
while (!ct.IsCancellationRequested)
{
var fileIds = Enumerable.Range(0, count).Select(_ => _hexGenerator.GetHex()).ToHashSet();
var existing = await _dbContext.Set<IdEntity>().Select(x => x.FileId).Where(x => fileIds.Contains(x)).ToArrayAsync(ct);
if (existing.Length == count) continue;
fileIds.ExceptWith(existing);
fileId = fileIds.First();
var fileIds = _hexGenerator.GetHex(count, 3);
var existing = _dbContext.Set<IdEntity>().Select(x => x.FileId).Where(x => fileIds.Contains(x)).ToHashSet();
if (existing.Count == count) continue;
fileId = existing.First(x => !fileIds.Contains(x));
break;
}
return fileId;
}
*/

private async Task<IActionResult> UploadHtmlAsync(CancellationToken ct)
{
Expand All @@ -93,13 +94,13 @@ private async Task<IActionResult> UploadHtmlAsync(CancellationToken ct)
Converters = { new JsonStringEnumConverter() }
}), ct);

idEntity = new IdEntity { FileId = default!, CrashReportId = id, Version = version, Created = DateTime.UtcNow, };
idEntity = new IdEntity { FileId = GenerateFileId(ct), CrashReportId = id, Version = version, Created = DateTime.UtcNow, };
await _dbContext.Set<IdEntity>().AddAsync(idEntity, ct);
await _dbContext.Set<FileEntity>().AddAsync(new FileEntity { Id = idEntity, DataCompressed = compressedHtmlStream.ToArray(), }, ct);
if (version >= 13) await _dbContext.Set<JsonEntity>().AddAsync(new JsonEntity { Id = idEntity, CrashReportCompressed = compressedJsonStream.ToArray(), }, ct);
await _dbContext.SaveChangesAsync(ct);

_reportVersion.Add(1, new[] {new KeyValuePair<string, object?>("Version", version)});
_reportVersion.Add(1, new[] { new KeyValuePair<string, object?>("Version", version) });

return Ok($"{_options.BaseUri}/{idEntity.FileId}");
}
Expand All @@ -121,7 +122,7 @@ private async Task<IActionResult> UploadJsonAsync(CancellationToken ct)
await using var compressedHtmlStream = await _gZipCompressor.CompressAsync(html.AsStream(), ct);
await using var compressedJsonStream = await _gZipCompressor.CompressAsync(json.AsStream(), ct);

idEntity = new IdEntity { FileId = default!, CrashReportId = crashReport.Id, Version = crashReport.Version, Created = DateTime.UtcNow, };
idEntity = new IdEntity { FileId = GenerateFileId(ct), CrashReportId = crashReport.Id, Version = crashReport.Version, Created = DateTime.UtcNow, };
await _dbContext.Set<IdEntity>().AddAsync(idEntity, ct);
await _dbContext.Set<JsonEntity>().AddAsync(new JsonEntity { Id = idEntity, CrashReportCompressed = compressedJsonStream.ToArray(), }, ct);
await _dbContext.Set<FileEntity>().AddAsync(new FileEntity { Id = idEntity, DataCompressed = compressedHtmlStream.ToArray(), }, ct);
Expand Down
47 changes: 22 additions & 25 deletions src/BUTR.CrashReportServer/Services/HexGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,46 +1,43 @@
using Microsoft.Extensions.Logging;

using System;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;

namespace BUTR.CrashReportServer.Services;

public sealed class HexGenerator
{
private readonly ILogger _logger;
private readonly RandomNumberGenerator _random;

public HexGenerator(ILogger<HexGenerator> logger, RandomNumberGenerator random)
public HexGenerator(RandomNumberGenerator random)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_random = random ?? throw new ArgumentNullException(nameof(random));
}

private static int GetHexChars(in ReadOnlySpan<byte> source, Span<char> buffer)
private static int GenerateHexChars(in ReadOnlySpan<byte> source, Span<char> destination)
{
var idx1 = 0;
var idx2 = 0;
while (idx2 < source.Length)
for (var i = 0; i < source.Length; i++)
{
var num1 = (byte) ((uint) source[idx2] >> 4);
buffer[idx1] = num1 > (byte) 9 ? (char) ((int) num1 + 55 + 32) : (char) ((int) num1 + 48);
var num2 = (byte) ((uint) source[idx2] & 15U);
int num3;
buffer[num3 = idx1 + 1] = num2 > (byte) 9 ? (char) ((int) num2 + 55 + 32) : (char) ((int) num2 + 48);
++idx2;
idx1 = num3 + 1;
var char1 = source[i] >> 4;
destination[i * 2] = char.ToUpperInvariant(char1 > 9 ? (char) (char1 + 55 + 32) : (char) (char1 + 48));
var char2 = source[i] & 15;
destination[i * 2 + 1] = char.ToUpperInvariant(char2 > 9 ? (char) (char2 + 55 + 32) : (char) (char2 + 48));
}
return idx1;
return source.Length * 2;
}

public string GetHex()
public HashSet<string> GetHex(int maxCount, int length)
{
Span<byte> input = stackalloc byte[3];
Span<char> output = stackalloc char[6];
var charLength = length * 2;
var byteLength = length;

Span<char> output = stackalloc char[maxCount * charLength];
Span<byte> input = stackalloc byte[maxCount * byteLength];
_random.GetBytes(input);
GetHexChars(input, output);
for (var i = 0; i < output.Length; i++)
output[i] = char.ToUpper(output[i]);
return output.ToString();

var unique = new HashSet<string>(maxCount);
GenerateHexChars(input, output);
for (var i = 0; i < output.Length; i += charLength)
unique.Add(output.Slice(i, charLength).ToString());
return unique;
}
}

0 comments on commit e3b0346

Please sign in to comment.