using System; using System.Collections.Generic; using System.Net; using System.Text; using System.Threading; using System.Web.Script.Serialization; namespace TellmePdmsPluging.Network { internal class BatchTaskResultCallbackService { private readonly string _serverAddress; private readonly string _token; private readonly string _softwareId; private readonly JavaScriptSerializer _serializer = new JavaScriptSerializer(); private readonly int[] _retryDelaysMs = new[] { 1000, 3000, 5000 }; public BatchTaskResultCallbackService(string serverAddress, string token, string softwareId) { _serverAddress = NormalizeServerAddress(serverAddress); _token = token ?? string.Empty; _softwareId = string.IsNullOrEmpty(softwareId) ? "pdms" : softwareId; } public void NotifyTaskResultAsync(string executionId, bool success, string errorMessage, object result) { if (string.IsNullOrEmpty(executionId)) { return; } if (string.IsNullOrEmpty(_serverAddress) || string.IsNullOrEmpty(_token)) { return; } ThreadPool.QueueUserWorkItem(_ => { TryPostWithRetries(executionId, success, errorMessage, result); }); } private void TryPostWithRetries(string executionId, bool success, string errorMessage, object result) { string callbackUrl = _serverAddress + "/api/v1/plugin-callbacks/task-result"; var payload = new Dictionary { { "execution_id", executionId }, { "software_id", _softwareId }, { "status", success ? "success" : "failed" }, { "error_message", success ? null : GetFailedErrorMessage(errorMessage) }, { "result", success ? (result ?? new Dictionary()) : new Dictionary() }, { "finished_at", DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") }, { "token", _token } }; string json = _serializer.Serialize(payload); for (int attempt = 0; attempt < _retryDelaysMs.Length + 1; attempt++) { if (PostJson(callbackUrl, json)) { return; } if (attempt < _retryDelaysMs.Length) { Thread.Sleep(_retryDelaysMs[attempt]); } } } private static bool PostJson(string url, string json) { try { var request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.ContentType = "application/json"; request.Timeout = 15000; byte[] data = Encoding.UTF8.GetBytes(json); request.ContentLength = data.Length; using (var stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); } using (var response = (HttpWebResponse)request.GetResponse()) { int statusCode = (int)response.StatusCode; return statusCode >= 200 && statusCode < 300; } } catch { return false; } } private static string NormalizeServerAddress(string serverAddress) { if (string.IsNullOrEmpty(serverAddress)) { return null; } string value = serverAddress.Trim(); while (value.EndsWith("/", StringComparison.Ordinal)) { value = value.Substring(0, value.Length - 1); } return value; } private static string GetFailedErrorMessage(string errorMessage) { return string.IsNullOrEmpty(errorMessage) ? "UNKNOWN_ERROR" : errorMessage; } } }