//TODO add IScheduler to get access to task queue /// <summary> /// Determine queue for this task. Can also modify task /// </summary> /// <param name="task"></param> /// <returns></returns> protected override string Schedule(ScheduledTask task) { switch ((Algorithms)task.AlgorithmID) { case Algorithms.Default: return "Default"; case Algorithms.Reports: return "Reports"; case Algorithms.Alerts: return "Alerts"; case Algorithms.System: ScheduleSystemTask(task); return "System"; case Algorithms.Address: return "Address"; default: return "Unknown"; } }
protected override void ScheduleSpecific(ScheduledTask newTask) { if (newTask.AlgorithmID == (byte)Algorithms.Reports) { var reportSpecific = (ReportTask.Args)XmlUtils.Deserialize(newTask.Arguments, typeof(ReportTask.Args)); DateTime userLocalStartTime = TimeZoneInfo.ConvertTimeFromUtc(newTask.StartTime, newTask.GetTimeZoneInfo()); reportSpecific.Definition.CalculatePeriod(userLocalStartTime); newTask.Arguments = XmlUtils.Serialize(reportSpecific, false); } }
protected override TaskStatus Run(ScheduledTask task) { Stopwatch sw = null; if (_Log.MaxLevel >= 3) sw = Stopwatch.StartNew(); try { switch ((Programs)task.ProgramID) { case Programs.ReportHandler: var started = DateTime.UtcNow; ReportTask repTask = AppTaskHelper.Convert<ReportTask>(task); repTask.Arguments = (ReportTask.Args)XmlUtils.Deserialize(task.Arguments, typeof(ReportTask.Args)); string reportName; string ext; Uri uri = RunReport(repTask, task.CompanyID, out reportName, out ext); _Log.InfoFormat("(1) RunReport -> {0} {1}", uri, reportName); string path = repTask.Notification.AsAttachment ? DownloadReport(uri, reportName,ext) : null; _Log.InfoFormat("(2) Download -> {0}", path); NotifyRecipients(repTask, path); _Log.InfoFormat("(3) Notify -> {0}", path); LogReportProcessingTime(repTask, reportName, started); break; case Programs.SystemEventHandler: var sysTask = AppTaskHelper.Convert<SystemEventTask>(task); sysTask.Arguments = (SystemEventTask.Args)XmlUtils.Deserialize(task.Arguments, typeof(SystemEventTask.Args)); if (!RunSystemEvent(sysTask)) return TaskStatus.Cancelled; break; #if TaskHandler case Programs.`ProgramName`: `Task`Task task`ProgramNumber` = AppTaskHelper.Convert<`Task`Task>(task); task`ProgramNumber`.Arguments = (`Task`Task.Args)XmlUtils.Deserialize(task.Arguments, typeof(`Task`Task.Args)); Run`Task`(task`ProgramNumber`); break; #endif } return TaskStatus.Success; } catch (Exception ex) { _Log.ErrorFormat("Error on Run {0}: {1}", task, ex); return TaskStatus.Failure; } finally { if (sw != null) { sw.Stop(); _Log.InfoFormat("- P{0} {1} ({2} ms) {3}", task.ProgramID, task.ID, sw.ElapsedMilliseconds, task.Recurrence); } } }
/// <summary> /// Execute one task and update the status in the table. /// </summary> /// <param name="task"></param> private void ProcessOneTask(ScheduledTask task) { TaskStatus status; // if (task.Recurrence != null && status != TaskStatus.Cancelled) if (task.Recurrence != null) { var cancelled = _QueueCache.CancelSeries(task.QueueID, task.TaskID); _Log.DebugFormat("Cancelled {0} of series {1}", cancelled.Count, task.TaskID); // Generate the very next recurring task only. ScheduledTask newTask = task.Copy(SequentialGuid.NewDbGuid()); DateTime userTime, utc; CalculateStartTime(newTask.GetTimeZoneInfo(), newTask.Recurrence, newTask.TimeOfDay, out userTime, out utc); newTask.StartTime = utc; newTask.DueTime = newTask.StartTime + (task.DueTime - task.StartTime); //TODO make sure before next recurrence newTask.Status = 0; newTask.Active = true; newTask.QueueID = null; ScheduleSpecific(newTask); IImardaTask service = _Proxy.GetChannel(); ChannelInvoker.Invoke(delegate(out IClientChannel channel) { channel = service as IClientChannel; var resp2 = service.SaveScheduledTask(new SaveRequest<ScheduledTask>(newTask)); ErrorHandler.Check(resp2); }); } try { // Active tasks get run, but inactive tasks are templates only, they need to be scheduled, i.e. their start time calculated. status = task.Active ? Run(task) : TaskStatus.Rescheduled; } catch { // make sure Run catches all exceptions, then we'll never get here. status = TaskStatus.Failure; } try { SaveStatus(task.ID, status, null); } catch (Exception ex) { _Log.ErrorFormat("Cannot save ScheduledTask: {0}", ex); throw; } }
/// <summary> /// Override to implement changing the task's arguments after setting the new StartTime of a recurrence. /// </summary> /// <param name="task"></param> protected abstract void ScheduleSpecific(ScheduledTask task);
/// <summary> /// Override to select a queue for this task and tweak start time, due time, retries etc, /// </summary> /// <param name="task"></param> /// <returns>queue ID</returns> protected abstract string Schedule(ScheduledTask task);
/// <summary> /// Override to execute the task. Exceptions thrown will be handled by the JobQueueHandler. /// </summary> /// <param name="task"></param> /// <returns>status</returns> protected abstract TaskStatus Run(ScheduledTask task);