public async Task <HttpResponseMessage> ScheduleLegacyRequest(LegacySchedulerRequestDTO dto) { if (dto.IsNull() || dto.ScheduleJSON.IsNullOrEmpty()) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "The Request Schedule is not defined.")); } try { //Delete the recurring job, if it exists Hangfire.RecurringJob.RemoveIfExists(dto.RequestID.ToString()); //Check if any additional schedule jobs exist if (DataContext.RequestSchedules.Any(p => p.RequestID == dto.RequestID)) { var schedules = await DataContext.RequestSchedules.Where(p => p.RequestID == dto.RequestID).ToListAsync(); foreach (var item in schedules) { if (item.ScheduleType == RequestScheduleTypes.Recurring) { Hangfire.RecurringJob.RemoveIfExists(item.ScheduleID); } else { Hangfire.BackgroundJob.Delete(item.ScheduleID); } } DataContext.RequestSchedules.RemoveRange(schedules); await DataContext.SaveChangesAsync(); } RequestScheduleModel scheduleModel = Newtonsoft.Json.JsonConvert.DeserializeObject <RequestScheduleModel>(dto.ScheduleJSON); if (scheduleModel.PauseJob) { //Do not schedule anything if the user has paused the schedule. return(new HttpResponseMessage(HttpStatusCode.OK)); } string cronExpression = ScheduleManager.GetCronExpression(scheduleModel); var schedule = NCrontab.CrontabSchedule.Parse(cronExpression); if (scheduleModel.StartDate <= DateTime.Now) { Hangfire.RecurringJob.AddOrUpdate <LegacyRequestsController>(dto.RequestID.ToString(), (x) => x.OnSubmitSchedulerRequest(Identity.ID, dto.RequestID.Value), cronExpression); //LegacyRequests.ActivateLegacyRequestSchedule(Identity.ID, requestID, cronExpression); RequestSchedule requestSchedule = new RequestSchedule(); requestSchedule.RequestID = dto.RequestID.Value; requestSchedule.ID = Guid.NewGuid(); requestSchedule.ScheduleID = dto.RequestID.ToString(); requestSchedule.ScheduleType = RequestScheduleTypes.Recurring; DataContext.RequestSchedules.Add(requestSchedule); } else { var jobID = Hangfire.BackgroundJob.Schedule <LegacyRequestsController>((x) => x.ActivateLegacyRequestSchedule(Identity.ID, dto.RequestID.Value, cronExpression), scheduleModel.StartDate); RequestSchedule requestSchedule = new RequestSchedule(); requestSchedule.RequestID = dto.RequestID.Value; requestSchedule.ID = Guid.NewGuid(); requestSchedule.ScheduleID = jobID; requestSchedule.ScheduleType = RequestScheduleTypes.Activate; DataContext.RequestSchedules.Add(requestSchedule); } if (scheduleModel.EndDate.HasValue) { var jobID = Hangfire.BackgroundJob.Schedule <LegacyRequestsController>((x) => x.DeactivateLegacyRequestSchedule(dto.RequestID.Value), scheduleModel.EndDate.Value); RequestSchedule requestSchedule = new RequestSchedule(); requestSchedule.RequestID = dto.RequestID.Value; requestSchedule.ID = Guid.NewGuid(); requestSchedule.ScheduleID = jobID; requestSchedule.ScheduleType = RequestScheduleTypes.Deactivate; DataContext.RequestSchedules.Add(requestSchedule); } await DataContext.SaveChangesAsync(); return(new HttpResponseMessage(HttpStatusCode.OK)); } catch (Exception ex) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not schedule request. Details: " + ex.Message)); } }
/// <summary> /// Hangfire uses NCronTab expressions. /// A crontab expression are a very compact way to express a recurring schedule. A single expression is composed of 5 space-delimited fields: /// MINUTES HOURS DAYS MONTHS DAYS-OF-WEEK /// </summary> /// <param name="model"></param> /// <returns></returns> internal static string GetCronExpression(RequestScheduleModel model) { int hour = model.RunTime.Hour; int mins = model.RunTime.Minute; // MINS HOURS DAYS MONTHS DAYS-WEEK string cronPattern = "{0} {1} {2} {3} {4}"; string cronExpr = null; switch (model.RecurrenceType) { case "Daily": switch (model.DailyType) { case "EveryNDays": if (model.NDays == 1) { cronExpr = string.Format(cronPattern, mins, hour, "*", "*", "*"); } else { cronExpr = string.Format(cronPattern, mins, hour, "*/" + model.NDays, "*", "*"); } break; case "EveryWeekDay": cronExpr = string.Format(cronPattern, mins, hour, "*", "*", "0-6"); break; } break; case "Weekly": string dow = ""; if (model.Sunday) { dow += "0,"; } if (model.Monday) { dow += "1,"; } if (model.Tuesday) { dow += "2,"; } if (model.Wednesday) { dow += "3,"; } if (model.Thursday) { dow += "4,"; } if (model.Friday) { dow += "5,"; } if (model.Saturday) { dow += "6,"; } dow = dow.Length > 0 ? dow.Substring(0, dow.Length - 1) : "*"; cronExpr = string.Format(cronPattern, mins, hour, "*", "*", dow); break; case "Monthly": switch (model.MonthlyType) { case "DayOfMonth": if (model.NMonthsForMonthDay == 1) { cronExpr = string.Format(cronPattern, mins, hour, model.MonthDay, "*", "*"); } else { cronExpr = string.Format(cronPattern, mins, hour, model.MonthDay + "/" + model.NMonthsForMonthDay, "*", "*"); } break; case "WeekDayOfMonth": if (model.NMonthsForWeekDay == 1) { cronExpr = string.Format(cronPattern, mins, hour, "*", "*", GetWeekDayNumber(model.WeekDay)); } else { cronExpr = string.Format(cronPattern, mins, hour, "*", "*/" + model.NMonthsForWeekDay, GetWeekDayNumber(model.WeekDay) + GetWeekDayPattern(model.NthWeekDay)); } break; } break; case "Yearly": switch (model.YearlyType) { case "YearlyDayOfMonth": cronExpr = string.Format(cronPattern, mins, hour, model.DayOfMonth, GetMonthNumber(model.Month), "*"); break; case "YearlyWeekDayOfMonth": cronExpr = string.Format(cronPattern, mins, hour, "*", GetMonthNumber(model.Month), GetWeekDayNumber(model.WeekDay) + GetWeekDayPattern(model.NthWeekDay)); break; } break; } return(cronExpr); }
public void OnSubmitSchedulerRequest(Guid userID, Guid requestID) { //Ensure the request exists and is not deleted, otherwise clear the schedule if (DataContext.Requests.Any(p => p.ID == requestID) == false || DataContext.Requests.Any(p => p.ID == requestID && p.Deleted == true)) { DeleteRequestSchedules(requestID); return; } var user = (from u in DataContext.Users where u.ID == userID select u).AsNoTracking().FirstOrDefault(); Lpp.Utilities.Security.ApiIdentity identity = new Utilities.Security.ApiIdentity(user.ID, user.UserName, user.FullName, user.OrganizationID); try { if (!DataContext.Requests.Any(p => p.ID == requestID)) { throw new Exception("Cannot find scheduled request ID = " + requestID.ToString()); } var request = DataContext.Requests .Include("Activity") .Include("Activity.ParentActivity") .Include("Activity.ParentActivity.ParentActivity") .Include("SourceActivity") .Include("SourceActivityProject") .Include("SourceTaskOrder") .Include("Organization") .Include("Project") .Include("RequestType") .Include("RequesterCenter") .Include("WorkplanType") .Include("CreatedBy") .Include("UpdatedBy") .Include("SubmittedBy") .Include("DataMarts") .Include("Folders") .Include("SearchTerms") //.AsNoTracking() .SingleOrDefault(r => r.ID == requestID); if (request == null) { throw new Exception("Cannot find scheduled request ID = " + requestID.ToString()); } var newRequest = CopyRequest(request, identity); //db.Entry(ctx.Request).Reload(); DataContext.Entry(request).Reload(); DataContext.Entry(newRequest).Reload(); // Suffix the request name by its recurrence type and instance count. XmlSerializer serializer = new XmlSerializer(typeof(DTO.Schedule.RequestScheduleModel)); RequestScheduleModel scheduleModel = serializer.Deserialize(new StringReader(request.Schedule ?? "")) as RequestScheduleModel; string schedName = string.IsNullOrEmpty(request.Name) ? "" : request.Name.Substring(0, (request.Name.Length > 100) ? 100 : request.Name.Length); schedName = schedName + " (" + scheduleModel.RecurrenceType + " " + (++request.ScheduleCount) + ")"; newRequest.Name = schedName; // If there is a request due date and there is a schedule start date and request due date > schedule start date, // then slide the due date forward by the same amount from the current date. if (request.DueDate != null && scheduleModel.StartDate != null) { DateTime newDueDate = DateTime.Now.Add(((DateTime)request.DueDate).Subtract(scheduleModel.StartDate.DateTime)); TimeSpan delta = newDueDate.Subtract((DateTime)request.DueDate); newRequest.DueDate = newDueDate; //RequestService.TimeShift(newCtx, delta); } //var res = RequestService.TimeShift(newCtx, newCtx.Request.CreatedOn - ctx.Request.CreatedOn); DataContext.SaveChanges(); if (!SubmitRequest(newRequest.ID, identity)) { throw new Exception("Failed to submit request."); } } catch (Exception ex) { //Log.Error(ex); throw; } }