示例#1
0
        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);
                }
            }
        }
示例#2
0
        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);
                    }
                }
            }
        }
示例#3
0
        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();
        }
示例#4
0
        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();
            });
        }
示例#5
0
        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();
                });
        }
示例#6
0
        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);
                    }
                }
            }
        }
示例#7
0
 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);
     }
 }
示例#8
0
        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();
            });
        }
示例#9
0
        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);
            }
        }
示例#10
0
        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);
                    }
                });
            }
        }
示例#11
0
        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();
            });
        }
示例#12
0
        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);
        }
示例#13
0
 public void Execute(ExecutingProcess executingProcess) => Action(executingProcess);