public static void Synchronize <K, N, O>(this ExecutingProcess ep, Dictionary <K, N> newDictionary, Dictionary <K, O> oldDictionary, Action <K, N> createNew, Action <K, O> removeOld, Action <K, N, O> merge) where K : notnull { HashSet <K> keys = new HashSet <K>(); keys.UnionWith(oldDictionary.Keys); keys.UnionWith(newDictionary.Keys); foreach (var key in keys) { var oldExists = oldDictionary.TryGetValue(key, out var oldVal); var newExists = newDictionary.TryGetValue(key, out var newVal); if (!oldExists) { createNew?.Invoke(key, newVal); } else if (!newExists) { removeOld?.Invoke(key, oldVal); } else { merge?.Invoke(key, newVal, oldVal); } } }
public static void ForEachLine <T>(this ExecutingProcess executingProcess, IQueryable <T> remainingLines, Action <T> action, int groupsOf = 100) where T : Entity, IProcessLineDataEntity, new() { var remainingNotExceptionsLines = remainingLines.Where(li => li.Exception(executingProcess.CurrentProcess) == null); var totalCount = remainingNotExceptionsLines.Count(); int j = 0; while (true) { List <T> lines = remainingNotExceptionsLines.Take(groupsOf).ToList(); if (lines.IsEmpty()) { return; } for (int i = 0; i < lines.Count; i++) { executingProcess.CancellationToken.ThrowIfCancellationRequested(); T pl = lines[i]; using (HeavyProfiler.Log("ProcessLine", () => pl.ToString())) { try { Transaction.ForceNew().EndUsing(tr => { action(pl); tr.Commit(); }); } catch (Exception e) { if (Transaction.InTestTransaction) { throw; } var exLog = e.LogException(); Transaction.ForceNew().EndUsing(tr => { new ProcessExceptionLineEntity { Exception = exLog.ToLite(), Line = pl.ToLite(), Process = executingProcess.CurrentProcess.ToLite() }.Save(); tr.Commit(); }); } executingProcess.ProgressChanged(j++, totalCount); } } } }
public static void ExecuteTest(this ProcessEntity p, bool writeToConsole = false) { p.QueuedDate = TimeZoneManager.Now; var ep = new ExecutingProcess(GetProcessAlgorithm(p.Algorithm), p) { WriteToConsole = writeToConsole }; ep.TakeForThisMachine(); ep.Execute(); }
public virtual void Execute(ExecutingProcess executingProcess) { PackageEntity package = (PackageEntity)executingProcess.Data; var args = package.OperationArgs; executingProcess.ForEachLine(package.Lines().Where(a => a.FinishTime == null), line => { ((T)(object)line.Target).Execute(Symbol, args); line.FinishTime = TimeZoneManager.Now; line.Save(); }); }
public virtual void Execute(ExecutingProcess executingProcess) { PackageEntity package = (PackageEntity)executingProcess.Data !; var args = package.GetOperationArgs(); using (OperationLogic.AllowSave <T>()) executingProcess.ForEachLine(package.Lines().Where(a => a.FinishTime == null), line => { ((T)(object)line.Target).Save(); line.FinishTime = TimeZoneManager.Now; line.Save(); }); }
public static void ForEachNonTransactional <T>(this ExecutingProcess executingProcess, List <T> collection, Func <T, string> elementInfo, Action <T> action, string?status = null) { if (executingProcess == null) { collection.ProgressForeach(elementInfo, action, transactional: false); } else { var totalCount = collection.Count; int j = 0; foreach (var item in collection) { executingProcess.CancellationToken.ThrowIfCancellationRequested(); using (HeavyProfiler.Log("ProgressForeach", () => elementInfo(item))) { try { action(item); } catch (Exception e) { if (Transaction.InTestTransaction) { throw; } var exLog = e.LogException(); Transaction.ForceNew().EndUsing(tr => { new ProcessExceptionLineEntity { Exception = exLog.ToLite(), ElementInfo = elementInfo(item), Process = executingProcess.CurrentProcess.ToLite() }.Save(); tr.Commit(); }); } executingProcess.ProgressChanged(j++, totalCount, status); } } } }
public static void ForEach <T>(this ExecutingProcess executingProcess, List <T> collection, Func <T, string> elementInfo, Action <T> action, string?status = null) { if (executingProcess == null) { collection.ProgressForeach(elementInfo, action); } else { executingProcess.ForEachNonTransactional(collection, elementInfo, item => { using (Transaction tr = Transaction.ForceNew()) { action(item); tr.Commit(); } }, status); } }
public virtual void Execute(ExecutingProcess executingProcess) { PackageEntity package = (PackageEntity)executingProcess.Data; var args = package.OperationArgs; executingProcess.ForEachLine(package.Lines().Where(a => a.FinishTime == null), line => { var result = ((F)(object)line.Target).ConstructFrom(Symbol, args); if (result.IsNew) { result.Save(); } line.Result = ((Entity)(IEntity)result).ToLite(); line.FinishTime = TimeZoneManager.Now; line.Save(); }); }
public static void SynchronizeProgressForeach <K, N, O>(this ExecutingProcess ep, Dictionary <K, N> newDictionary, Dictionary <K, O> oldDictionary, Action <K, N> createNew, Action <K, O> removeOld, Action <K, N, O> merge, string?status = null) where O : class where N : class where K : notnull { if (ep == null) { ep.WriteLineColor(ConsoleColor.Green, status); Synchronizer.SynchronizeProgressForeach(newDictionary, oldDictionary, createNew, removeOld, merge); } else { HashSet <K> keys = new HashSet <K>(); keys.UnionWith(oldDictionary.Keys); keys.UnionWith(newDictionary.Keys); ep.ForEach(keys.ToList(), key => key.ToString() !, key => { var oldVal = oldDictionary.TryGetC(key); var newVal = newDictionary.TryGetC(key); if (oldVal == null) { createNew?.Invoke(key, newVal !); } else if (newVal == null) { removeOld?.Invoke(key, oldVal); } else { merge?.Invoke(key, newVal, oldVal); } }, status); } }
public static void SynchronizeProgressForeachNonTransactional <K, N, O>(this ExecutingProcess ep, Dictionary <K, N> newDictionary, Dictionary <K, O> oldDictionary, Action <K, N> createNew, Action <K, O> removeOld, Action <K, N, O> merge) where O : class where N : class where K : notnull { if (ep == null) { Synchronizer.SynchronizeProgressForeach(newDictionary, oldDictionary, createNew, removeOld, merge, transactional: false); } else { HashSet <K> keys = new HashSet <K>(); keys.UnionWith(oldDictionary.Keys); keys.UnionWith(newDictionary.Keys); ep.ForEachNonTransactional(keys.ToList(), key => key.ToString(), key => { var oldVal = oldDictionary.TryGetC(key); var newVal = newDictionary.TryGetC(key); if (oldVal == null) { createNew?.Invoke(key, newVal !); } else if (newVal == null) { removeOld?.Invoke(key, oldVal); } else { merge?.Invoke(key, newVal, oldVal); } }); } }
public void Execute(ExecutingProcess executingProcess) { PackageOperationEntity package = (PackageOperationEntity)executingProcess.Data; OperationSymbol operationSymbol = package.Operation; var args = package.OperationArgs; executingProcess.ForEachLine(package.Lines().Where(a => a.FinishTime == null), line => { OperationType operationType = OperationLogic.OperationType(line.Target.GetType(), operationSymbol); switch (operationType) { case OperationType.Execute: OperationLogic.ServiceExecute(line.Target, operationSymbol, args); break; case OperationType.Delete: OperationLogic.ServiceDelete(line.Target, operationSymbol, args); break; case OperationType.ConstructorFrom: { var result = OperationLogic.ServiceConstructFrom(line.Target, operationSymbol, args); line.Result = result.ToLite(); } break; default: throw new InvalidOperationException("Unexpected operation type {0}".FormatWith(operationType)); } line.FinishTime = TimeZoneManager.Now; line.Save(); }); }
public static void StartRunningProcesses() { if (running) { throw new InvalidOperationException("ProcessLogic is running"); } using (ExecutionContext.SuppressFlow()) Task.Factory.StartNew(() => { var database = Schema.Current.Table(typeof(ProcessEntity)).Name.Schema?.Database; SystemEventLogLogic.Log("Start ProcessRunner"); ExceptionEntity exception = null; using (AuthLogic.Disable()) { try { running = true; (from p in Database.Query <ProcessEntity>() where p.IsMine() && (p.State == ProcessState.Executing || p.State == ProcessState.Suspending || p.State == ProcessState.Suspended) || p.IsShared() && p.State == ProcessState.Suspended select p).SetAsQueued(); CancelNewProcesses = new CancellationTokenSource(); autoResetEvent.Set(); timerNextExecution = new Timer(ob => WakeUp("TimerNextExecution", null), // main timer null, Timeout.Infinite, Timeout.Infinite); if (!CacheLogic.WithSqlDependency) { timerPeriodic = new Timer(ob => WakeUp("TimerPeriodic", null), null, PoolingPeriodMilliseconds, PoolingPeriodMilliseconds); } while (autoResetEvent.WaitOne()) { if (CancelNewProcesses.IsCancellationRequested) { return; } using (HeavyProfiler.Log("PWL", () => "Process Runner")) { (from p in Database.Query <ProcessEntity>() where p.State == ProcessState.Planned && p.PlannedDate <= TimeZoneManager.Now select p).SetAsQueued(); var list = Database.Query <ProcessEntity>() .Where(p => p.IsMine() || p.IsShared()) .Where(p => p.State == ProcessState.Planned) .Select(p => p.PlannedDate) .ToListWakeup("Planned dependency"); SetNextPannedExecution(list.Min()); lock (executing) { int remaining = MaxDegreeOfParallelism - executing.Count; if (remaining > 0) { retry: var queued = Database.Query <ProcessEntity>() .Where(p => p.State == ProcessState.Queued) .Where(p => p.IsMine() || p.IsShared()) .Select(a => new { Process = a.ToLite(), a.QueuedDate, a.MachineName }) .ToListWakeup("Planned dependency"); var afordable = queued .OrderByDescending(p => p.MachineName == Environment.MachineName) .OrderBy(a => a.QueuedDate) .Take(remaining).ToList(); var taken = afordable.Where(p => p.MachineName == ProcessEntity.None).Select(a => a.Process).ToList(); if (taken.Any()) { using (Transaction tr = Transaction.ForceNew()) { Database.Query <ProcessEntity>() .Where(p => taken.Contains(p.ToLite()) && p.MachineName == ProcessEntity.None) .UnsafeUpdate() .Set(p => p.MachineName, p => Environment.MachineName) .Set(p => p.ApplicationName, p => Schema.Current.ApplicationName) .Execute(); tr.Commit(); } goto retry; } foreach (var pair in afordable) { ProcessEntity pro = pair.Process.Retrieve(); IProcessAlgorithm algorithm = ProcessLogic.GetProcessAlgorithm(pro.Algorithm); ExecutingProcess executingProcess = new ExecutingProcess(algorithm, pro); executing.Add(pro.ToLite(), executingProcess); executingProcess.TakeForThisMachine(); using (ExecutionContext.SuppressFlow()) Task.Run(() => { try { executingProcess.Execute(); } catch (Exception ex) { try { ex.LogException(edn => { edn.ControllerName = "ProcessWorker"; edn.ActionName = executingProcess.CurrentProcess.ToLite().Key(); }); } catch { } } finally { lock (executing) { executing.Remove(pro.ToLite()); WakeUp("Process ended", null); } } }); } var suspending = Database.Query <ProcessEntity>() .Where(p => p.State == ProcessState.Suspending) .Where(p => p.IsMine()) .Select(a => a.ToLite()) .ToListWakeup("Suspending dependency"); foreach (var s in suspending) { ExecutingProcess execProc = executing.GetOrThrow(s); if (execProc.CurrentProcess.State != ProcessState.Finished) { execProc.CurrentProcess = s.Retrieve(); execProc.CancelationSource.Cancel(); } } } } } } } catch (ThreadAbortException) { //Ignore } catch (Exception e) { try { exception = e.LogException(edn => { edn.ControllerName = "ProcessWorker"; edn.ActionName = "MainLoop"; }); } catch { } } finally { lock (executing) executing.Clear(); SystemEventLogLogic.Log("Stop ProcessRunner", exception); running = false; } } }, TaskCreationOptions.LongRunning); }
public void Execute(ExecutingProcess executingProcess) => Action(executingProcess);