Example #1
0
        public void Execute(ScheduleTask task, bool throwOnError = false)
        {
            if (task.IsRunning)
            {
                return;
            }

            if (AsyncRunner.AppShutdownCancellationToken.IsCancellationRequested)
            {
                return;
            }

            bool   faulted   = false;
            bool   canceled  = false;
            string lastError = null;
            ITask  instance  = null;
            string stateName = null;

            Type taskType = null;

            try
            {
                taskType = Type.GetType(task.Type);
                if (!PluginManager.IsActivePluginAssembly(taskType.Assembly))
                {
                    return;
                }
            }
            catch
            {
                return;
            }

            try
            {
                // set background task system customer as current customer
                var customer = _userService.GetUserByUserName(SystemUserNames.BackgroundTask);
                _workContext.CurrentUser = customer;

                // create task instance
                instance  = _taskResolver(taskType);
                stateName = task.Id.ToString();

                // prepare and save entity
                task.LastStartUtc    = DateTime.UtcNow;
                task.LastEndUtc      = null;
                task.NextRunUtc      = null;
                task.ProgressPercent = null;
                task.ProgressMessage = null;

                _scheduledTaskService.UpdateTask(task);

                // create & set a composite CancellationTokenSource which also contains the global app shoutdown token
                var cts = CancellationTokenSource.CreateLinkedTokenSource(AsyncRunner.AppShutdownCancellationToken, new CancellationTokenSource().Token);
                AsyncState.Current.SetCancelTokenSource <ScheduleTask>(cts, stateName);

                var ctx = new TaskExecutionContext(_componentContext, task)
                {
                    ScheduleTask      = task.Clone(),
                    CancellationToken = cts.Token
                };

                instance.Execute(ctx);
            }
            catch (Exception ex)
            {
                faulted  = true;
                canceled = ex is OperationCanceledException;
                Logger.Error(string.Format("Error while running scheduled task '{0}'. {1}", task.Name, ex.Message), ex);
                lastError = ex.Message.Truncate(995, "...");
                if (throwOnError)
                {
                    throw;
                }
            }
            finally
            {
                // remove from AsyncState
                if (stateName.HasValue())
                {
                    AsyncState.Current.Remove <ScheduleTask>(stateName);
                }

                task.ProgressPercent = null;
                task.ProgressMessage = null;

                var now = DateTime.UtcNow;
                task.LastError  = lastError;
                task.LastEndUtc = now;

                if (faulted)
                {
                    if ((!canceled && task.StopOnError) || instance == null)
                    {
                        task.Enabled = false;
                    }
                }
                else
                {
                    task.LastSuccessUtc = now;
                }

                if (task.Enabled)
                {
                    task.NextRunUtc = _scheduledTaskService.GetNextSchedule(task);
                }

                _scheduledTaskService.UpdateTask(task);
            }
        }