public void Can_save_and_load_scheduleTask() { var scheduleTask = new ScheduleTask { Name = "Task 1", Seconds = 1, Type = "some type 1", Enabled = true, StopOnError = true, LastStartUtc = new DateTime(2010, 01, 01), LastEndUtc = new DateTime(2010, 01, 02), LastSuccessUtc= new DateTime(2010, 01, 03), }; var fromDb = SaveAndLoadEntity(scheduleTask); fromDb.ShouldNotBeNull(); fromDb.Name.ShouldEqual("Task 1"); fromDb.Seconds.ShouldEqual(1); fromDb.Type.ShouldEqual("some type 1"); fromDb.Enabled.ShouldEqual(true); fromDb.StopOnError.ShouldEqual(true); fromDb.LastStartUtc.ShouldEqual(new DateTime(2010, 01, 01)); fromDb.LastEndUtc.ShouldEqual(new DateTime(2010, 01, 02)); fromDb.LastSuccessUtc.ShouldEqual(new DateTime(2010, 01, 03)); }
protected ScheduleTaskModel PrepareScheduleTaskModel(ScheduleTask task) { var model = new ScheduleTaskModel() { Id = task.Id, Name = task.Name, Seconds = task.Seconds, Enabled = task.Enabled, StopOnError = task.StopOnError, LastStartUtc = task.LastStartUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastStartUtc.Value, DateTimeKind.Utc).ToString("G") : "", LastEndUtc = task.LastEndUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastEndUtc.Value, DateTimeKind.Utc).ToString("G") : "", LastSuccessUtc = task.LastSuccessUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastSuccessUtc.Value, DateTimeKind.Utc).ToString("G") : "", LastError = task.LastError.EmptyNull(), IsRunning = task.IsRunning, //task.LastStartUtc.GetValueOrDefault() > task.LastEndUtc.GetValueOrDefault(), Duration = "" }; var span = TimeSpan.Zero; if (task.LastStartUtc.HasValue) { span = model.IsRunning ? DateTime.UtcNow - task.LastStartUtc.Value : task.LastEndUtc.Value - task.LastStartUtc.Value; model.Duration = span.ToString("g"); } return model; }
/// <summary> /// Ctor for Task /// </summary> /// <param name="task">Task </param> public Task(ScheduleTask task) { this.Type = task.Type; this.Enabled = task.Enabled; this.StopOnError = task.StopOnError; this.Name = task.Name; }
/// <summary> /// Deletes a task /// </summary> /// <param name="task">Task</param> public virtual void DeleteTask(ScheduleTask task) { if (task == null) throw new ArgumentNullException("task"); _taskRepository.Delete(task); }
private bool IsTaskInstalled(ScheduleTask task) { var type = Type.GetType(task.Type); if (type != null) { return PluginManager.IsActivePluginAssembly(type.Assembly); } return false; }
/// <summary> /// Ctor for Task /// </summary> /// <param name="task">Task </param> public Job(ScheduleTask task) { this.Type = task.Type; this.Enabled = task.Enabled; this.StopOnError = task.StopOnError; this.Name = task.Name; this.LastError = task.LastError; this.IsRunning = task.IsRunning; //task.LastStartUtc.GetValueOrDefault() > task.LastEndUtc.GetValueOrDefault(); }
protected ScheduleTaskModel PrepareScheduleTaskModel(ScheduleTask task) { var model = new ScheduleTaskModel() { Id = task.Id, Name = task.Name, Seconds = task.Seconds, Enabled = task.Enabled, StopOnError = task.StopOnError, LastStartUtc = task.LastStartUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastStartUtc.Value, DateTimeKind.Utc).ToString("G") : "", LastEndUtc = task.LastEndUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastEndUtc.Value, DateTimeKind.Utc).ToString("G") : "", LastSuccessUtc = task.LastSuccessUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastSuccessUtc.Value, DateTimeKind.Utc).ToString("G") : "", }; return model; }
public virtual void UpdateTask(ScheduleTask task) { if (task == null) throw new ArgumentNullException("task"); bool saveFailed; bool? autoCommit = null; do { saveFailed = false; // ALWAYS save immediately try { autoCommit = _taskRepository.AutoCommitEnabled; _taskRepository.AutoCommitEnabled = true; _taskRepository.Update(task); } catch (DbUpdateConcurrencyException ex) { saveFailed = true; var entry = ex.Entries.Single(); var current = (ScheduleTask)entry.CurrentValues.ToObject(); // from current scope // When 'StopOnError' is true, the 'Enabled' property could have been be set to true on exception. var enabledModified = entry.Property("Enabled").IsModified; // Save current cron expression var cronExpression = task.CronExpression; // Fetch Name, CronExpression, Enabled & StopOnError from database // (these were possibly edited thru the backend) _taskRepository.Context.ReloadEntity(task); // Do we have to reschedule the task? var cronModified = cronExpression != task.CronExpression; // Copy execution specific data from current to reloaded entity task.LastEndUtc = current.LastEndUtc; task.LastError = current.LastError; task.LastStartUtc = current.LastStartUtc; task.LastSuccessUtc = current.LastSuccessUtc; task.ProgressMessage = current.ProgressMessage; task.ProgressPercent = current.ProgressPercent; task.NextRunUtc = current.NextRunUtc; if (enabledModified) { task.Enabled = current.Enabled; } if (task.NextRunUtc.HasValue && cronModified) { // reschedule task task.NextRunUtc = GetNextSchedule(task); } } finally { _taskRepository.AutoCommitEnabled = autoCommit; } } while (saveFailed); }
internal TaskThread(ScheduleTask scheduleTask) { this._jobs = new Dictionary<string, Job>(); this._seconds = scheduleTask.Seconds; this._isRunning = false; }
public virtual void SetupModel(FeedFroogleModel model, ScheduleTask task = null) { var stores = _storeService.GetAllStores().ToList(); model.AvailableCurrencies = Helper.AvailableCurrencies(); model.AvailableGoogleCategories = GetTaxonomyList(); model.GeneratedFiles = Helper.FeedFiles(stores); model.Helper = Helper; model.AvailableStores = new List<SelectListItem>(); model.AvailableStores.Add(new SelectListItem() { Text = Helper.Resource("Admin.Common.All"), Value = "0" }); model.AvailableStores.AddRange(_storeService.GetAllStores().ToSelectListItems()); if (task != null) { model.GenerateStaticFileEachMinutes = task.Seconds / 60; model.TaskEnabled = task.Enabled; } }
private bool IsTaskVisible(ScheduleTask task) { if (task.IsHidden) return false; var type = Type.GetType(task.Type); if (type != null) { return PluginManager.IsActivePluginAssembly(type.Assembly); } return false; }
public virtual ExportProfile InsertExportProfile( string providerSystemName, string name, string fileExtension, ExportFeatures features, bool isSystemProfile = false, string profileSystemName = null, int cloneFromProfileId = 0) { Guard.ArgumentNotEmpty(() => providerSystemName); var profileCount = _exportProfileRepository.Table.Count(x => x.ProviderSystemName == providerSystemName); if (name.IsEmpty()) name = providerSystemName; if (!isSystemProfile) name = string.Concat(_localizationService.GetResource("Common.My"), " ", name); name = string.Concat(name, " ", profileCount + 1); var cloneProfile = GetExportProfileById(cloneFromProfileId); ScheduleTask task = null; ExportProfile profile = null; if (cloneProfile == null) { task = new ScheduleTask { CronExpression = "0 */6 * * *", // every six hours Type = typeof(DataExportTask).AssemblyQualifiedNameWithoutVersion(), Enabled = false, StopOnError = false, IsHidden = true }; } else { task = cloneProfile.ScheduleTask.Clone(); task.LastEndUtc = task.LastStartUtc = task.LastSuccessUtc = null; } task.Name = string.Concat(name, " Task"); _scheduleTaskService.InsertTask(task); if (cloneProfile == null) { profile = new ExportProfile { FileNamePattern = _defaultFileNamePattern }; if (isSystemProfile) { profile.Enabled = true; profile.PerStore = false; profile.CreateZipArchive = false; profile.Cleanup = false; } else { // what we do here is to preset typical settings for feed creation // but on the other hand they may be untypical for generic data export\exchange var projection = new ExportProjection { RemoveCriticalCharacters = true, CriticalCharacters = "¼,½,¾", PriceType = PriceDisplayType.PreSelectedPrice, NoGroupedProducts = (features.HasFlag(ExportFeatures.CanOmitGroupedProducts) ? true : false), DescriptionMerging = ExportDescriptionMerging.Description }; var filter = new ExportFilter { IsPublished = true }; profile.Projection = XmlHelper.Serialize<ExportProjection>(projection); profile.Filtering = XmlHelper.Serialize<ExportFilter>(filter); } } else { profile = cloneProfile.Clone(); } profile.IsSystemProfile = isSystemProfile; profile.Name = name; profile.ProviderSystemName = providerSystemName; profile.SchedulingTaskId = task.Id; var cleanedSystemName = providerSystemName .Replace("Exports.", "") .Replace("Feeds.", "") .Replace("/", "") .Replace("-", ""); var folderName = SeoHelper.GetSeName(cleanedSystemName, true, false) .ToValidPath() .Truncate(_dataExchangeSettings.MaxFileNameLength); profile.FolderName = "~/App_Data/ExportProfiles/" + FileSystemHelper.CreateNonExistingDirectoryName(CommonHelper.MapPath("~/App_Data/ExportProfiles"), folderName); if (profileSystemName.IsEmpty() && isSystemProfile) profile.SystemName = cleanedSystemName; else profile.SystemName = profileSystemName; _exportProfileRepository.Insert(profile); task.Alias = profile.Id.ToString(); _scheduleTaskService.UpdateTask(task); if (fileExtension.HasValue() && !isSystemProfile) { if (cloneProfile == null) { if (features.HasFlag(ExportFeatures.CreatesInitialPublicDeployment)) { var subFolder = FileSystemHelper.CreateNonExistingDirectoryName(CommonHelper.MapPath("~/" + DataExporter.PublicFolder), folderName); profile.Deployments.Add(new ExportDeployment { ProfileId = profile.Id, Enabled = true, DeploymentType = ExportDeploymentType.PublicFolder, Name = profile.Name, SubFolder = subFolder }); UpdateExportProfile(profile); } } else { foreach (var deployment in cloneProfile.Deployments) { profile.Deployments.Add(deployment.Clone()); } UpdateExportProfile(profile); } } _eventPublisher.EntityInserted(profile); return profile; }
protected ScheduleTaskModel PrepareScheduleTaskModel(ScheduleTask task) { var now = DateTime.UtcNow; TimeSpan? dueIn = null; if (task.NextRunUtc.HasValue) { dueIn = task.NextRunUtc.Value - now; } var nextRunPretty = ""; bool isOverdue = false; if (dueIn.HasValue) { if (dueIn.Value.TotalSeconds > 0) { nextRunPretty = dueIn.Value.Prettify(); } else { nextRunPretty = T("Common.Waiting") + "..."; isOverdue = true; } } var isRunning = task.IsRunning; var lastStartOn = task.LastStartUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastStartUtc.Value, DateTimeKind.Utc) : (DateTime?)null; var lastEndOn = task.LastEndUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastEndUtc.Value, DateTimeKind.Utc) : (DateTime?)null; var lastSuccessOn = task.LastSuccessUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.LastSuccessUtc.Value, DateTimeKind.Utc) : (DateTime?)null; var nextRunOn = task.NextRunUtc.HasValue ? _dateTimeHelper.ConvertToUserTime(task.NextRunUtc.Value, DateTimeKind.Utc) : (DateTime?)null; var model = new ScheduleTaskModel { Id = task.Id, Name = task.Name, CronExpression = task.CronExpression, CronDescription = CronExpression.GetFriendlyDescription(task.CronExpression), Enabled = task.Enabled, StopOnError = task.StopOnError, LastStart = lastStartOn, LastStartPretty = task.LastStartUtc.HasValue ? task.LastStartUtc.Value.RelativeFormat(true, "f") : "", LastEnd = lastEndOn, LastEndPretty = lastEndOn.HasValue ? lastEndOn.Value.ToString("G") : "", LastSuccess = lastSuccessOn, LastSuccessPretty = lastSuccessOn.HasValue ? lastSuccessOn.Value.ToString("G") : "", NextRun = nextRunOn, NextRunPretty = nextRunPretty, LastError = task.LastError.EmptyNull(), IsRunning = isRunning, CancelUrl = Url.Action("CancelJob", new { id = task.Id }), ExecuteUrl = Url.Action("RunJob", new { id = task.Id }), EditUrl = Url.Action("Edit", new { id = task.Id }), ProgressPercent = task.ProgressPercent, ProgressMessage = task.ProgressMessage, IsOverdue = isOverdue, Duration = "" }; var span = TimeSpan.Zero; if (task.LastStartUtc.HasValue) { span = model.IsRunning ? now - task.LastStartUtc.Value : task.LastEndUtc.Value - task.LastStartUtc.Value; if (span > TimeSpan.Zero) { model.Duration = span.ToString("g"); } } return model; }
public virtual ImportProfile InsertImportProfile(string fileName, string name, ImportEntityType entityType) { Guard.ArgumentNotEmpty(() => fileName); if (name.IsEmpty()) name = GetNewProfileName(entityType); var task = new ScheduleTask { CronExpression = "0 */24 * * *", Type = typeof(DataImportTask).AssemblyQualifiedNameWithoutVersion(), Enabled = false, StopOnError = false, IsHidden = true }; task.Name = string.Concat(name, " Task"); _scheduleTaskService.InsertTask(task); var profile = new ImportProfile { Name = name, EntityType = entityType, Enabled = true, SchedulingTaskId = task.Id }; if (Path.GetExtension(fileName).IsCaseInsensitiveEqual(".xlsx")) profile.FileType = ImportFileType.XLSX; else profile.FileType = ImportFileType.CSV; string[] keyFieldNames = null; switch (entityType) { case ImportEntityType.Product: keyFieldNames = ProductImporter.DefaultKeyFields; break; case ImportEntityType.Category: keyFieldNames = CategoryImporter.DefaultKeyFields; break; case ImportEntityType.Customer: keyFieldNames = CustomerImporter.DefaultKeyFields; break; case ImportEntityType.NewsLetterSubscription: keyFieldNames = NewsLetterSubscriptionImporter.DefaultKeyFields; break; } profile.KeyFieldNames = string.Join(",", keyFieldNames); profile.FolderName = SeoHelper.GetSeName(name, true, false) .ToValidPath() .Truncate(_dataExchangeSettings.MaxFileNameLength); profile.FolderName = FileSystemHelper.CreateNonExistingDirectoryName(CommonHelper.MapPath("~/App_Data/ImportProfiles"), profile.FolderName); _importProfileRepository.Insert(profile); task.Alias = profile.Id.ToString(); _scheduleTaskService.UpdateTask(task); _eventPublisher.EntityInserted(profile); return profile; }
public virtual DateTime? GetNextSchedule(ScheduleTask task) { if (task.Enabled) { try { var baseTime = _dateTimeHelper.ConvertToUserTime(DateTime.UtcNow); var next = CronExpression.GetNextSchedule(task.CronExpression, baseTime); return _dateTimeHelper.ConvertToUtcTime(next); } catch { } } return null; }
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 = _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 }; 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); } }
private string GetTaskMessage(ScheduleTask task, string resourceKey) { string message = null; var taskClassName = task.Type .SplitSafe(",") .SafeGet(0) .SplitSafe(".") .LastOrDefault(); if (taskClassName.HasValue()) { message = _localizationService.GetResource(string.Concat(resourceKey, ".", taskClassName), returnEmptyIfNotFound: true); } if (message.IsEmpty()) { message = T(resourceKey); } return message; }