添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
using MainShell.Common;
|
||||
using MainShell.ProcessResult;
|
||||
using MW.WorkFlow;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MainShell.Process
|
||||
{
|
||||
public abstract class ActivityAbstractBase : IActivity
|
||||
{
|
||||
public string Name { get; protected set; }
|
||||
|
||||
protected ProcessResultManager ResultManager { get; private set; }
|
||||
|
||||
protected string CurrentWorkflowName { get; private set; } = "UnknownFlow";
|
||||
|
||||
protected string ParentActivityName { get; private set; } = string.Empty;
|
||||
|
||||
protected ActivityAbstractBase(string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
throw new ArgumentException("Activity name cannot be null or whitespace.", nameof(name));
|
||||
}
|
||||
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public async Task<ActivityResult> ExecuteAsync(WorkflowContext context, ActivityControl activityControl)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
if (activityControl == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(activityControl));
|
||||
}
|
||||
|
||||
var result = ActivityResult.Failure;
|
||||
var hasFaulted = false;
|
||||
|
||||
try
|
||||
{
|
||||
if (context.TryGetData<string>(WorkflowContextKeys.WorkflowName, out var flowName))
|
||||
{
|
||||
CurrentWorkflowName = flowName;
|
||||
}
|
||||
|
||||
if (context.TryGetData<string>(WorkflowContextKeys.ParentActivityName, out var parentName))
|
||||
{
|
||||
ParentActivityName = parentName;
|
||||
}
|
||||
else
|
||||
{
|
||||
ParentActivityName = string.Empty;
|
||||
}
|
||||
|
||||
if (context.TryGetData<ProcessResultManager>(WorkflowContextKeys.ProcessResultManager, out var manager))
|
||||
{
|
||||
ResultManager = manager;
|
||||
ResultManager.UpdateFlowState(CurrentWorkflowName, ParentActivityName, Name, ProcessExecutionStatus.Running, null);
|
||||
}
|
||||
|
||||
PrepareExecute(context, activityControl);
|
||||
result = await OnExecuteAsync(context, activityControl);
|
||||
return result;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
ResultManager?.UpdateFlowState(CurrentWorkflowName, ParentActivityName, Name, ProcessExecutionStatus.Canceled, null);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!HasWorkflowFailure(context))
|
||||
{
|
||||
SetWorkflowFailure(
|
||||
context,
|
||||
MessageKey.ProcessStepFailedWithReason,
|
||||
new object[] { Name, ex.Message ?? string.Empty });
|
||||
}
|
||||
|
||||
var errorMsg = ResolveWorkflowFailureMessage(context);
|
||||
ResultManager?.UpdateFlowState(CurrentWorkflowName, ParentActivityName, Name, ProcessExecutionStatus.Faulted, errorMsg);
|
||||
hasFaulted = true;
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
AfterExecute(context, activityControl);
|
||||
|
||||
if (ResultManager != null && !hasFaulted)
|
||||
{
|
||||
if (result == ActivityResult.Success)
|
||||
{
|
||||
ResultManager.UpdateFlowState(CurrentWorkflowName, ParentActivityName, Name, ProcessExecutionStatus.Completed, null);
|
||||
}
|
||||
else if (result == ActivityResult.Canceled)
|
||||
{
|
||||
ResultManager.UpdateFlowState(CurrentWorkflowName, ParentActivityName, Name, ProcessExecutionStatus.Canceled, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
ResultManager.UpdateFlowState(
|
||||
CurrentWorkflowName,
|
||||
ParentActivityName,
|
||||
Name,
|
||||
ProcessExecutionStatus.Faulted,
|
||||
ResolveWorkflowFailureMessage(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ActivityResult Fail(WorkflowContext context, MessageKey failureMessageKey, object[] failureMessageArguments)
|
||||
{
|
||||
SetWorkflowFailure(context, failureMessageKey, failureMessageArguments);
|
||||
return ActivityResult.Failure;
|
||||
}
|
||||
|
||||
protected void SetWorkflowFailure(WorkflowContext context, MessageKey failureMessageKey, object[] failureMessageArguments)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var normalized = NormalizeFailureMessageArguments(failureMessageArguments);
|
||||
context.SetData(WorkflowContextKeys.WorkflowFailureMessageKey, failureMessageKey);
|
||||
context.SetData(WorkflowContextKeys.WorkflowFailureMessageArguments, normalized);
|
||||
context.SetData(WorkflowContextKeys.WorkflowFailureMessage, LanguageResourceHelper.Format(failureMessageKey, normalized));
|
||||
}
|
||||
|
||||
protected void SetWorkflowFailure(WorkflowContext context, string failureMessage)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
context.SetData(WorkflowContextKeys.WorkflowFailureMessageKey, MessageKey.None);
|
||||
context.SetData<object[]>(WorkflowContextKeys.WorkflowFailureMessageArguments, null);
|
||||
context.SetData(WorkflowContextKeys.WorkflowFailureMessage, failureMessage ?? string.Empty);
|
||||
}
|
||||
|
||||
protected bool HasWorkflowFailure(WorkflowContext context)
|
||||
{
|
||||
if (context.TryGetData<MessageKey>(WorkflowContextKeys.WorkflowFailureMessageKey, out var failureMessageKey) &&
|
||||
failureMessageKey > MessageKey.None)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return context.TryGetData<string>(WorkflowContextKeys.WorkflowFailureMessage, out var failureMessage) &&
|
||||
!string.IsNullOrWhiteSpace(failureMessage);
|
||||
}
|
||||
|
||||
protected string ResolveWorkflowFailureMessage(WorkflowContext context)
|
||||
{
|
||||
if (context.TryGetData<MessageKey>(WorkflowContextKeys.WorkflowFailureMessageKey, out var failureMessageKey) &&
|
||||
failureMessageKey > MessageKey.None)
|
||||
{
|
||||
return LanguageResourceHelper.Format(failureMessageKey, GetWorkflowFailureMessageArguments(context));
|
||||
}
|
||||
|
||||
if (context.TryGetData<string>(WorkflowContextKeys.WorkflowFailureMessage, out var failureMessage) &&
|
||||
!string.IsNullOrWhiteSpace(failureMessage))
|
||||
{
|
||||
return failureMessage;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
protected object[] GetWorkflowFailureMessageArguments(WorkflowContext context)
|
||||
{
|
||||
if (context.TryGetData<object[]>(WorkflowContextKeys.WorkflowFailureMessageArguments, out var failureMessageArguments) &&
|
||||
failureMessageArguments != null)
|
||||
{
|
||||
return failureMessageArguments;
|
||||
}
|
||||
|
||||
return Array.Empty<object>();
|
||||
}
|
||||
|
||||
protected object[] NormalizeFailureMessageArguments(object[] failureMessageArguments)
|
||||
{
|
||||
return failureMessageArguments ?? Array.Empty<object>();
|
||||
}
|
||||
|
||||
protected abstract Task<ActivityResult> OnExecuteAsync(WorkflowContext context, ActivityControl activityControl);
|
||||
|
||||
protected virtual void PrepareExecute(WorkflowContext context, ActivityControl activityControl)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void AfterExecute(WorkflowContext context, ActivityControl activityControl)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
using MainShell.Common;
|
||||
using MW.WorkFlow;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MainShell.Process
|
||||
{
|
||||
public class CompositeActivity : IActivity
|
||||
{
|
||||
private readonly IEnumerable<IActivity> _subSteps;
|
||||
private readonly IEnumerable<IActivity> _finallySteps;
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public CompositeActivity(string name, IEnumerable<IActivity> subSteps)
|
||||
: this(name, subSteps, Array.Empty<IActivity>())
|
||||
{
|
||||
}
|
||||
|
||||
public CompositeActivity(string name, IEnumerable<IActivity> subSteps, IEnumerable<IActivity> finallySteps)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
throw new ArgumentException("Composite activity name cannot be null or whitespace.", nameof(name));
|
||||
}
|
||||
|
||||
Name = name;
|
||||
_subSteps = subSteps ?? throw new ArgumentNullException(nameof(subSteps));
|
||||
_finallySteps = finallySteps ?? Array.Empty<IActivity>();
|
||||
}
|
||||
|
||||
public async Task<ActivityResult> ExecuteAsync(WorkflowContext context, ActivityControl activityControl)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
if (activityControl == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(activityControl));
|
||||
}
|
||||
|
||||
activityControl.ThrowIfCancellationRequested();
|
||||
|
||||
context.TryGetData<string>(WorkflowContextKeys.ParentActivityName, out var previousParent);
|
||||
context.SetData(WorkflowContextKeys.ParentActivityName, Name);
|
||||
|
||||
ActivityResult result = ActivityResult.Success;
|
||||
Exception mainException = null;
|
||||
Exception cleanupException = null;
|
||||
|
||||
try
|
||||
{
|
||||
foreach (IActivity step in _subSteps)
|
||||
{
|
||||
activityControl.ThrowIfCancellationRequested();
|
||||
|
||||
result = await step.ExecuteAsync(context, activityControl);
|
||||
if (result != ActivityResult.Success)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
mainException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (IActivity cleanupStep in _finallySteps)
|
||||
{
|
||||
try
|
||||
{
|
||||
ActivityResult cleanupResult = await cleanupStep.ExecuteAsync(context, activityControl);
|
||||
if (mainException == null && result == ActivityResult.Success && cleanupResult != ActivityResult.Success)
|
||||
{
|
||||
result = cleanupResult;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (mainException == null && result == ActivityResult.Success)
|
||||
{
|
||||
cleanupException = ex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.SetData(WorkflowContextKeys.ParentActivityName, previousParent ?? string.Empty);
|
||||
}
|
||||
|
||||
if (mainException != null)
|
||||
{
|
||||
ExceptionDispatchInfo.Capture(mainException).Throw();
|
||||
}
|
||||
|
||||
if (cleanupException != null)
|
||||
{
|
||||
ExceptionDispatchInfo.Capture(cleanupException).Throw();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MainShell.Process
|
||||
{
|
||||
public class ProcessFlowName
|
||||
{
|
||||
public const string AutoProduction = "AutoProduction";
|
||||
/// <summary>
|
||||
/// 基板上料
|
||||
/// </summary>
|
||||
public const string SubstrateLoadFlow = "SubstrateLoadFlow";
|
||||
/// <summary>
|
||||
/// 基板定位
|
||||
/// </summary>
|
||||
public const string SubstratePositionFlow = "SubstratePositionFlow";
|
||||
/// <summary>
|
||||
/// 芯片拉直
|
||||
/// </summary>
|
||||
public const string ChipStraighteningFlow = "WaferAngleAdjustmentFlow";
|
||||
/// <summary>
|
||||
/// 芯片定位
|
||||
/// </summary>
|
||||
public const string DiePositionFlow = "DiePositionFlow";
|
||||
/// <summary>
|
||||
/// 芯片转移
|
||||
/// </summary>
|
||||
public const string DieTransferFlow = "DieTransferFlow";
|
||||
/// <summary>
|
||||
/// 基板测高
|
||||
/// </summary>
|
||||
public const string SubstrateHeightMeasureFlow = "SubstrateHeightMeasureFlow";
|
||||
/// <summary>
|
||||
/// 精度复检
|
||||
/// </summary>
|
||||
public const string DieRecheckFlow = "DieRecheckFlow";
|
||||
/// <summary>
|
||||
/// 基板下料
|
||||
/// </summary>
|
||||
public const string SubstrateUnloadFlow = "SubstrateUnloadFlow";
|
||||
|
||||
public const string PreparationSignalFlow = "PreparationSignalFlow";
|
||||
public const string ChipPreparationAutoLoadStartFlow = "ChipPreparationAutoLoadStartFlow";
|
||||
public const string ChipPreparationSyncFlow = "ChipPreparationSyncFlow";
|
||||
public const string PreTransferValidationFlow = "PreTransferValidationFlow";
|
||||
public const string ChipUnloadFlow = "ChipUnloadFlow";
|
||||
|
||||
public const string ChipPreparationOnDemandFlow = "ChipPreparationOnDemand";
|
||||
public const string ChipLoadExecuteActivity = "ChipLoadExecute";
|
||||
public const string ChipUnloadExecuteActivity = "ChipUnloadExecute";
|
||||
}
|
||||
|
||||
public enum DieTransferRoute
|
||||
{
|
||||
None = 0,
|
||||
Recheck = 1
|
||||
}
|
||||
|
||||
public enum AutoProductionRoute
|
||||
{
|
||||
None = 0,
|
||||
ContinueCurrentSubstrate = 1,
|
||||
Recheck = 2,
|
||||
ChipExhausted = 3,
|
||||
SubstrateComplete = 4,
|
||||
BothExhausted = 5
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
using MainShell.Common;
|
||||
using MainShell.ProcessResult;
|
||||
using MW.WorkFlow;
|
||||
using Stylet;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MainShell.Process
|
||||
{
|
||||
public class WorkflowRunCompletedEventArgs : EventArgs
|
||||
{
|
||||
public WorkflowState FinalState { get; }
|
||||
public string Error { get; }
|
||||
public string FailureMessage { get; }
|
||||
public MessageKey FailureMessageKey { get; }
|
||||
public object[] FailureMessageArguments { get; }
|
||||
|
||||
public WorkflowRunCompletedEventArgs(WorkflowState finalState, string error, string failureMessage, MessageKey failureMessageKey, object[] failureMessageArguments)
|
||||
{
|
||||
FinalState = finalState;
|
||||
Error = error;
|
||||
FailureMessage = failureMessage;
|
||||
FailureMessageKey = failureMessageKey;
|
||||
FailureMessageArguments = failureMessageArguments ?? Array.Empty<object>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 封装工作流的启动、停止和状态管理,用于手动流程的复用。
|
||||
/// </summary>
|
||||
public class
|
||||
WorkflowRunner : PropertyChangedBase, IDisposable
|
||||
{
|
||||
private WorkflowEngine _workflowEngine;
|
||||
private bool _isRunning;
|
||||
|
||||
/// <summary>
|
||||
/// 流程是否正在运行
|
||||
/// </summary>
|
||||
public bool IsRunning
|
||||
{
|
||||
get { return _isRunning; }
|
||||
private set { SetAndNotify(ref _isRunning, value); }
|
||||
}
|
||||
|
||||
public event EventHandler<WorkflowRunCompletedEventArgs> RunCompleted;
|
||||
|
||||
/// <summary>
|
||||
/// 运行单个 Activity(自动包装为单步工作流)
|
||||
/// </summary>
|
||||
public Task RunActivityAsync(IActivity activity, WorkflowContext context)
|
||||
{
|
||||
if (activity == null) throw new ArgumentNullException(nameof(activity));
|
||||
|
||||
// 自动构建单步工作流定义
|
||||
var stepId = "SingleStep_" + Guid.NewGuid().ToString("N");
|
||||
var step = new WorkflowStep(stepId, activity);
|
||||
var definition = new WorkflowDefinition(stepId);
|
||||
definition.AddStep(step);
|
||||
|
||||
return RunAsync(definition, context);
|
||||
}
|
||||
|
||||
public Task<WorkflowRunCompletedEventArgs> RunActivityWithResultAsync(IActivity activity, WorkflowContext context)
|
||||
{
|
||||
if (activity == null) throw new ArgumentNullException(nameof(activity));
|
||||
|
||||
var stepId = "SingleStep_" + Guid.NewGuid().ToString("N");
|
||||
var step = new WorkflowStep(stepId, activity);
|
||||
var definition = new WorkflowDefinition(stepId);
|
||||
definition.AddStep(step);
|
||||
|
||||
return RunWithResultAsync(definition, context, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行完整的工作流定义
|
||||
/// </summary>
|
||||
public async Task RunAsync(WorkflowDefinition definition, WorkflowContext context)
|
||||
{
|
||||
await RunWithResultAsync(definition, context, null);
|
||||
}
|
||||
|
||||
public Task<WorkflowRunCompletedEventArgs> RunWithResultAsync(WorkflowDefinition definition, WorkflowContext context)
|
||||
{
|
||||
return RunWithResultAsync(definition, context, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行完整的工作流定义,并支持从指定步骤启动。
|
||||
/// </summary>
|
||||
/// <param name="definition">工作流定义</param>
|
||||
/// <param name="context">工作流上下文</param>
|
||||
/// <param name="startStepId">可选:指定起始步骤ID;为 null/空时从初始步骤启动</param>
|
||||
public async Task RunAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId)
|
||||
{
|
||||
await RunWithResultAsync(definition, context, startStepId);
|
||||
}
|
||||
|
||||
public async Task<WorkflowRunCompletedEventArgs> RunWithResultAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId)
|
||||
{
|
||||
if (definition == null) throw new ArgumentNullException(nameof(definition));
|
||||
if (context == null) throw new ArgumentNullException(nameof(context));
|
||||
|
||||
if (IsRunning)
|
||||
{
|
||||
throw new InvalidOperationException("当前已有流程正在运行,无法重复启动。");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(startStepId) && !definition.GetAllStepIds().Contains(startStepId))
|
||||
{
|
||||
throw new ArgumentException($"指定的起始步骤ID '{startStepId}' 不存在于工作流定义中。", nameof(startStepId));
|
||||
}
|
||||
|
||||
var resolvedStartStepId = ResolveStartStepId(definition, context, startStepId);
|
||||
|
||||
var errorStr = string.Empty;
|
||||
WorkflowState finalState = WorkflowState.Created;
|
||||
MessageKey failureMessageKey = MessageKey.None;
|
||||
object[] failureMessageArguments = Array.Empty<object>();
|
||||
string failureMessage = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
IsRunning = true;
|
||||
_workflowEngine = new WorkflowEngine(definition, context);
|
||||
_workflowEngine.Start(resolvedStartStepId);
|
||||
|
||||
// 异步轮询等待工作流结束
|
||||
// 这样可以不阻塞 UI 线程,同时保持 IsRunning 状态正确
|
||||
while (_workflowEngine != null && _workflowEngine.IsWorkflowRunning)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
// 捕获最终状态(Dispose 之前)
|
||||
if (_workflowEngine != null)
|
||||
{
|
||||
finalState = _workflowEngine.CurrentState;
|
||||
}
|
||||
|
||||
failureMessageKey = ResolveFailureMessageKey(context);
|
||||
failureMessageArguments = ResolveFailureMessageArguments(context);
|
||||
failureMessage = ResolveFailureMessage(context, failureMessageKey, failureMessageArguments);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 无论正常结束、异常还是被取消,都确保清理资源和复位状态
|
||||
errorStr = _workflowEngine?.LastException?.ToString();
|
||||
IsRunning = false;
|
||||
_workflowEngine?.Dispose();
|
||||
_workflowEngine = null;
|
||||
}
|
||||
|
||||
var completedArgs = new WorkflowRunCompletedEventArgs(finalState, errorStr, failureMessage, failureMessageKey, failureMessageArguments);
|
||||
RunCompleted?.Invoke(this, completedArgs);
|
||||
|
||||
return completedArgs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从指定步骤启动工作流(语义化封装)。
|
||||
/// </summary>
|
||||
public Task RunFromStepAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(startStepId))
|
||||
throw new ArgumentNullException(nameof(startStepId));
|
||||
|
||||
return RunAsync(definition, context, startStepId);
|
||||
}
|
||||
|
||||
public Task<WorkflowRunCompletedEventArgs> RunFromStepWithResultAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(startStepId))
|
||||
throw new ArgumentNullException(nameof(startStepId));
|
||||
|
||||
return RunWithResultAsync(definition, context, startStepId);
|
||||
}
|
||||
|
||||
private string ResolveStartStepId(WorkflowDefinition definition, WorkflowContext context, string startStepId)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(startStepId))
|
||||
{
|
||||
return startStepId;
|
||||
}
|
||||
|
||||
if (!context.TryGetData<string>(WorkflowContextKeys.WorkflowName, out var workflowName) ||
|
||||
string.IsNullOrWhiteSpace(workflowName) ||
|
||||
!context.TryGetData<ProcessResultManager>(WorkflowContextKeys.ProcessResultManager, out var resultManager) ||
|
||||
resultManager == null ||
|
||||
!resultManager.TryGetResumeStepId(workflowName, out var resumeStepId) ||
|
||||
!definition.ContainsStep(resumeStepId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return resumeStepId;
|
||||
}
|
||||
|
||||
private MessageKey ResolveFailureMessageKey(WorkflowContext context)
|
||||
{
|
||||
MessageKey failureMessageKey;
|
||||
if (context.TryGetData<MessageKey>(WorkflowContextKeys.WorkflowFailureMessageKey, out failureMessageKey))
|
||||
{
|
||||
return failureMessageKey;
|
||||
}
|
||||
|
||||
return MessageKey.None;
|
||||
}
|
||||
|
||||
private object[] ResolveFailureMessageArguments(WorkflowContext context)
|
||||
{
|
||||
object[] failureMessageArguments;
|
||||
if (context.TryGetData<object[]>(WorkflowContextKeys.WorkflowFailureMessageArguments, out failureMessageArguments) &&
|
||||
failureMessageArguments != null)
|
||||
{
|
||||
return failureMessageArguments;
|
||||
}
|
||||
|
||||
return Array.Empty<object>();
|
||||
}
|
||||
|
||||
private string ResolveFailureMessage(WorkflowContext context, MessageKey failureMessageKey, object[] failureMessageArguments)
|
||||
{
|
||||
if (failureMessageKey != MessageKey.None)
|
||||
{
|
||||
return LanguageResourceHelper.Format(failureMessageKey, failureMessageArguments);
|
||||
}
|
||||
|
||||
string failureMessage;
|
||||
if (context.TryGetData<string>(WorkflowContextKeys.WorkflowFailureMessage, out failureMessage) &&
|
||||
!string.IsNullOrWhiteSpace(failureMessage))
|
||||
{
|
||||
return failureMessage;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 请求停止当前流程
|
||||
/// </summary>
|
||||
public async Task StopAsync()
|
||||
{
|
||||
if (_workflowEngine != null && _workflowEngine.IsWorkflowRunning)
|
||||
{
|
||||
await _workflowEngine.StopAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public void Pause()
|
||||
{
|
||||
if (_workflowEngine != null && _workflowEngine.IsWorkflowRunning)
|
||||
{
|
||||
_workflowEngine.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
public void Resume()
|
||||
{
|
||||
if (_workflowEngine != null && _workflowEngine.IsWorkflowRunning)
|
||||
{
|
||||
_workflowEngine.Resume();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_workflowEngine?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using MainShell.Log;
|
||||
using MainShell.ProcessResult;
|
||||
using System;
|
||||
using MW.WorkFlow;
|
||||
|
||||
namespace MainShell.Process
|
||||
{
|
||||
public class WorkflowRuntimeTracker : IWorkflowRuntimeTracker
|
||||
{
|
||||
private readonly ProcessResultManager _processResultManager;
|
||||
|
||||
public WorkflowRuntimeTracker(ProcessResultManager processResultManager)
|
||||
{
|
||||
_processResultManager = processResultManager ?? throw new ArgumentNullException(nameof(processResultManager));
|
||||
}
|
||||
|
||||
public void UpdateExecutionPointer(WorkflowExecutionPointer executionPointer)
|
||||
{
|
||||
if (executionPointer != null)
|
||||
{
|
||||
string.Format(
|
||||
"Workflow pointer updated. WorkflowName={0}, FlowName={1}, ActivityName={2}, CurrentStepId={3}, NextStepId={4}, UpdatedAt={5:yyyy-MM-dd HH:mm:ss.fff}.",
|
||||
NormalizeValue(executionPointer.WorkflowName),
|
||||
NormalizeValue(executionPointer.FlowName),
|
||||
NormalizeValue(executionPointer.ActivityName),
|
||||
NormalizeValue(executionPointer.CurrentStepId),
|
||||
NormalizeValue(executionPointer.NextStepId),
|
||||
executionPointer.UpdatedAt).LogProcessDebug();
|
||||
}
|
||||
|
||||
_processResultManager.UpdateExecutionPointer(executionPointer);
|
||||
}
|
||||
|
||||
public void ReportWorkflowFault(WorkflowFaultInfo faultInfo)
|
||||
{
|
||||
if (faultInfo != null)
|
||||
{
|
||||
string.Format(
|
||||
"Workflow fault reported. WorkflowName={0}, FlowName={1}, ActivityName={2}, CurrentStepId={3}, OccurredAt={4:yyyy-MM-dd HH:mm:ss.fff}, ErrorMessage={5}.",
|
||||
NormalizeValue(faultInfo.WorkflowName),
|
||||
NormalizeValue(faultInfo.FlowName),
|
||||
NormalizeValue(faultInfo.ActivityName),
|
||||
NormalizeValue(faultInfo.CurrentStepId),
|
||||
faultInfo.OccurredAt,
|
||||
NormalizeValue(faultInfo.ErrorMessage)).LogProcessError();
|
||||
}
|
||||
|
||||
_processResultManager.ReportWorkflowFault(faultInfo);
|
||||
}
|
||||
|
||||
private static string NormalizeValue(string value)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(value) ? "N/A" : value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using MW.WorkFlow;
|
||||
|
||||
namespace MainShell.Process
|
||||
{
|
||||
public class WorkflowStartRequest
|
||||
{
|
||||
public WorkflowDefinition Definition { get; }
|
||||
public WorkflowContext Context { get; }
|
||||
public string StartStepId { get; }
|
||||
|
||||
public WorkflowStartRequest(WorkflowDefinition definition, WorkflowContext context, string startStepId)
|
||||
{
|
||||
Definition = definition ?? throw new ArgumentNullException(nameof(definition));
|
||||
Context = context ?? throw new ArgumentNullException(nameof(context));
|
||||
StartStepId = startStepId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MainShell.Process
|
||||
{
|
||||
public static class WorkflowStepIdResolver
|
||||
{
|
||||
private static readonly IReadOnlyDictionary<string, string> AutoProductionEntryStepIdMap =
|
||||
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ ProcessFlowName.SubstrateLoadFlow, WorkflowStepIds.AutoProduction.SubstrateLoadEntry },
|
||||
{ ProcessFlowName.SubstratePositionFlow, WorkflowStepIds.AutoProduction.SubstratePositionEntry },
|
||||
{ ProcessFlowName.SubstrateHeightMeasureFlow, WorkflowStepIds.AutoProduction.SubstrateHeightMeasureEntry },
|
||||
{ ProcessFlowName.PreparationSignalFlow, WorkflowStepIds.AutoProduction.PreparationSignalEntry },
|
||||
{ ProcessFlowName.ChipPreparationSyncFlow, WorkflowStepIds.AutoProduction.ChipPreparationSyncEntry },
|
||||
{ ProcessFlowName.PreTransferValidationFlow, WorkflowStepIds.AutoProduction.PreTransferValidationEntry },
|
||||
{ ProcessFlowName.ChipStraighteningFlow, WorkflowStepIds.AutoProduction.ChipStraighteningEntry },
|
||||
{ ProcessFlowName.DiePositionFlow, WorkflowStepIds.AutoProduction.DiePositionEntry },
|
||||
{ ProcessFlowName.DieTransferFlow, WorkflowStepIds.AutoProduction.DieTransferEntry },
|
||||
{ ProcessFlowName.DieRecheckFlow, WorkflowStepIds.AutoProduction.DieRecheckEntry },
|
||||
{ ProcessFlowName.ChipUnloadFlow, WorkflowStepIds.AutoProduction.ChipUnloadEntry },
|
||||
{ ProcessFlowName.SubstrateUnloadFlow, WorkflowStepIds.AutoProduction.SubstrateUnloadEntry }
|
||||
};
|
||||
|
||||
public static string GetAutoProductionEntryStepId(string flowName)
|
||||
{
|
||||
if (TryGetAutoProductionEntryStepId(flowName, out var stepId))
|
||||
{
|
||||
return stepId;
|
||||
}
|
||||
|
||||
return WorkflowStepIds.AutoProduction.SubstrateLoadEntry;
|
||||
}
|
||||
|
||||
public static bool TryGetAutoProductionEntryStepId(string flowName, out string stepId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(flowName))
|
||||
{
|
||||
stepId = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return AutoProductionEntryStepIdMap.TryGetValue(flowName, out stepId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
|
||||
namespace MainShell.Process
|
||||
{
|
||||
public static class WorkflowStepIds
|
||||
{
|
||||
public static class AutoProduction
|
||||
{
|
||||
public const string SubstrateLoadEntry = "Auto.SubstrateLoad.Entry";
|
||||
public const string SubstratePositionEntry = "Auto.SubstratePosition.Entry";
|
||||
public const string SubstrateHeightMeasureEntry = "Auto.SubstrateHeightMeasure.Entry";
|
||||
public const string PreparationSignalEntry = "Auto.PreparationSignal.Entry";
|
||||
public const string ChipPreparationSyncEntry = "Auto.ChipPreparationSync.Entry";
|
||||
public const string PreTransferValidationEntry = "Auto.PreTransferValidation.Entry";
|
||||
public const string ChipStraighteningEntry = "Auto.ChipStraightening.Entry";
|
||||
public const string DiePositionEntry = "Auto.DiePosition.Entry";
|
||||
public const string DieTransferEntry = "Auto.DieTransfer.Entry";
|
||||
public const string DieRecheckEntry = "Auto.DieRecheck.Entry";
|
||||
public const string ChipUnloadEntry = "Auto.ChipUnload.Entry";
|
||||
public const string SubstrateUnloadEntry = "Auto.SubstrateUnload.Entry";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user