예제 #1
0
 /// <summary>
 /// Позволяет инициировать немедленный запуск задачи в отдельном объекте <see cref="Task"/>.
 /// </summary>
 /// <param name="taskDescription">Запускаемая задача.</param>
 /// <return>Возвращает объект <see cref="Task"/>.</return>
 public Task <TaskExecuted> ExecuteTask(TaskDescription taskDescription)
 {
     if (!_taskList.Any(x => x.Value == taskDescription))
     {
         throw new InvalidOperationException("Задача не зарегистрирована.");
     }
     return(Task.Factory.StartNew(() => ExecuteTaskInternal(taskDescription)));
 }
예제 #2
0
 /// <summary>
 /// Позволяет изменить состояние задачи.
 /// </summary>
 /// <param name="taskDescription">Зарегистрированная задача.</param>
 /// <param name="isEnabled">Новое состояние задачи.</param>
 /// <exception cref="ArgumentNullException">Возникает, если <paramref name="taskDescription"/> равен null.</exception>
 /// <exception cref="InvalidOperationException">Возникает, если задача не зарегистрирована.</exception>
 /// <exception cref="InvalidOperationException">Возникает, если для задачи запрещено изменение состояния (см. <see cref="TaskOptions.AllowDisabling"/>).</exception>
 public void SetTaskEnabled(TaskDescription taskDescription, bool isEnabled)
 {
     if (taskDescription == null)
     {
         throw new ArgumentNullException(nameof(taskDescription));
     }
     if (!_taskList.TryGetValue(taskDescription.UniqueKey, out var taskDescription2))
     {
         throw new InvalidOperationException("Неизвестная задача.");
     }
     if (!taskDescription2.TaskOptions.HasFlag(TaskOptions.AllowDisabling))
     {
         throw new InvalidOperationException("Для задачи запрещено изменение состояния.");
     }
     taskDescription2.IsEnabled = isEnabled;
     taskDescription.IsEnabled  = isEnabled;
 }
예제 #3
0
        private TaskExecuted ExecuteTaskInternal(TaskDescription taskDescription)
        {
            if (!_executeFlags.TryLock(taskDescription.UniqueKey) && taskDescription.TaskOptions.HasFlag(TaskOptions.PreventParallelExecution))
            {
                return(TaskExecuted.ParallelPrevented);
            }

            try
            {
                var idItemType = Core.Items.ItemTypeFactory.GetItemType <Db.Task>().IdItemType;
                var itemKey    = new Core.Items.ItemKey(idItemType, taskDescription.Id);

                if (!(taskDescription.JournalOptions != null && taskDescription.JournalOptions.LimitByLastNDays.HasValue && taskDescription.JournalOptions.LimitByLastNDays <= 0))
                {
                    this.RegisterEventForItem(itemKey, Journaling.EventType.Info, "Запуск", $"Запуск задачи '{taskDescription.Name}' (№{taskDescription.Id} / '{taskDescription.UniqueKey}').");
                }

                var timeStart = DateTime.Now;

                taskDescription.ExecutionLambda.Compile().Invoke();

                if (!(taskDescription.JournalOptions != null && taskDescription.JournalOptions.LimitByLastNDays.HasValue && taskDescription.JournalOptions.LimitByLastNDays <= 0))
                {
                    this.RegisterEventForItem(itemKey, Journaling.EventType.Info, "Завершение", $"Задача '{taskDescription.Name}' (№{taskDescription.Id} / '{taskDescription.UniqueKey}') выполнена за {Math.Round((DateTime.Now - timeStart).TotalSeconds, 3)} сек.");
                }

                return(TaskExecuted.Executed);
            }
            catch (Exception ex)
            {
                if (!(taskDescription.JournalOptions != null && taskDescription.JournalOptions.LimitByLastNDays.HasValue && taskDescription.JournalOptions.LimitByLastNDays <= 0))
                {
                    this.RegisterEvent(Journaling.EventType.Info, "Ошибка выполнения", $"Неожиданная ошибка выполнения задачи '{taskDescription.Name}' (№{taskDescription.Id} / '{taskDescription.UniqueKey}').", ex);
                }
                return(TaskExecuted.Faulted);
            }
            finally
            {
                _executeFlags.ReleaseLock(taskDescription.UniqueKey);
            }
        }
예제 #4
0
        private void PrepareTaskSchedules(TaskDescription taskDescription)
        {
            foreach (var schedule in taskDescription.ManualSchedules)
            {
                var scheduleUniqueKey = schedule.GetUniqueKey();
                var uniqueKey         = $"task_{taskDescription.UniqueKey}_sc_{scheduleUniqueKey}";

                if (!schedule.IsEnabled)
                {
                    lock (_jobsSyncRoot)
                    {
                        _jobsList.RemoveAll(x => x.JobName == uniqueKey);
                    }
                    continue;
                }

                if (schedule is TaskCronSchedule taskCronSchedule)
                {
                    SetTask(uniqueKey, taskCronSchedule.CronExpression, () => ExecuteTaskStatic(taskDescription.UniqueKey, scheduleUniqueKey));
                }
                else if (schedule is TaskFixedTimeSchedule taskFixedTimeSchedule)
                {
                    SetTask(uniqueKey, taskFixedTimeSchedule.DateTime, () => ExecuteTaskStatic(taskDescription.UniqueKey, scheduleUniqueKey));
                }
            }
            foreach (var schedule in taskDescription.Schedules)
            {
                var scheduleUniqueKey = schedule.GetUniqueKey();
                var uniqueKey         = $"task_{taskDescription.UniqueKey}_sc_{scheduleUniqueKey}";

                if (schedule is TaskCronSchedule taskCronSchedule)
                {
                    SetTask(uniqueKey, taskCronSchedule.CronExpression, () => ExecuteTaskStatic(taskDescription.UniqueKey, scheduleUniqueKey));
                }
                else if (schedule is TaskFixedTimeSchedule taskFixedTimeSchedule)
                {
                    SetTask(uniqueKey, taskFixedTimeSchedule.DateTime, () => ExecuteTaskStatic(taskDescription.UniqueKey, scheduleUniqueKey));
                }
            }
        }
예제 #5
0
        private TaskDescription UpdateTask(TaskDescription taskDescription, TaskRequest taskRequest)
        {
            using (var db = new Db.DataContext())
            {
                var taskDb = db.Task.Where(x => x.UniqueKey == taskRequest.UniqueKey).Include(x => x.TaskSchedules).FirstOrDefault();
                if (taskDb == null)
                {
                    taskDb = new Db.Task()
                    {
                        Name          = taskRequest.Name,
                        Description   = taskRequest.Description,
                        IsEnabled     = null,
                        TaskSchedules = new List <Db.TaskSchedule>(),
                        UniqueKey     = taskRequest.UniqueKey
                    };
                    db.Task.Add(taskDb);
                    db.SaveChanges();
                }

                taskDb.Name        = taskRequest.Name;
                taskDb.Description = taskRequest.Description;

                if (!taskRequest.TaskOptions.HasFlag(TaskOptions.AllowDisabling))
                {
                    taskDb.IsEnabled = null;
                }

                if (!taskRequest.TaskOptions.HasFlag(TaskOptions.AllowManualSchedule) && taskDb.TaskSchedules.Count > 0)
                {
                    db.TaskSchedule.RemoveRange(taskDb.TaskSchedules);
                    taskDb.TaskSchedules.Clear();
                }
                db.SaveChanges();

                var schedules = new List <TaskSchedule>();
                foreach (var scheduleDb in taskDb.TaskSchedules)
                {
                    TaskSchedule taskSchedule = null;
                    if (scheduleDb.DateTimeFixed.HasValue)
                    {
                        taskSchedule = new TaskFixedTimeSchedule(new DateTimeOffset(scheduleDb.DateTimeFixed.Value.Ticks, TimeSpan.Zero));
                    }
                    else if (!string.IsNullOrEmpty(scheduleDb.Cron))
                    {
                        taskSchedule = new TaskCronSchedule(scheduleDb.Cron);
                    }

                    if (taskSchedule == null)
                    {
                        continue;
                    }
                    taskSchedule.IsEnabled = scheduleDb.IsEnabled;
                    schedules.Add(taskSchedule);
                }

                taskDescription.Id              = taskDb.Id;
                taskDescription.Name            = taskRequest.Name;
                taskDescription.Description     = taskRequest.Description;
                taskDescription.ExecutionLambda = taskRequest.ExecutionLambda;
                taskDescription.IsConfirmed     = true;
                taskDescription.UniqueKey       = taskRequest.UniqueKey;
                taskDescription.IsEnabled       = taskDb.IsEnabled ?? taskRequest.IsEnabled;
                taskDescription.TaskOptions     = taskRequest.TaskOptions;
                taskDescription.Schedules       = new ReadOnlyCollection <TaskSchedule>(taskRequest.Schedules ?? new List <TaskSchedule>());
                taskDescription.ManualSchedules = new ReadOnlyCollection <TaskSchedule>(schedules.GroupBy(x => x.GetUniqueKey()).Select(x => x.First()).ToList());
                taskDescription.JournalOptions  = taskRequest.JournalOptions;
            }
            return(taskDescription);
        }
예제 #6
0
        /// <summary>
        /// Позволяет изменить список дополнительных правил задачи.
        /// </summary>
        /// <param name="taskDescription">Зарегистрированная задача.</param>
        /// <param name="scheduleList">Список правил задачи.</param>
        /// <exception cref="ArgumentNullException">Возникает, если <paramref name="taskDescription"/> равен null.</exception>
        /// <exception cref="InvalidOperationException">Возникает, если задача не зарегистрирована.</exception>
        /// <exception cref="InvalidOperationException">Возникает, если для задачи запрещено изменение списка правил (см. <see cref="TaskOptions.AllowManualSchedule"/>).</exception>
        public void SetTaskManualScheduleList(TaskDescription taskDescription, List <TaskSchedule> scheduleList)
        {
            if (taskDescription == null)
            {
                throw new ArgumentNullException(nameof(taskDescription));
            }
            if (!_taskList.TryGetValue(taskDescription.UniqueKey, out var taskDescription2))
            {
                throw new InvalidOperationException("Неизвестная задача.");
            }
            if (!taskDescription2.TaskOptions.HasFlag(TaskOptions.AllowManualSchedule))
            {
                throw new InvalidOperationException("Для задачи запрещено изменение списка правил.");
            }
            if (scheduleList?.GroupBy(x => x.GetUniqueKey()).Any(x => x.Count() > 1) ?? false)
            {
                throw new ArgumentException("В списке есть повторяющиеся правила запуска.", nameof(scheduleList));
            }

            try
            {
                var schedules  = scheduleList?.ToDictionary(x => x.GetUniqueKey(), x => x);
                var collection = new ReadOnlyCollection <TaskSchedule>(scheduleList ?? new List <TaskSchedule>());

                using (var db = new Db.DataContext())
                {
                    var list = db.TaskSchedule.Where(x => x.IdTask == taskDescription2.Id).ToList();

                    var listToRemove = list.Where(x => !schedules.ContainsKey(x.GetUniqueKey())).ToList();
                    db.TaskSchedule.RemoveRange(listToRemove);

                    var isChanged = listToRemove.Count > 0;

                    list.Where(x => schedules.ContainsKey(x.GetUniqueKey())).ForEach(x =>
                    {
                        isChanged   = isChanged || x.IsEnabled != schedules[x.GetUniqueKey()].IsEnabled;
                        x.IsEnabled = schedules[x.GetUniqueKey()].IsEnabled;
                    });

                    schedules.ForEach(pair =>
                    {
                        if (!list.Any(x => x.GetUniqueKey() == pair.Key))
                        {
                            if (pair.Value is TaskCronSchedule taskCronSchedule)
                            {
                                isChanged = true;
                                db.TaskSchedule.Add(new Db.TaskSchedule()
                                {
                                    IdTask    = taskDescription2.Id,
                                    IsEnabled = pair.Value.IsEnabled,
                                    Cron      = taskCronSchedule.CronExpression
                                });
                            }
                            else if (pair.Value is TaskFixedTimeSchedule taskFixedTimeSchedule)
                            {
                                isChanged = true;
                                db.TaskSchedule.Add(new Db.TaskSchedule()
                                {
                                    IdTask        = taskDescription2.Id,
                                    IsEnabled     = pair.Value.IsEnabled,
                                    DateTimeFixed = taskFixedTimeSchedule.DateTime.UtcDateTime
                                });
                            }
                        }
                    });

                    if (isChanged)
                    {
                        db.SaveChanges();
                    }

                    taskDescription2.ManualSchedules = collection;
                    taskDescription.ManualSchedules  = collection;
                    PrepareTaskSchedules(taskDescription2);
                }
            }
            catch (Exception ex)
            {
                this.RegisterEvent(Journaling.EventType.CriticalError, "Ошибка во время сохранения списка правил", null, ex);
                throw new Exception("Неожиданная ошибка во время сохранения списка правил.");
            }
        }
예제 #7
0
        /// <summary>
        /// Возвращает список задач.
        /// </summary>
        /// <param name="onlyConfirmed">Если равно true, то возвращает только подтвержденные задачи (см. <see cref="TaskDescription.IsConfirmed"/>.</param>
        public List <TaskDescription> GetTaskList(bool onlyConfirmed)
        {
            try
            {
                var list = _taskList.Values.ToDictionary(x => x.Id, x => x);
                if (!onlyConfirmed)
                {
                    using (var db = new Db.DataContext())
                    {
                        var query    = db.Task.Include(x => x.TaskSchedules);
                        var taskList = query.ToList();
                        foreach (var taskDb in taskList)
                        {
                            if (list.ContainsKey(taskDb.Id))
                            {
                                continue;
                            }

                            var schedules = new List <TaskSchedule>();
                            foreach (var scheduleDb in taskDb.TaskSchedules)
                            {
                                TaskSchedule taskSchedule = null;
                                if (scheduleDb.DateTimeFixed.HasValue)
                                {
                                    taskSchedule = new TaskFixedTimeSchedule(new DateTimeOffset(scheduleDb.DateTimeFixed.Value.Ticks, TimeSpan.Zero));
                                }
                                else if (!string.IsNullOrEmpty(scheduleDb.Cron))
                                {
                                    taskSchedule = new TaskCronSchedule(scheduleDb.Cron);
                                }

                                if (taskSchedule == null)
                                {
                                    continue;
                                }
                                taskSchedule.IsEnabled = scheduleDb.IsEnabled;
                                schedules.Add(taskSchedule);
                            }

                            var taskDescription = new TaskDescription
                            {
                                Id              = taskDb.Id,
                                Name            = taskDb.Name,
                                Description     = taskDb.Description,
                                ExecutionLambda = null,
                                IsConfirmed     = false,
                                UniqueKey       = taskDb.UniqueKey,
                                IsEnabled       = taskDb.IsEnabled ?? false,
                                TaskOptions     = TaskOptions.None,
                                Schedules       = new ReadOnlyCollection <TaskSchedule>(new List <TaskSchedule>()),
                                ManualSchedules = new ReadOnlyCollection <TaskSchedule>(schedules)
                            };
                            list[taskDb.Id] = taskDescription;
                        }
                    }
                }
                return(list.Values.ToList());
            }
            catch (Exception ex)
            {
                this.RegisterEvent(Journaling.EventType.CriticalError, "Ошибка во время получения списка задач", null, ex);
                throw new Exception("Неожиданная ошибка во время получения списка задач.");
            }
        }