TellmePdmsPluging/Network/BatchTaskResultCallbackService.cs

125 lines
4.1 KiB
C#

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<string, object>
{
{ "execution_id", executionId },
{ "software_id", _softwareId },
{ "status", success ? "success" : "failed" },
{ "error_message", success ? null : GetFailedErrorMessage(errorMessage) },
{ "result", success ? (result ?? new Dictionary<string, object>()) : new Dictionary<string, object>() },
{ "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;
}
}
}