generated from fahricansecer/boilerplate-be
This commit is contained in:
140
media-worker/Services/DatabaseService.cs
Normal file
140
media-worker/Services/DatabaseService.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Npgsql;
|
||||
|
||||
namespace SaasMediaWorker.Services;
|
||||
|
||||
/// <summary>
|
||||
/// PostgreSQL veritabanı servisi — RenderJob ve Project durumlarını günceller.
|
||||
/// NestJS Prisma schema'sıyla uyumlu SQL sorguları kullanır.
|
||||
///
|
||||
/// Neden doğrudan SQL (ORM yerine)?
|
||||
/// - C# Worker minimum footprint olmalı (16GB RPi).
|
||||
/// - Sadece UPDATE sorguları yapılıyor — ORM gereksiz overhead.
|
||||
/// - Npgsql ARM64'te native çalışır.
|
||||
/// </summary>
|
||||
public class DatabaseService
|
||||
{
|
||||
private readonly ILogger<DatabaseService> _logger;
|
||||
private readonly string _connectionString;
|
||||
|
||||
public DatabaseService(
|
||||
ILogger<DatabaseService> logger,
|
||||
IConfiguration configuration)
|
||||
{
|
||||
_logger = logger;
|
||||
_connectionString = configuration.GetConnectionString("DefaultConnection")
|
||||
?? throw new InvalidOperationException("DefaultConnection bağlantı dizesi bulunamadı");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RenderJob tablosunun durumunu günceller.
|
||||
/// </summary>
|
||||
public async Task UpdateRenderJobStatus(
|
||||
string renderJobId,
|
||||
string status,
|
||||
int progress,
|
||||
string? currentStage,
|
||||
string? errorMessage = null,
|
||||
string? errorStack = null,
|
||||
long? processingTimeMs = null,
|
||||
string? workerVersion = null,
|
||||
string? workerHostname = null)
|
||||
{
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
|
||||
var sql = @"
|
||||
UPDATE ""RenderJob""
|
||||
SET ""status"" = @status::""RenderJobStatus"",
|
||||
""progress"" = @progress,
|
||||
""currentStage"" = CASE WHEN @stage IS NOT NULL THEN @stage::""RenderStage"" ELSE ""currentStage"" END,
|
||||
""errorMessage"" = COALESCE(@errorMessage, ""errorMessage""),
|
||||
""errorStack"" = COALESCE(@errorStack, ""errorStack""),
|
||||
""processingTimeMs"" = COALESCE(@processingTimeMs, ""processingTimeMs""),
|
||||
""workerVersion"" = COALESCE(@workerVersion, ""workerVersion""),
|
||||
""workerHostname"" = COALESCE(@workerHostname, ""workerHostname""),
|
||||
""startedAt"" = CASE WHEN @status = 'PROCESSING' AND ""startedAt"" IS NULL THEN NOW() ELSE ""startedAt"" END,
|
||||
""completedAt"" = CASE WHEN @status IN ('COMPLETED', 'FAILED') THEN NOW() ELSE ""completedAt"" END,
|
||||
""lastErrorAt"" = CASE WHEN @status = 'FAILED' THEN NOW() ELSE ""lastErrorAt"" END,
|
||||
""updatedAt"" = NOW()
|
||||
WHERE ""id"" = @id";
|
||||
|
||||
await using var cmd = new NpgsqlCommand(sql, conn);
|
||||
cmd.Parameters.AddWithValue("id", renderJobId);
|
||||
cmd.Parameters.AddWithValue("status", status);
|
||||
cmd.Parameters.AddWithValue("progress", progress);
|
||||
cmd.Parameters.AddWithValue("stage", (object?)currentStage ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("errorMessage", (object?)errorMessage ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("errorStack", (object?)errorStack ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("processingTimeMs", (object?)processingTimeMs ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("workerVersion", (object?)workerVersion ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("workerHostname", (object?)workerHostname ?? DBNull.Value);
|
||||
|
||||
var affected = await cmd.ExecuteNonQueryAsync();
|
||||
_logger.LogDebug("RenderJob güncellendi: {Id} → {Status} ({Progress}%)", renderJobId, status, progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Project tablosunun durumunu günceller.
|
||||
/// </summary>
|
||||
public async Task UpdateProjectStatus(
|
||||
string projectId,
|
||||
string status,
|
||||
int progress,
|
||||
string? finalVideoUrl = null,
|
||||
string? errorMessage = null)
|
||||
{
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
|
||||
var sql = @"
|
||||
UPDATE ""Project""
|
||||
SET ""status"" = @status::""ProjectStatus"",
|
||||
""progress"" = @progress,
|
||||
""finalVideoUrl"" = COALESCE(@finalVideoUrl, ""finalVideoUrl""),
|
||||
""errorMessage"" = @errorMessage,
|
||||
""completedAt"" = CASE WHEN @status = 'COMPLETED' THEN NOW() ELSE ""completedAt"" END,
|
||||
""updatedAt"" = NOW()
|
||||
WHERE ""id"" = @id";
|
||||
|
||||
await using var cmd = new NpgsqlCommand(sql, conn);
|
||||
cmd.Parameters.AddWithValue("id", projectId);
|
||||
cmd.Parameters.AddWithValue("status", status);
|
||||
cmd.Parameters.AddWithValue("progress", progress);
|
||||
cmd.Parameters.AddWithValue("finalVideoUrl", (object?)finalVideoUrl ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("errorMessage", (object?)errorMessage ?? DBNull.Value);
|
||||
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
_logger.LogDebug("Project güncellendi: {Id} → {Status} ({Progress}%)", projectId, status, progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Render log kaydı ekler.
|
||||
/// </summary>
|
||||
public async Task AddRenderLog(
|
||||
string renderJobId,
|
||||
string stage,
|
||||
string message,
|
||||
string level = "info",
|
||||
int? durationMs = null,
|
||||
string? metadata = null)
|
||||
{
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync();
|
||||
|
||||
var sql = @"
|
||||
INSERT INTO ""RenderLog"" (""id"", ""renderJobId"", ""stage"", ""message"", ""level"", ""durationMs"", ""metadata"", ""createdAt"")
|
||||
VALUES (gen_random_uuid(), @renderJobId, @stage::""RenderStage"", @message, @level, @durationMs, @metadata::jsonb, NOW())";
|
||||
|
||||
await using var cmd = new NpgsqlCommand(sql, conn);
|
||||
cmd.Parameters.AddWithValue("renderJobId", renderJobId);
|
||||
cmd.Parameters.AddWithValue("stage", stage);
|
||||
cmd.Parameters.AddWithValue("message", message);
|
||||
cmd.Parameters.AddWithValue("level", level);
|
||||
cmd.Parameters.AddWithValue("durationMs", (object?)durationMs ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("metadata", (object?)metadata ?? DBNull.Value);
|
||||
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user