/// <summary> /// Execute scenario in other thread /// </summary> /// <param name="param"></param> /// <param name="cancelToken"></param> public virtual void ExecuteAsyncParallel(ScenarioActionSource source, string param, ExecutionContext parentContext) { CheckRights(source, parentContext); TaskUtils.StartLongRunning(() => { CheckValue(param, parentContext); var output = new OutputChangedDelegates(); ExecutionContext context; var oldVal = GetPreviousValue(); if (parentContext != null) { var cancellationTokenSource = new SafeCancellationToken(); parentContext.CancellationTokenSource.RegisterCallback(cancellationTokenSource.Cancel); context = new ExecutionContext(this, param, oldVal, output, parentContext, cancellationTokenSource); } else { context = new ExecutionContext(this, param, oldVal, output, new SafeCancellationToken()); } CheckContext(context); HandleExecution(() => ExecuteInternal(context)); }, HandleSet); }
public void SetValue(Lazurite.ActionsDomain.ExecutionContext context, string value) { float val = 0; float.TryParse(value, out val); Thread.Sleep(TimeSpan.FromMinutes(val)); }
protected void CheckValue(string param, ExecutionContext parentContext) { try { if (!ValueType.Interprete(param).Success) { throw new ScenarioExecutionException(ScenarioExecutionError.InvalidValue, param); } } catch (Exception e) { parentContext?.CancelAll(); //stop execution throw e; } }
protected void CheckRights(ScenarioActionSource source, ExecutionContext context) { try { if (!IsAccessAvailable(source)) { throw new ScenarioExecutionException(ScenarioExecutionError.AccessDenied); } } catch (Exception e) { context?.CancelAll(); //stop execution throw e; } }
/// <summary> /// Current value of scenario execution /// </summary> public virtual string CalculateCurrentValue(ScenarioActionSource source, ExecutionContext parentContext) { CheckRights(source, parentContext); try { if (parentContext != null) { //empty context, just for stack overflow and circular reference check var context = new ExecutionContext(this, string.Empty, string.Empty, null, parentContext, parentContext.CancellationTokenSource); CheckContext(context); } return(CalculateCurrentValueInternal()); } catch (Exception e) { HandleGet(e); throw e; } }
protected void CheckContext(ExecutionContext context) { try { if (context.Find((x) => x.AlgorithmContext is ScenarioBase scenarioBase && scenarioBase.Id == Id) != null) //if true - then it is circular reference { throw new ScenarioExecutionException(ScenarioExecutionError.CircularReference); } if (context.ExecutionNesting >= MaxStackValue) { throw new ScenarioExecutionException(ScenarioExecutionError.StackOverflow); } } catch (Exception e) { context?.CancelAll(); //stop execution throw e; } }
protected ExecutionContext PrepareExecutionContext(string param, ExecutionContext parentContext) { var output = new OutputChangedDelegates(); output.Add(val => SetCurrentValue(val, SystemActionSource)); var tokenSource = PrepareCancellationTokenSource(); ExecutionContext context; var prevValue = GetCurrentValue(); if (parentContext == null) { context = new ExecutionContext(this, param, prevValue, output, tokenSource); } else { context = new ExecutionContext(this, param, prevValue, output, parentContext, tokenSource); parentContext.CancellationTokenSource.RegisterCallback(tokenSource.Cancel); CheckContext(context); } return(context); }
public ExecutionContext(IAlgorithmContext algorithmContext, string input, string previousValue, OutputChangedDelegates output, ExecutionContext parentContext, CancellationTokenSource cancellationTokenSource) { OutputChanged = output; AlgorithmContext = algorithmContext; Input = input; PreviousValue = previousValue; CancellationTokenSource = cancellationTokenSource; ParentContext = parentContext; ExecutionNesting = ParentContext.ExecutionNesting + 1; }
public string GetValue(Lazurite.ActionsDomain.ExecutionContext context) { return("0"); }
/// <summary> /// Execute scenario in current thread /// </summary> /// <param name="param"></param> /// <param name="cancelToken"></param> protected abstract void ExecuteInternal(ExecutionContext context);
/// <summary> /// Execute in current thread /// </summary> /// <param name="param"></param> /// <param name="cancelToken"></param> public virtual void Execute(ScenarioActionSource source, string param, out string executionId, ExecutionContext parentContext = null) { executionId = PrepareExecutionId(); CheckRights(source, parentContext); try { CheckValue(param, parentContext); TryCancelAll(); var context = PrepareExecutionContext(param, parentContext); HandleExecution(() => { SetPreviousValue(GetCurrentValue()); SetCurrentValue(param, source); ExecuteInternal(context); }); } catch (Exception e) { HandleSet(e); } }
/// <summary> /// Execute scenario in main execution context /// </summary> /// <param name="param"></param> public virtual void ExecuteAsync(ScenarioActionSource source, string param, out string executionId, ExecutionContext parentContext = null) { executionId = PrepareExecutionId(); CheckRights(source, parentContext); TaskUtils.StartLongRunning(() => { CheckValue(param, parentContext); TryCancelAll(); var context = PrepareExecutionContext(param, parentContext); HandleExecution(() => { SetPreviousValue(GetCurrentValue()); SetCurrentValue(param, source); ExecuteInternal(context); }); }, HandleSet); }
protected override void RunInternal() { if (GetScenario() == null) { return; } //удаляем старую подписку, если имеется if (_lastSubscribe != null) { GetScenario().RemoveOnStateChanged(_lastSubscribe); } //выполнение по подписке на изменение значения var executeBySubscription = true; //если сценарий это одиночное действие и нельзя подписаться на изменение целевого действия //то не выполняем по подписке, а выполняем просто через цикл if (GetScenario() is SingleActionScenario singleActionScen && !singleActionScen.ActionHolder.Action.IsSupportsEvent) { executeBySubscription = false; } var contextCancellationToken = new SafeCancellationToken(); CancellationToken.RegisterCallback(contextCancellationToken.Cancel); if (executeBySubscription) { _lastSubscribe = (sender, args) => { if (CancellationToken.IsCancellationRequested) { //crutch; scenario can be changed before initializing, then we need to remove //current subscribe from previous scenario. CancellationToken.IsCancellationRequested //can be setted in true only when trigger stopped; args.Value.Scenario.RemoveOnStateChanged(_lastSubscribe); } else { if (!args.Value.OnlyIntent) { var action = TargetAction; var outputChanged = new OutputChangedDelegates(); outputChanged.Add((value) => GetScenario().SetCurrentValue(value, ExecuteActionSource)); contextCancellationToken.Cancel(); contextCancellationToken = new SafeCancellationToken(); var executionContext = new ExecutionContext(this, args.Value.Value, args.Value.PreviousValue, outputChanged, contextCancellationToken); TaskUtils.StartLongRunning( () => action.SetValue(executionContext, string.Empty), (exception) => Log.ErrorFormat(exception, "Ошибка выполнения триггера [{0}][{1}]", Name, Id)); } } }; GetScenario().SetOnStateChanged(_lastSubscribe); } else { var lastVal = string.Empty; var timerCancellationToken = SystemUtils.StartTimer( (token) => { try { var curVal = GetScenario().CalculateCurrentValue(ViewActionSource, null); if (!lastVal.Equals(curVal)) { var prevVal = GetScenario().GetPreviousValue(); lastVal = curVal; contextCancellationToken.Cancel(); contextCancellationToken = new SafeCancellationToken(); var executionContext = new ExecutionContext(this, curVal, prevVal, new OutputChangedDelegates(), contextCancellationToken); try { TargetAction.SetValue(executionContext, string.Empty); } catch (Exception exception) { Log.ErrorFormat(exception, "Ошибка выполнения триггера [{0}][{1}]", Name, Id); } } } catch (Exception e) { Log.ErrorFormat(e, "Ошибка выполнения триггера [{0}][{1}]", Name, Id); } }, () => TriggerChangesListenInterval, true, ticksSuperposition: true /*наложение тиков*/); CancellationToken.RegisterCallback(timerCancellationToken.Cancel); } }
public override string CalculateCurrentValue(ScenarioActionSource source, ExecutionContext parentContext) { CheckRights(source, parentContext); return(CalculateCurrentValueInternal()); }
/// <summary> /// Current value of scenario execution /// </summary> public virtual void CalculateCurrentValueAsync(ScenarioActionSource source, Action <string> callback, ExecutionContext parentContext) { CheckRights(source, parentContext); TaskUtils.Start( () => { var result = CalculateCurrentValue(source, parentContext); callback(result); }, HandleGet); }
protected override void ExecuteInternal(ExecutionContext context) { TargetAction.SetValue(context, string.Empty); }
public override void CalculateCurrentValueAsync(ScenarioActionSource source, Action <string> callback, ExecutionContext parentContext) { CheckRights(source, parentContext); callback(CalculateCurrentValueInternal()); }