예제 #1
0
        public Task <bool> Run(ScheduledTask task, IProgress <SboJobProgress> progress = null, bool force = false)
        {
            Task <bool> returnTask = Task.FromResult(false);

            try
            {
                SboTransaction.Start();
                var lockResult = SboDistributedLock.GetLock($"SboTaskScheduler.{task.Name}");
                if (lockResult != 0)
                {
                    SboTransaction.Rollback();
                    return(returnTask);
                }

                var lastOccurrence = SboAddon.Instance.Settings.GetValueOrDefault <DateTime?>("taskscheduler.lastoccurrence." + task.Name);
                var nextOccurrence = SboAddon.Instance.Settings.GetValueOrDefault <DateTime?>("taskscheduler.nextoccurrence." + task.Name);
                var synchronicity  = task.IsAsync ? "asynchronous" : "synchronous";
                Logger.Trace(
                    $"Checking if task {task.Name} is applicable, last occurrence {lastOccurrence} - next occurrence {nextOccurrence}");

                if (force || !nextOccurrence.HasValue || nextOccurrence.Value < DateTime.Now)
                {
                    // Set new values
                    lastOccurrence = DateTime.Now;
                    nextOccurrence = task.Schedule.GetNextOccurrence(lastOccurrence.Value);
                    SboAddon.Instance.Settings.SetValue("taskscheduler.lastoccurrence." + task.Name, lastOccurrence.Value);
                    SboAddon.Instance.Settings.SetValue("taskscheduler.nextoccurrence." + task.Name, nextOccurrence.Value);

                    SboTransaction.Commit();

                    // Run task
                    var cancellationToken = CancellationToken.None;
                    var task1             = task;
                    var progressObject    = progress;
                    returnTask = Task.Factory.StartNew(async() =>
                    {
                        Logger.Info($@"Running {synchronicity} task {task.Name}.");

                        var stopwatch = Stopwatch.StartNew();

                        try
                        {
                            task.Action?.Invoke(progressObject);

                            if (task.AsyncAction != null)
                            {
                                await task.AsyncAction(progressObject);
                            }
                        }
                        catch (Exception e)
                        {
                            Logger.Error(e, $"Unhandled exception occurred running scheduled task {task.Name}");
                        }

                        stopwatch.Stop();

                        Logger.Info(
                            $"Completed task {task1.Name} in {stopwatch.Elapsed}. Next occurrence {nextOccurrence}");

                        SboAddonTracker.TrackEvent("ScheduledTaskRun", new Dictionary <string, string> {
                            ["TaskName"] = task1.Name
                        },
                                                   new Dictionary <string, double> {
                            ["Duration"] = stopwatch.ElapsedMilliseconds
                        });

                        return(true);
                    }, cancellationToken, TaskCreationOptions.None,
                                                       task.IsAsync ? TaskScheduler.Default : SboAddon.Instance.UiTaskScheduler).Unwrap();
                }
                else if (SboAddon.Instance.Company.InTransaction)
                {
                    SboTransaction.Commit();
                }

                task.LastOccurrence = lastOccurrence;
            }
            catch (Exception e)
            {
                Logger.Error(e, "Unhandled exception occurred running scheduled tasks");
                try { SboTransaction.Rollback(); } catch (Exception) { }
            }

            return(returnTask);
        }