using System.Text; using System.Text.Json; using LiquidCode.Tester.Common.Models; namespace LiquidCode.Tester.Worker.Services; public class CallbackService : ICallbackService { private readonly IHttpClientFactory _httpClientFactory; private readonly ILogger _logger; public CallbackService(IHttpClientFactory httpClientFactory, ILogger logger) { _httpClientFactory = httpClientFactory; _logger = logger; } public async Task SendStatusAsync(string callbackUrl, TesterResponseModel response) { // Check if callback should be logged instead of sent via HTTP if (IsLogCallback(callbackUrl)) { LogCallback(response); return; } _logger.LogInformation("Sending status update to {CallbackUrl} for submit {SubmitId}", callbackUrl, response.SubmitId); try { var httpClient = _httpClientFactory.CreateClient(); var json = JsonSerializer.Serialize(response); var content = new StringContent(json, Encoding.UTF8, "application/json"); var httpResponse = await httpClient.PostAsync(callbackUrl, content); httpResponse.EnsureSuccessStatusCode(); _logger.LogInformation("Status update sent successfully"); } catch (Exception ex) { _logger.LogError(ex, "Failed to send status update to {CallbackUrl}", callbackUrl); // Don't throw - callback failures shouldn't stop testing } } private bool IsLogCallback(string callbackUrl) { if (string.IsNullOrWhiteSpace(callbackUrl)) { return false; } var normalized = callbackUrl.Trim().ToLowerInvariant(); return normalized == "log" || normalized == "console" || normalized.StartsWith("log://"); } private void LogCallback(TesterResponseModel response) { var options = new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; var json = JsonSerializer.Serialize(response, options); _logger.LogInformation( "\n" + "╔═══════════════════════════════════════════════════════════════╗\n" + "║ CALLBACK RESULT ║\n" + "╠═══════════════════════════════════════════════════════════════╣\n" + "{Json}\n" + "╚═══════════════════════════════════════════════════════════════╝", json); } }