Exemplo n.º 1
0
        /// <summary>
        /// Creates a transient context, which can be passed to methods requiring a <see cref="TaskExecutionContext"/> instance.
        /// Such methods are usually executed by the task executor in the background. If a manual invocation of such
        /// methods is required, this is the way to go.
        /// </summary>
        /// <param name="componentContext">The component context</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>A transient context</returns>
        public static TaskExecutionContext CreateTransientContext(IComponentContext componentContext, CancellationToken cancellationToken)
        {
            var originalTask = new ScheduleTask {
                Name = "Transient", IsHidden = true, Enabled = true
            };
            var context = new TransientTaskExecutionContext(componentContext, originalTask);

            context.CancellationToken = cancellationToken;
            context.ScheduleTask      = originalTask.Clone();

            return(context);
        }
Exemplo n.º 2
0
        public void Execute(
            ScheduleTask task,
            IDictionary <string, string> taskParameters = null,
            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);

                Debug.WriteLineIf(taskType == null, "Invalid task type: " + task.Type.NaIfEmpty());

                if (taskType == null)
                {
                    return;
                }

                if (!PluginManager.IsActivePluginAssembly(taskType.Assembly))
                {
                    return;
                }
            }
            catch
            {
                return;
            }

            try
            {
                Customer customer = null;

                // try virtualize current customer (which is necessary when user manually executes a task)
                if (taskParameters != null && taskParameters.ContainsKey(CurrentCustomerIdParamName))
                {
                    customer = _customerService.GetCustomerById(taskParameters[CurrentCustomerIdParamName].ToInt());
                }

                if (customer == null)
                {
                    // no virtualization: set background task system customer as current customer
                    customer = _customerService.GetCustomerBySystemName(SystemCustomerNames.BackgroundTask);
                }

                _workContext.CurrentCustomer = 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,
                    Parameters        = taskParameters ?? new Dictionary <string, string>()
                };

                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);
            }
        }
Exemplo n.º 3
0
        public void Execute(
            ScheduleTask task,
            IDictionary <string, string> taskParameters = null,
            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 (taskType == null)
                {
                    Logger.DebugFormat("Invalid scheduled task type: {0}", task.Type.NaIfEmpty());
                }

                if (taskType == null)
                {
                    return;
                }

                if (!PluginManager.IsActivePluginAssembly(taskType.Assembly))
                {
                    return;
                }
            }
            catch
            {
                return;
            }

            try
            {
                // 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.SetCancelTokenSource <ScheduleTask>(cts, stateName);

                var ctx = new TaskExecutionContext(_componentContext, task)
                {
                    ScheduleTask      = task.Clone(),
                    CancellationToken = cts.Token,
                    Parameters        = taskParameters ?? new Dictionary <string, string>()
                };

                Logger.DebugFormat("Executing scheduled task: {0}", task.Type);
                instance.Execute(ctx);
            }
            catch (Exception exception)
            {
                faulted   = true;
                canceled  = exception is OperationCanceledException;
                lastError = exception.Message.Truncate(995, "...");

                if (canceled)
                {
                    Logger.Warn(exception, T("Admin.System.ScheduleTasks.Cancellation", task.Name));
                }
                else
                {
                    Logger.Error(exception, string.Concat(T("Admin.System.ScheduleTasks.RunningError", task.Name), ": ", exception.Message));
                }

                if (throwOnError)
                {
                    throw;
                }
            }
            finally
            {
                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;
                }

                Logger.DebugFormat("Executed scheduled task: {0}. Elapsed: {1} ms.", task.Type, (now - task.LastStartUtc.Value).TotalMilliseconds);

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

                // remove from AsyncState
                if (stateName.HasValue())
                {
                    _asyncState.Remove <ScheduleTask>(stateName);
                }

                _scheduledTaskService.UpdateTask(task);
            }
        }