init commit
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
using SimpleCore;
|
||||
using SimpleCore.Library;
|
||||
using StandardScene.Utils;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
using StandardScene.Model;
|
||||
|
||||
namespace StandardScene.Chained
|
||||
{
|
||||
/// <summary>
|
||||
/// 统一管理 TransportDelivery 相关的任务回调方法,并通过回调注册表提供可恢复性。
|
||||
/// </summary>
|
||||
public static class TransportDeliveryCallbacks
|
||||
{
|
||||
public const string KeyOnStarted = "Transport.OnMissionStarted";
|
||||
public const string KeyOnFetched = "Transport.OnFetched";
|
||||
public const string KeyOnPut = "Transport.OnPut";
|
||||
public const string KeyOnFinished = "Transport.OnMissionFinished";
|
||||
public const string KeyOnFailed = "Transport.OnMissionFailed";
|
||||
public const string KeyOnTerminated = "Transport.OnMissionTerminated";
|
||||
|
||||
private static bool _initialized;
|
||||
private static readonly HttpClient _httpClient = new HttpClient();
|
||||
private static string _callbackUrl = "http://127.0.0.1:20101/api/v1/MDCS/State";
|
||||
|
||||
static TransportDeliveryCallbacks()
|
||||
{
|
||||
if (_initialized) return;
|
||||
_initialized = true;
|
||||
|
||||
DeliveryCallbackRegistry.RegisterOnStart (KeyOnStarted, OnMissionStarted);
|
||||
DeliveryCallbackRegistry.RegisterDoneFetch (KeyOnFetched, OnFetched);
|
||||
DeliveryCallbackRegistry.RegisterDonePut (KeyOnPut, OnPut);
|
||||
DeliveryCallbackRegistry.RegisterDoneMission(KeyOnFinished, OnMissionFinished);
|
||||
DeliveryCallbackRegistry.RegisterFailed (KeyOnFailed, OnMissionFailed);
|
||||
DeliveryCallbackRegistry.RegisterOnTerminated(KeyOnTerminated, OnMissionTerminated);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显式调用以确保静态构造函数已执行(注册所有默认回调)。
|
||||
/// </summary>
|
||||
public static void EnsureInitialized()
|
||||
{
|
||||
// 访问本类,确保静态构造已执行
|
||||
if (!_initialized)
|
||||
{
|
||||
// 触发 static ctor(CLR 保证线程安全)
|
||||
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(TransportDeliveryCallbacks).TypeHandle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置任务状态回调的完整 URL(例如 http://ip:port/api/v1/MDCS/State)。
|
||||
/// 建议在 TransportMission 启动或构造时调用一次。
|
||||
/// </summary>
|
||||
public static void ConfigureCallbackUrl(string url)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(url))
|
||||
{
|
||||
_callbackUrl = url;
|
||||
}
|
||||
}
|
||||
|
||||
private static void DispatchMissionState(TransportDelivery d, MissionState.MissionStateEnum state)
|
||||
{
|
||||
var ms = new MissionState
|
||||
{
|
||||
MissionId = d.TaskId,
|
||||
CarCode = d.UsingCar?.id.ToString() ?? "0",
|
||||
TriggerTime = DateTime.Now,
|
||||
State = state
|
||||
};
|
||||
MissionStatePost(ms);
|
||||
}
|
||||
|
||||
private static async void MissionStatePost(MissionState ms)
|
||||
{
|
||||
var retryCount = 10;
|
||||
var retryDelay = TimeSpan.FromSeconds(1);
|
||||
var content = new StringContent(ms.ToJson());
|
||||
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||
|
||||
for (int i = 0; i < retryCount; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
var resp = await _httpClient.PostAsync(_callbackUrl, content);
|
||||
Diagnosis.Post($"{ms.State}回调结果 => {resp.Content.ReadAsStringAsync().Result}");
|
||||
var body = resp.Content.ReadAsStringAsync().Result.JsonTo<BaseRespose>();
|
||||
var result = body.Code == 200 ? "成功" : "失败";
|
||||
Diagnosis.Post($"车辆编号:{ms.CarCode} 任务id:{ms.MissionId} 状态回调执行{result}");
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Diagnosis.Log($"{ms.State}状态回调失败 => ex:{ex}");
|
||||
if (i == retryCount - 1)
|
||||
{
|
||||
Diagnosis.Log($"StringContent:{content}", "apiError");
|
||||
}
|
||||
await Task.Delay(retryDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async void OnMissionStarted(ChainedDeliveryMission.Delivery delivery)
|
||||
{
|
||||
var d = (TransportDelivery)delivery;
|
||||
Diagnosis.Log($"task(#{d.TaskId}) started");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(d.TaskIdsString))
|
||||
{
|
||||
Commons.AddOrUpdateTag(d.UsingCar.tags, "taskIdsString", d.TaskIdsString);
|
||||
Diagnosis.Log(
|
||||
$"holdCarTagAddOrUpdate--TaskId:{d.TaskId},task:[{d.ToJson()}].taskIdsString:{d.TaskIdsString}",
|
||||
"holdCarTag",
|
||||
true);
|
||||
}
|
||||
|
||||
Commons.DeleteTag(d.UsingCar.tags, "holdCar");
|
||||
if (!string.IsNullOrEmpty(d.HoldCarSite))
|
||||
{
|
||||
Commons.AddOrUpdateTag(d.UsingCar.tags, "holdCar", d.HoldCarSite);
|
||||
Diagnosis.Log(
|
||||
$"holdCarTagAddOrUpdate--TaskId:{d.TaskId},task:[{d.ToJson()}].holdCar:{d.HoldCarSite}",
|
||||
"holdCarTag",
|
||||
true);
|
||||
}
|
||||
|
||||
DispatchMissionState(d, MissionState.MissionStateEnum.Started);
|
||||
}
|
||||
|
||||
public static async void OnFetched(ChainedDeliveryMission.Delivery delivery)
|
||||
{
|
||||
var d = (TransportDelivery)delivery;
|
||||
if (d.Src == d.Dst) return;
|
||||
|
||||
Diagnosis.Log($"task(#{d.TaskId}) fetched");
|
||||
DispatchMissionState(d, MissionState.MissionStateEnum.Fetched);
|
||||
}
|
||||
|
||||
public static async void OnPut(ChainedDeliveryMission.Delivery delivery)
|
||||
{
|
||||
var d = (TransportDelivery)delivery;
|
||||
if (d.Src == d.Dst) return;
|
||||
|
||||
Diagnosis.Log($"task(#{d.TaskId}) put");
|
||||
DispatchMissionState(d, MissionState.MissionStateEnum.Put);
|
||||
}
|
||||
|
||||
public static async void OnMissionFailed(ChainedDeliveryMission.Delivery delivery)
|
||||
{
|
||||
var d = (TransportDelivery)delivery;
|
||||
Diagnosis.Log($"task(#{d.TaskId}) failed");
|
||||
DispatchMissionState(d, MissionState.MissionStateEnum.Failed);
|
||||
}
|
||||
|
||||
public static async void OnMissionFinished(ChainedDeliveryMission.Delivery delivery)
|
||||
{
|
||||
var d = (TransportDelivery)delivery;
|
||||
Diagnosis.Log($"task(#{d.TaskId}) finished");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(d.MGTaskCode!) && d.MGTaskCode.Contains("-"))
|
||||
{
|
||||
var phase = d.MGTaskCode.Split('-')[1];
|
||||
var last = int.Parse(phase) - 1;
|
||||
if (last > 0 && string.IsNullOrWhiteSpace(d.TaskIdsString))
|
||||
{
|
||||
var holdCar = SimpleLib.GetAllCars()
|
||||
.FirstOrDefault(e => e.tags.TryGetValue("taskIdsString", out var v) && v.Contains(d.TaskId));
|
||||
if (holdCar != null)
|
||||
{
|
||||
Commons.DeleteTag(holdCar.tags, "taskIdsString");
|
||||
Diagnosis.Log(
|
||||
$"holdCarTagDelete-2:OnMissionFinished--TaskId:{d.TaskId},task:[{d.ToJson()}].taskIdsString:{d.TaskIdsString}",
|
||||
"holdCarTag",
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DispatchMissionState(d, MissionState.MissionStateEnum.Finished);
|
||||
}
|
||||
|
||||
public static async Task<int> OnMissionTerminated(ChainedDeliveryMission.Delivery delivery, string ISRelease)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var hc = new HttpClient();
|
||||
var task = await hc.GetAsync($"http://{delivery.UsingCar.address}:8008/car/startOrPause?ISRelease={ISRelease}");
|
||||
var resp = task.Content.ReadAsStringAsync().Result.JsonTo<BaseRespose>();
|
||||
var result = resp.Code == 200 ? "成功" : "失败";
|
||||
return 1;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Diagnosis.Log($"暂停恢复失败 => ex:{ExceptionFormatter.FormatEx(ex)}");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user