diff --git a/code/Common/Configuration/DTOs/QueueCleaner/QueueCleanerConfigDto.cs b/code/Common/Configuration/DTOs/QueueCleaner/QueueCleanerConfigDto.cs
index 21b2fe2c..173cef31 100644
--- a/code/Common/Configuration/DTOs/QueueCleaner/QueueCleanerConfigDto.cs
+++ b/code/Common/Configuration/DTOs/QueueCleaner/QueueCleanerConfigDto.cs
@@ -22,11 +22,6 @@ public class QueueCleanerConfigDto
///
public bool RunSequentially { get; set; }
- ///
- /// Path to ignored downloads file
- ///
- public string IgnoredDownloadsPath { get; set; } = string.Empty;
-
///
/// Maximum number of strikes for failed imports
///
diff --git a/code/Common/Configuration/QueueCleaner/QueueCleanerConfig.cs b/code/Common/Configuration/QueueCleaner/QueueCleanerConfig.cs
index bd1b2ad5..ec71abd7 100644
--- a/code/Common/Configuration/QueueCleaner/QueueCleanerConfig.cs
+++ b/code/Common/Configuration/QueueCleaner/QueueCleanerConfig.cs
@@ -12,6 +12,7 @@ public sealed record QueueCleanerConfig : IJobConfig
public string CronExpression { get; init; } = "0 0/5 * * * ?";
+ // TODO
public string IgnoredDownloadsPath { get; init; } = string.Empty;
public FailedImportConfig FailedImport { get; init; } = new();
diff --git a/code/Executable/Controllers/ConfigurationController.cs b/code/Executable/Controllers/ConfigurationController.cs
index 46d42bb3..de0ca4a0 100644
--- a/code/Executable/Controllers/ConfigurationController.cs
+++ b/code/Executable/Controllers/ConfigurationController.cs
@@ -158,22 +158,24 @@ public class ConfigurationController : ControllerBase
if (!string.IsNullOrEmpty(config.CronExpression))
{
// If the job is enabled, update its schedule with the configured cron expression
- _logger.LogInformation("{JobName} is enabled, updating job schedule with cron expression: {CronExpression}",
+ _logger.LogInformation("{name} is enabled, updating job schedule with cron expression: {CronExpression}",
jobType.ToString(), config.CronExpression);
+ _logger.LogCritical("This is a random test log");
+
// Create a Quartz job schedule with the cron expression
await _jobManagementService.StartJob(jobType, null, config.CronExpression);
}
else
{
- _logger.LogWarning("{JobName} is enabled, but no cron expression was found in the configuration", jobType.ToString());
+ _logger.LogWarning("{name} is enabled, but no cron expression was found in the configuration", jobType.ToString());
}
return;
}
// If the job is disabled, stop it
- _logger.LogInformation("{JobName} is disabled, stopping the job", jobType.ToString());
+ _logger.LogInformation("{name} is disabled, stopping the job", jobType.ToString());
await _jobManagementService.StopJob(jobType);
}
diff --git a/code/Executable/Jobs/BackgroundJobManager.cs b/code/Executable/Jobs/BackgroundJobManager.cs
index 93e5c437..ce079552 100644
--- a/code/Executable/Jobs/BackgroundJobManager.cs
+++ b/code/Executable/Jobs/BackgroundJobManager.cs
@@ -188,7 +188,7 @@ public class BackgroundJobManager : IHostedService
await _scheduler.ScheduleJob(trigger, cancellationToken);
await _scheduler.ScheduleJob(startupTrigger, cancellationToken);
- _logger.LogInformation("Added job {JobName} with cron expression {CronExpression}",
+ _logger.LogInformation("Added job {name} with cron expression {CronExpression}",
typeName, cronExpression);
}
@@ -215,6 +215,6 @@ public class BackgroundJobManager : IHostedService
// Add job to scheduler
await _scheduler.AddJob(jobDetail, true, cancellationToken);
- _logger.LogInformation("Added job {JobName} without trigger (will be chained)", typeName);
+ _logger.LogInformation("Added job {name} without trigger (will be chained)", typeName);
}
}
diff --git a/code/Infrastructure/Services/JobManagementService.cs b/code/Infrastructure/Services/JobManagementService.cs
index 757f3d8b..0394d951 100644
--- a/code/Infrastructure/Services/JobManagementService.cs
+++ b/code/Infrastructure/Services/JobManagementService.cs
@@ -34,7 +34,7 @@ public class JobManagementService : IJobManagementService
// Check if job exists
if (!await scheduler.CheckExists(jobKey))
{
- _logger.LogError("Job {jobName} does not exist", jobName);
+ _logger.LogError("Job {name} does not exist", jobName);
return false;
}
@@ -86,7 +86,7 @@ public class JobManagementService : IJobManagementService
// Resume the job if it's paused
await scheduler.ResumeJob(jobKey);
- _logger.LogInformation("Job {jobName} started successfully", jobName);
+ _logger.LogInformation("Job {name} started successfully", jobName);
return true;
}
catch (Exception ex)
@@ -106,7 +106,7 @@ public class JobManagementService : IJobManagementService
if (!await scheduler.CheckExists(jobKey))
{
- _logger.LogError("Job {jobName} does not exist", jobName);
+ _logger.LogError("Job {name} does not exist", jobName);
return false;
}
@@ -117,7 +117,7 @@ public class JobManagementService : IJobManagementService
await scheduler.UnscheduleJob(trigger.Key);
}
- _logger.LogInformation("Job {jobName} stopped successfully", jobName);
+ _logger.LogInformation("Job {name} stopped successfully", jobName);
return true;
}
catch (Exception ex)
@@ -137,12 +137,12 @@ public class JobManagementService : IJobManagementService
if (!await scheduler.CheckExists(jobKey))
{
- _logger.LogError("Job {jobName} does not exist", jobName);
+ _logger.LogError("Job {name} does not exist", jobName);
return false;
}
await scheduler.PauseJob(jobKey);
- _logger.LogInformation("Job {jobName} paused successfully", jobName);
+ _logger.LogInformation("Job {name} paused successfully", jobName);
return true;
}
catch (Exception ex)
@@ -162,17 +162,17 @@ public class JobManagementService : IJobManagementService
if (!await scheduler.CheckExists(jobKey))
{
- _logger.LogError("Job {jobName} does not exist", jobName);
+ _logger.LogError("Job {name} does not exist", jobName);
return false;
}
await scheduler.ResumeJob(jobKey);
- _logger.LogInformation("Job {jobName} resumed successfully", jobName);
+ _logger.LogInformation("Job {name} resumed successfully", jobName);
return true;
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error resuming job {jobName}", jobName);
+ _logger.LogError(ex, "Error resuming job {name}", jobName);
return false;
}
}
@@ -247,7 +247,7 @@ public class JobManagementService : IJobManagementService
if (!await scheduler.CheckExists(jobKey))
{
- _logger.LogError("Job {jobName} does not exist", jobName);
+ _logger.LogError("Job {name} does not exist", jobName);
return new JobInfo { Name = jobName, Status = "Not Found" };
}
@@ -290,7 +290,7 @@ public class JobManagementService : IJobManagementService
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error getting job {jobName}", jobName);
+ _logger.LogError(ex, "Error getting job {name}", jobName);
return new JobInfo { Name = jobName, Status = "Error" };
}
}
@@ -310,7 +310,7 @@ public class JobManagementService : IJobManagementService
if (!await scheduler.CheckExists(jobKey))
{
- _logger.LogError("Job {jobName} does not exist", jobName);
+ _logger.LogError("Job {name} does not exist", jobName);
return false;
}
@@ -332,12 +332,12 @@ public class JobManagementService : IJobManagementService
await scheduler.ScheduleJob(newTrigger);
}
- _logger.LogInformation("Job {jobName} schedule updated successfully to {cronExpression}", jobName, cronExpression);
+ _logger.LogInformation("Job {name} schedule updated successfully to {cronExpression}", jobName, cronExpression);
return true;
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error updating job {jobName} schedule", jobName);
+ _logger.LogError(ex, "Error updating job {name} schedule", jobName);
return false;
}
}
diff --git a/code/Infrastructure/Verticals/ContentBlocker/ContentBlocker.cs b/code/Infrastructure/Verticals/ContentBlocker/ContentBlocker.cs
deleted file mode 100644
index 8f0d35f7..00000000
--- a/code/Infrastructure/Verticals/ContentBlocker/ContentBlocker.cs
+++ /dev/null
@@ -1,187 +0,0 @@
-// using System.Collections.Concurrent;
-// using System.Text.RegularExpressions;
-// using Common.Configuration.Arr;
-// using Common.Configuration.DownloadClient;
-// using Common.Configuration.QueueCleaner;
-// using Data.Enums;
-// using Data.Models.Arr.Queue;
-// using Infrastructure.Configuration;
-// using Infrastructure.Helpers;
-// using Infrastructure.Services;
-// using Infrastructure.Verticals.Arr;
-// using Infrastructure.Verticals.Arr.Interfaces;
-// using Infrastructure.Verticals.DownloadClient;
-// using Infrastructure.Verticals.Jobs;
-// using MassTransit;
-// using Microsoft.Extensions.Caching.Memory;
-// using Microsoft.Extensions.Logging;
-// using LogContext = Serilog.Context.LogContext;
-//
-// namespace Infrastructure.Verticals.ContentBlocker;
-//
-// public sealed class ContentBlocker : GenericHandler
-// {
-// private readonly ContentBlockerConfig _config;
-// private readonly BlocklistProvider _blocklistProvider;
-// private readonly IIgnoredDownloadsService _ignoredDownloadsService;
-//
-// public ContentBlocker(
-// ILogger logger,
-// IConfigManager configManager,
-// IMemoryCache cache,
-// IBus messageBus,
-// ArrClientFactory arrClientFactory,
-// ArrQueueIterator arrArrQueueIterator,
-// BlocklistProvider blocklistProvider,
-// IIgnoredDownloadsService ignoredDownloadsService,
-// DownloadServiceFactory downloadServiceFactory
-// ) : base(
-// logger, cache, messageBus,
-// arrClientFactory, arrArrQueueIterator, downloadServiceFactory
-// )
-// {
-// _blocklistProvider = blocklistProvider;
-// _ignoredDownloadsService = ignoredDownloadsService;
-//
-// _config = configManager.GetConfiguration();
-// _downloadClientConfig = configManager.GetConfiguration();
-// _sonarrConfig = configManager.GetConfiguration();
-// _radarrConfig = configManager.GetConfiguration();
-// _lidarrConfig = configManager.GetConfiguration();
-// }
-//
-// public override async Task ExecuteAsync()
-// {
-// if (_downloadClientConfig.Clients.Count is 0)
-// {
-// _logger.LogWarning("No download clients configured");
-// return;
-// }
-//
-// bool blocklistIsConfigured = _config.Sonarr.Enabled && !string.IsNullOrEmpty(_config.Sonarr.Path) ||
-// _config.Radarr.Enabled && !string.IsNullOrEmpty(_config.Radarr.Path) ||
-// _config.Lidarr.Enabled && !string.IsNullOrEmpty(_config.Lidarr.Path);
-//
-// if (!blocklistIsConfigured)
-// {
-// _logger.LogWarning("no blocklist is configured");
-// return;
-// }
-//
-// await _blocklistProvider.LoadBlocklistsAsync();
-// await base.ExecuteAsync();
-// }
-//
-// protected override async Task ProcessInstanceAsync(ArrInstance instance, InstanceType instanceType, ArrConfig config)
-// {
-// IReadOnlyList ignoredDownloads = await _ignoredDownloadsService.GetIgnoredDownloadsAsync();
-//
-// using var _ = LogContext.PushProperty(LogProperties.Category, instanceType.ToString());
-//
-// IArrClient arrClient = _arrClientFactory.GetClient(instanceType);
-// BlocklistType blocklistType = _blocklistProvider.GetBlocklistType(instanceType);
-// ConcurrentBag patterns = _blocklistProvider.GetPatterns(instanceType);
-// ConcurrentBag regexes = _blocklistProvider.GetRegexes(instanceType);
-//
-// await _arrArrQueueIterator.Iterate(arrClient, instance, async items =>
-// {
-// var groups = items
-// .GroupBy(x => x.DownloadId)
-// .ToList();
-//
-// foreach (var group in groups)
-// {
-// if (group.Any(x => !arrClient.IsRecordValid(x)))
-// {
-// continue;
-// }
-//
-// QueueRecord record = group.First();
-//
-// if (record.Protocol is not "torrent")
-// {
-// continue;
-// }
-//
-// if (string.IsNullOrEmpty(record.DownloadId))
-// {
-// _logger.LogDebug("skip | download id is null for {title}", record.Title);
-// continue;
-// }
-//
-// if (ignoredDownloads.Contains(record.DownloadId, StringComparer.InvariantCultureIgnoreCase))
-// {
-// _logger.LogInformation("skip | {title} | ignored", record.Title);
-// continue;
-// }
-//
-// _logger.LogTrace("processing | {name}", record.Title);
-//
-// string downloadRemovalKey = CacheKeys.DownloadMarkedForRemoval(record.DownloadId, instance.Url);
-//
-// if (_cache.TryGetValue(downloadRemovalKey, out bool _))
-// {
-// _logger.LogDebug("skip | already marked for removal | {title}", record.Title);
-// continue;
-// }
-//
-// _logger.LogDebug("searching unwanted files for {title}", record.Title);
-// bool found = false;
-//
-// foreach (var downloadService in _downloadServices)
-// {
-// try
-// {
-// BlockFilesResult result = await downloadService
-// .BlockUnwantedFilesAsync(record.DownloadId, blocklistType, patterns, regexes, ignoredDownloads);
-//
-// if (!result.Found)
-// {
-// continue;
-// }
-//
-// found = true;
-//
-// if (!result.ShouldRemove)
-// {
-// break;
-// }
-//
-// _logger.LogDebug("all files are marked as unwanted | {hash}", record.Title);
-//
-// bool removeFromClient = true;
-//
-// if (result.IsPrivate && !_config.DeletePrivate)
-// {
-// removeFromClient = false;
-// }
-//
-// await PublishQueueItemRemoveRequest(
-// downloadRemovalKey,
-// instanceType,
-// instance,
-// record,
-// group.Count() > 1,
-// removeFromClient,
-// DeleteReason.AllFilesBlocked
-// );
-//
-// break;
-// }
-// catch (Exception ex)
-// {
-// _logger.LogError(
-// ex,
-// "Error blocking unwanted files for {hash} with download client",
-// record.DownloadId);
-// }
-// }
-//
-// if (!found)
-// {
-// _logger.LogWarning("skip | download not found {title}", record.Title);
-// }
-// }
-// });
-// }
-// }
\ No newline at end of file
diff --git a/code/UI/src/app/core/services/configuration.service.ts b/code/UI/src/app/core/services/configuration.service.ts
index 532a6a6f..fe5091f6 100644
--- a/code/UI/src/app/core/services/configuration.service.ts
+++ b/code/UI/src/app/core/services/configuration.service.ts
@@ -1,11 +1,11 @@
-import { HttpClient } from '@angular/common/http';
-import { Injectable, inject } from '@angular/core';
-import { Observable, catchError, map, throwError } from 'rxjs';
-import { environment } from '../../../environments/environment';
-import { JobSchedule, QueueCleanerConfig, ScheduleUnit } from '../../shared/models/queue-cleaner-config.model';
+import { HttpClient } from "@angular/common/http";
+import { Injectable, inject } from "@angular/core";
+import { Observable, catchError, map, throwError } from "rxjs";
+import { environment } from "../../../environments/environment";
+import { JobSchedule, QueueCleanerConfig, ScheduleUnit } from "../../shared/models/queue-cleaner-config.model";
@Injectable({
- providedIn: 'root'
+ providedIn: "root",
})
export class ConfigurationService {
private readonly apiUrl = environment.apiUrl;
@@ -15,149 +15,29 @@ export class ConfigurationService {
* Get queue cleaner configuration
*/
getQueueCleanerConfig(): Observable {
- return this.http.get(`${this.apiUrl}/api/configuration/queue_cleaner`)
- .pipe(
- map(response => this.transformQueueCleanerResponse(response)),
- catchError(error => {
- console.error('Error fetching queue cleaner config:', error);
- return throwError(() => new Error('Failed to load queue cleaner configuration'));
- })
- );
+ return this.http.get(`${this.apiUrl}/api/configuration/queue_cleaner`).pipe(
+ map((response) => {
+ response.jobSchedule = this.tryExtractJobScheduleFromCron(response.cronExpression);
+ return response;
+ }),
+ catchError((error) => {
+ console.error("Error fetching queue cleaner config:", error);
+ return throwError(() => new Error("Failed to load queue cleaner configuration"));
+ })
+ );
}
/**
* Update queue cleaner configuration
*/
- updateQueueCleanerConfig(config: QueueCleanerConfig): Observable {
- // Create a copy to avoid modifying the original
- const configToSend = this.prepareQueueCleanerConfigForSending({ ...config });
-
- return this.http.put(`${this.apiUrl}/api/configuration/queue_cleaner`, configToSend)
- .pipe(
- catchError(error => {
- console.error('Error updating queue cleaner config:', error);
- return throwError(() => new Error(error.error?.error || 'Failed to update queue cleaner configuration'));
- })
- );
- }
-
- /**
- * Transform the API response to our frontend model
- * Convert property names from PascalCase to camelCase
- */
- private transformQueueCleanerResponse(response: any): QueueCleanerConfig {
- const config: QueueCleanerConfig = {
- enabled: response.Enabled,
- cronExpression: response.CronExpression,
- runSequentially: response.RunSequentially,
- ignoredDownloadsPath: response.IgnoredDownloadsPath || '',
-
- // Create the nested configuration objects
- failedImport: {
- maxStrikes: response.FailedImportMaxStrikes,
- ignorePrivate: response.FailedImportIgnorePrivate,
- deletePrivate: response.FailedImportDeletePrivate,
- ignorePatterns: response.FailedImportIgnorePatterns || []
- },
-
- stalled: {
- maxStrikes: response.StalledMaxStrikes,
- resetStrikesOnProgress: response.StalledResetStrikesOnProgress,
- ignorePrivate: response.StalledIgnorePrivate,
- deletePrivate: response.StalledDeletePrivate,
- downloadingMetadataMaxStrikes: response.DownloadingMetadataMaxStrikes
- },
-
- slow: {
- maxStrikes: response.SlowMaxStrikes,
- resetStrikesOnProgress: response.SlowResetStrikesOnProgress,
- ignorePrivate: response.SlowIgnorePrivate,
- deletePrivate: response.SlowDeletePrivate,
- minSpeed: response.SlowMinSpeed || '',
- maxTime: response.SlowMaxTime,
- ignoreAboveSize: response.SlowIgnoreAboveSize || ''
- },
-
- contentBlocker: {
- enabled: false, // Default values since they're not in the DTO
- ignorePrivate: false,
- deletePrivate: false,
- sonarrBlocklist: { path: '', type: 'Blacklist' as any },
- radarrBlocklist: { path: '', type: 'Blacklist' as any },
- lidarrBlocklist: { path: '', type: 'Blacklist' as any }
- },
-
- // Keep legacy flat properties for backward compatibility
- failedImportMaxStrikes: response.FailedImportMaxStrikes,
- failedImportIgnorePrivate: response.FailedImportIgnorePrivate,
- failedImportDeletePrivate: response.FailedImportDeletePrivate,
- failedImportIgnorePatterns: response.FailedImportIgnorePatterns || [],
- stalledMaxStrikes: response.StalledMaxStrikes,
- stalledResetStrikesOnProgress: response.StalledResetStrikesOnProgress,
- stalledIgnorePrivate: response.StalledIgnorePrivate,
- stalledDeletePrivate: response.StalledDeletePrivate,
- downloadingMetadataMaxStrikes: response.DownloadingMetadataMaxStrikes,
- slowMaxStrikes: response.SlowMaxStrikes,
- slowResetStrikesOnProgress: response.SlowResetStrikesOnProgress,
- slowIgnorePrivate: response.SlowIgnorePrivate,
- slowDeletePrivate: response.SlowDeletePrivate,
- slowMinSpeed: response.SlowMinSpeed || '',
- slowMaxTime: response.SlowMaxTime,
- slowIgnoreAboveSize: response.SlowIgnoreAboveSize || '',
- };
-
- // Attempt to extract job schedule from cron expression
- // This is just UI sugar, not sent back to API
- config.jobSchedule = this.tryExtractJobScheduleFromCron(config.cronExpression);
-
- return config;
- }
-
- /**
- * Prepare configuration object for sending to API
- * Convert property names from camelCase to PascalCase
- */
- private prepareQueueCleanerConfigForSending(config: QueueCleanerConfig): any {
- // If we have a job schedule, update the cron expression
- if (config.jobSchedule) {
- config.cronExpression = this.convertJobScheduleToCron(config.jobSchedule);
- }
-
- // Remove UI-only properties
- const { jobSchedule, ...rest } = config;
-
- // Convert to PascalCase for backend
- // Use nested objects if available, fall back to flat properties if needed
- return {
- Enabled: rest.enabled,
- CronExpression: rest.cronExpression,
- RunSequentially: rest.runSequentially,
- IgnoredDownloadsPath: rest.ignoredDownloadsPath,
-
- // Failed Import settings
- FailedImportMaxStrikes: rest.failedImport?.maxStrikes ?? rest.failedImportMaxStrikes,
- FailedImportIgnorePrivate: rest.failedImport?.ignorePrivate ?? rest.failedImportIgnorePrivate,
- FailedImportDeletePrivate: rest.failedImport?.deletePrivate ?? rest.failedImportDeletePrivate,
- FailedImportIgnorePatterns: rest.failedImport?.ignorePatterns ?? rest.failedImportIgnorePatterns,
-
- // Stalled settings
- StalledMaxStrikes: rest.stalled?.maxStrikes ?? rest.stalledMaxStrikes,
- StalledResetStrikesOnProgress: rest.stalled?.resetStrikesOnProgress ?? rest.stalledResetStrikesOnProgress,
- StalledIgnorePrivate: rest.stalled?.ignorePrivate ?? rest.stalledIgnorePrivate,
- StalledDeletePrivate: rest.stalled?.deletePrivate ?? rest.stalledDeletePrivate,
-
- // Downloading Metadata settings
- DownloadingMetadataMaxStrikes: rest.stalled?.downloadingMetadataMaxStrikes ?? rest.downloadingMetadataMaxStrikes,
-
- // Slow Download settings
- SlowMaxStrikes: rest.slow?.maxStrikes ?? rest.slowMaxStrikes,
- SlowResetStrikesOnProgress: rest.slow?.resetStrikesOnProgress ?? rest.slowResetStrikesOnProgress,
- SlowIgnorePrivate: rest.slow?.ignorePrivate ?? rest.slowIgnorePrivate,
- SlowDeletePrivate: rest.slow?.deletePrivate ?? rest.slowDeletePrivate,
- SlowMinSpeed: rest.slow?.minSpeed ?? rest.slowMinSpeed,
- SlowMaxTime: rest.slow?.maxTime ?? rest.slowMaxTime,
- SlowIgnoreAboveSize: rest.slow?.ignoreAboveSize ?? rest.slowIgnoreAboveSize,
- };
+ updateQueueCleanerConfig(config: QueueCleanerConfig): Observable {
+ config.cronExpression = this.convertJobScheduleToCron(config.jobSchedule!);
+ return this.http.put(`${this.apiUrl}/api/configuration/queue_cleaner`, config).pipe(
+ catchError((error) => {
+ console.error("Error updating queue cleaner config:", error);
+ return throwError(() => new Error(error.error?.error || "Failed to update queue cleaner configuration"));
+ })
+ );
}
/**
@@ -170,37 +50,37 @@ export class ConfigurationService {
// Minutes: 0 */n * ? * * *
// Hours: 0 0 */n ? * * *
try {
- const parts = cronExpression.split(' ');
-
+ const parts = cronExpression.split(" ");
+
if (parts.length !== 7) return undefined;
-
+
// Every n seconds
- if (parts[0].startsWith('*/') && parts[1] === '*') {
+ if (parts[0].startsWith("*/") && parts[1] === "*") {
const seconds = parseInt(parts[0].substring(2));
if (!isNaN(seconds) && seconds > 0 && seconds < 60) {
return { every: seconds, type: ScheduleUnit.Seconds };
}
}
-
+
// Every n minutes
- if (parts[0] === '0' && parts[1].startsWith('*/')) {
+ if (parts[0] === "0" && parts[1].startsWith("*/")) {
const minutes = parseInt(parts[1].substring(2));
if (!isNaN(minutes) && minutes > 0 && minutes < 60) {
return { every: minutes, type: ScheduleUnit.Minutes };
}
}
-
+
// Every n hours
- if (parts[0] === '0' && parts[1] === '0' && parts[2].startsWith('*/')) {
+ if (parts[0] === "0" && parts[1] === "0" && parts[2].startsWith("*/")) {
const hours = parseInt(parts[2].substring(2));
if (!isNaN(hours) && hours > 0 && hours < 24) {
return { every: hours, type: ScheduleUnit.Hours };
}
}
} catch (e) {
- console.warn('Could not parse cron expression:', cronExpression);
+ console.warn("Could not parse cron expression:", cronExpression);
}
-
+
return undefined;
}
@@ -209,7 +89,7 @@ export class ConfigurationService {
*/
private convertJobScheduleToCron(schedule: JobSchedule): string {
if (!schedule || schedule.every <= 0) {
- return '0 0/5 * * * ?'; // Default: every 5 minutes
+ return "0 0/5 * * * ?"; // Default: every 5 minutes
}
switch (schedule.type) {
@@ -218,13 +98,13 @@ export class ConfigurationService {
return `*/${schedule.every} * * ? * * *`;
}
break;
-
+
case ScheduleUnit.Minutes:
if (schedule.every < 60) {
return `0 */${schedule.every} * ? * * *`;
}
break;
-
+
case ScheduleUnit.Hours:
if (schedule.every < 24) {
return `0 0 */${schedule.every} ? * * *`;
@@ -233,6 +113,6 @@ export class ConfigurationService {
}
// Fallback to default
- return '0 0/5 * * * ?';
+ return "0 0/5 * * * ?";
}
}