using System.IO.Compression; using Dapper; using ScrapperAPI.Dtos; using ScrapperAPI.Interfaces; using ScrapperAPI.Records; using ScrapperAPI.Utils; namespace ScrapperAPI.Repositories; public sealed class ContentRepository : IContentRepository { private readonly IDbConnectionFactory _db; public ContentRepository(IDbConnectionFactory db) => _db = db; public async Task SaveAsync(int queueId, string content, CancellationToken ct) { var compressed = CompressionUtils.GzipCompressUtf8(content, CompressionLevel.Fastest); const string sql = """ insert into content(queue_id, content_encoding, content_bytes, original_length, compressed_length) values (@queueId, 'gzip', @bytes, @origLen, @compLen) returning id; """; using var conn = await _db.CreateOpenConnectionAsync(ct); return await conn.ExecuteScalarAsync(new CommandDefinition(sql, new { queueId, bytes = compressed, origLen = content.Length, // chars (ok) compLen = compressed.Length // bytes }, cancellationToken: ct)); } public async Task GetByQueueIdAsync(int queueId, CancellationToken ct) { const string sql = """ select id, queue_id as QueueId, content, created_date as CreatedDate from content where queue_id = @queueId order by id desc limit 1; """; using var conn = await _db.CreateOpenConnectionAsync(ct); return await conn.QuerySingleOrDefaultAsync( new CommandDefinition(sql, new { queueId }, cancellationToken: ct)); } public async Task GetCompressedByQueueIdAsync( int queueId, CancellationToken ct ) { const string sql = """ select id, queue_id as QueueId, content_encoding as ContentEncoding, content_bytes as ContentBytes, original_length as OriginalLength, compressed_length as CompressedLength, created_date as CreatedDate from content where queue_id = @queueId order by id desc limit 1; """; using var conn = await _db.CreateOpenConnectionAsync(ct); return await conn.QuerySingleOrDefaultAsync( new CommandDefinition( sql, new { queueId }, cancellationToken: ct ) ); } }