From 7e7eee7299c556afeaaa8fe8556029ae3e9dd91b Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 23 Dec 2022 13:27:30 +0100 Subject: [PATCH] 23-12-2022 --- ECM.JobRunner.Web/Data/HelperService.cs | 10 +++- .../Data/ImportProfileService.cs | 14 ++++- ECM.JobRunner.Web/ECM.JobRunner.Web.csproj | 3 ++ ECM.JobRunner.Web/Pages/History.razor | 2 +- .../Pages/ImportProfile/ProfileForm.razor | 26 ++++++++-- .../Pages/ImportProfile/ShowProfile.razor | 26 +++++++++- .../Scheduler/JobScheduler.vb | 51 ++++++++++++------- .../Scheduler/Jobs/BaseJob.vb | 11 ++-- .../Scheduler/Jobs/FileImportJob.vb | 20 +++++++- ECM.JobRunner.Windows/WCF/JobRunner.vb | 3 +- 10 files changed, 130 insertions(+), 36 deletions(-) diff --git a/ECM.JobRunner.Web/Data/HelperService.cs b/ECM.JobRunner.Web/Data/HelperService.cs index 95b7c32..76517f8 100644 --- a/ECM.JobRunner.Web/Data/HelperService.cs +++ b/ECM.JobRunner.Web/Data/HelperService.cs @@ -1,4 +1,5 @@ using DigitalData.Modules.Logging; +using DigitalData.Modules.Filesystem; using ECM.JobRunner.Common.JobRunnerReference; using System; @@ -8,14 +9,21 @@ namespace ECM.JobRunner.Web.Data { private readonly Logger logger; private readonly IEDMIServiceChannel channel; + private readonly DigitalData.Modules.Filesystem.File fileEx; public event EventHandler? PageTitleChanged; public HelperService(LoggingService Logging, WcfService Wcf) { logger = Logging.LogConfig.GetLogger(); + fileEx = new DigitalData.Modules.Filesystem.File(Logging.LogConfig); channel = Wcf.Channel; } + + public string GetDateDirectory(DateTime date) + { + return fileEx.GetDateString(date); + } public void SetPageTitle(string title) { @@ -61,8 +69,6 @@ namespace ECM.JobRunner.Web.Data waiting = executingItems.Where(i => i.Successful && i.Waiting == true).Count() }; } - - public DateTime GetNextExecutionTime(string pCronExpression) { Quartz.CronExpression expression = new(pCronExpression); diff --git a/ECM.JobRunner.Web/Data/ImportProfileService.cs b/ECM.JobRunner.Web/Data/ImportProfileService.cs index 1c38bf1..185138e 100644 --- a/ECM.JobRunner.Web/Data/ImportProfileService.cs +++ b/ECM.JobRunner.Web/Data/ImportProfileService.cs @@ -56,7 +56,19 @@ namespace ECM.JobRunner.Web.Data return null; } - } + } + + public async Task RunProfile(ImportProfile profile) + { + try + { + await channel.RunJobAsync(new RunJobRunJobRequest() { JobId = profile.JobId }); + } + catch (Exception ex) + { + logger.Error(ex); + } + } public async Task CreateProfile(ImportProfile profile) => await DoUpdateProfile(profile, UpdateProfileUpdateProfileRequest.UpdateProfileAction.Create); diff --git a/ECM.JobRunner.Web/ECM.JobRunner.Web.csproj b/ECM.JobRunner.Web/ECM.JobRunner.Web.csproj index 6908ee2..b1310f2 100644 --- a/ECM.JobRunner.Web/ECM.JobRunner.Web.csproj +++ b/ECM.JobRunner.Web/ECM.JobRunner.Web.csproj @@ -31,6 +31,9 @@ ..\..\DDModules\Database\bin\Debug\DigitalData.Modules.Database.dll + + ..\..\DDModules\Filesystem\bin\Debug\DigitalData.Modules.Filesystem.dll + ..\..\DDModules\Logging\bin\Debug\DigitalData.Modules.Logging.dll diff --git a/ECM.JobRunner.Web/Pages/History.razor b/ECM.JobRunner.Web/Pages/History.razor index 19e1cd5..a1a25b8 100644 --- a/ECM.JobRunner.Web/Pages/History.razor +++ b/ECM.JobRunner.Web/Pages/History.razor @@ -126,7 +126,7 @@ private List? filteredEntries; private int dateFilter = 1; - private bool showWaiting = true; + private bool showWaiting = false; // TODO: implement more filters private bool showSuccessful = true; diff --git a/ECM.JobRunner.Web/Pages/ImportProfile/ProfileForm.razor b/ECM.JobRunner.Web/Pages/ImportProfile/ProfileForm.razor index 1afbaec..1498bc6 100644 --- a/ECM.JobRunner.Web/Pages/ImportProfile/ProfileForm.razor +++ b/ECM.JobRunner.Web/Pages/ImportProfile/ProfileForm.razor @@ -1,7 +1,6 @@ @using ECM.JobRunner.Common.JobRunnerReference; @using ECM.JobRunner.Web.Data; @inject ImportProfileService Import; -@inject HelperService Jobs; @inject WcfService Service; @if (profile == null) @@ -144,9 +143,10 @@ else
Der Windream Objekttyp, dem das Profil zugeordnet wird. Bestimmt u.a., welche Indexe zur Verfügung stehen.
@@ -195,6 +195,24 @@ else return ProfileId == Constants.ENTITY_ID_NEW ? "profiles/import" : $"profiles/import/{ProfileId}"; } + private List GetSubdirectoryDateStrings() + { + return new() + { + new() {prettyName = $"YYYY", exampleValue = $"{DateTime.Now:yyyy}", formatString = "yyyy" }, + new() {prettyName = $"YYYY\\MM", exampleValue = $"{DateTime.Now:yyyy\\\\MM}", formatString = "yyyy\\MM" }, + new() {prettyName = $"YYYY\\MM\\DD", exampleValue = $"{DateTime.Now:yyyy\\\\MM\\\\dd}", formatString = "yyyy\\MM\\dd" } + }; + } + + private class SubdirectoryDateString + { + public string? prettyName; + public string? exampleValue; + public string? formatString; + } + + protected override async Task OnInitializedAsync() { jobTypes = await Service.GetJobTypes(); diff --git a/ECM.JobRunner.Web/Pages/ImportProfile/ShowProfile.razor b/ECM.JobRunner.Web/Pages/ImportProfile/ShowProfile.razor index 6b29430..95f3390 100644 --- a/ECM.JobRunner.Web/Pages/ImportProfile/ShowProfile.razor +++ b/ECM.JobRunner.Web/Pages/ImportProfile/ShowProfile.razor @@ -84,9 +84,21 @@ else Delete +
} @@ -110,6 +122,18 @@ else } } + protected async void RunProfile() + { + if (profile != null) + { + bool confirmed = await JsRuntime.InvokeAsync("confirm", "Are you sure?"); + if (confirmed) + { + await Import.RunProfile(profile); + } + } + } + protected async void DeleteJob() { if (profile != null) diff --git a/ECM.JobRunner.Windows/Scheduler/JobScheduler.vb b/ECM.JobRunner.Windows/Scheduler/JobScheduler.vb index 933858f..ffe52f3 100644 --- a/ECM.JobRunner.Windows/Scheduler/JobScheduler.vb +++ b/ECM.JobRunner.Windows/Scheduler/JobScheduler.vb @@ -1,4 +1,5 @@ Imports System.Collections.Specialized +Imports System.Runtime.InteropServices Imports DigitalData.Modules.Database Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Windream @@ -88,11 +89,20 @@ Namespace Scheduler If oJob IsNot Nothing Then Logger.Info("Scheduling Job [{0}] manually!", oJob.Name) - Await PrepareScheduleJob(oJob) + Await PrepareScheduleJob(oJob, pStartManually:=True) End If End Function - Private Async Function PrepareScheduleJob(pJob As JobDefinition) As Task + Private Async Sub ScheduleJobs() + + Logger.Info("Loading [{0}] Job Definitions..", State.JobDefinitions.Count) + + For Each oJob In State.JobDefinitions + Await PrepareScheduleJob(oJob, pStartManually:=False) + Next + End Sub + + Private Async Function PrepareScheduleJob(pJob As JobDefinition, pStartManually As Boolean) As Task Logger.Debug("Loading Job Definition [{0}]", pJob.Name) Logger.Debug("Job Type is [{0}]", pJob.Type.Name) @@ -110,15 +120,6 @@ Namespace Scheduler End Select End Function - Private Async Sub ScheduleJobs() - - Logger.Info("Loading [{0}] Job Definitions..", State.JobDefinitions.Count) - - For Each oJob In State.JobDefinitions - Await PrepareScheduleJob(oJob) - Next - End Sub - Private Function BuildJobConfig(Of TJob As IJob)(pJob As JobDefinition) As JobConfig Return New JobConfig With { .Name = pJob.Name, @@ -131,8 +132,11 @@ Namespace Scheduler } End Function - Private Async Function ScheduleJob(Of T As IJob)(pJobConfig As JobConfig) As Task - If Await Scheduler.CheckExists(New JobKey(GetJobName(pJobConfig))) Then + Private Async Function ScheduleJob(Of T As IJob)(pJobConfig As JobConfig, pStartManually As Boolean) As Task + If pStartManually = True Then + Logger.Debug("Manual run, scheduling..") + Await DoScheduleJobWithoutDelay(Of T)(pJobConfig) + ElseIf Await Scheduler.CheckExists(New JobKey(GetJobName(pJobConfig))) Then Logger.Debug("Job already exists, rescheduling..") Await DoRescheduleJob(Of T)(pJobConfig) Else @@ -156,12 +160,12 @@ Namespace Scheduler End Function Private Async Function DoScheduleJob(Of T As IJob)(pJobConfig As JobConfig) As Task - Dim oJobName As String = GetJobName(pJobConfig) Dim oTriggerName As String = GetTriggerName(pJobConfig) + Dim oTrigger As ITrigger = BuildTrigger(pJobConfig) + Dim oJobName As String = GetJobName(pJobConfig) Dim oJobData As JobDataMap = BuildJobData(pJobConfig) Dim oJob As IJobDetail = BuildJob(Of T)(pJobConfig, oJobData) - Dim oTrigger As ITrigger = BuildTrigger(pJobConfig) If pJobConfig.Enabled Then Await Scheduler.ScheduleJob(oJob, oTrigger) @@ -172,14 +176,23 @@ Namespace Scheduler End If If pJobConfig.StartWithoutDelay Then - Dim oNoDelayTrigger = TriggerBuilder.Create(). + Await DoScheduleJobWithoutDelay(Of T)(pJobConfig) + End If + End Function + + Private Async Function DoScheduleJobWithoutDelay(Of T As IJob)(pJobConfig As JobConfig) As Task + Dim oJobName As String = GetJobName(pJobConfig) + Dim oJobData As JobDataMap = BuildJobData(pJobConfig) + Dim oJob As IJobDetail = BuildJob(Of T)(pJobConfig, oJobData) + + Dim oTriggerName As String = GetTriggerName(pJobConfig) + Dim oNoDelayTrigger = TriggerBuilder.Create(). WithIdentity(oTriggerName & "-NO-DELAY"). StartAt(DateBuilder.FutureDate(10, IntervalUnit.Second)). Build() - Logger.Info("Job {0} will start in 10 Seconds.", oJobName) - Await Scheduler.ScheduleJob(oJob, oNoDelayTrigger) - End If + Logger.Info("Job {0} will start in 10 Seconds.", oJobName) + Await Scheduler.ScheduleJob(oJob, oNoDelayTrigger) End Function Private Function BuildJob(Of T As IJob)(pJobConfig As JobConfig, pJobData As JobDataMap) As IJobDetail diff --git a/ECM.JobRunner.Windows/Scheduler/Jobs/BaseJob.vb b/ECM.JobRunner.Windows/Scheduler/Jobs/BaseJob.vb index 2fd8361..a74e01a 100644 --- a/ECM.JobRunner.Windows/Scheduler/Jobs/BaseJob.vb +++ b/ECM.JobRunner.Windows/Scheduler/Jobs/BaseJob.vb @@ -46,7 +46,7 @@ Namespace Scheduler.Jobs State.JobStatus.Update(ctx, pCurrentValue, pTotalValue) End Sub - Public Sub LogDebug(pMessage As String, ParamArray pArgs As String()) + Public Sub LogDebug(pMessage As String, ParamArray pArgs As Object()) Logger.Debug(pMessage, pArgs) JobSteps.Add(New StatusItem.HistoryStep With { .Message = String.Format(pMessage, pArgs), @@ -54,15 +54,16 @@ Namespace Scheduler.Jobs }) End Sub - Public Sub LogInfo(pMessage As String, ParamArray pArgs As String()) + Public Sub LogInfo(pMessage As String, ParamArray pArgs As Object()) Logger.Info(pMessage, pArgs) + JobSteps.Add(New StatusItem.HistoryStep With { .Message = String.Format(pMessage, pArgs), .Level = StatusItem.STEP_INFO }) End Sub - Public Sub LogWarning(pMessage As String, ParamArray pArgs As String()) + Public Sub LogWarning(pMessage As String, ParamArray pArgs As Object()) Logger.Warn(pMessage, pArgs) JobSteps.Add(New StatusItem.HistoryStep With { .Message = String.Format(pMessage, pArgs), @@ -70,15 +71,13 @@ Namespace Scheduler.Jobs }) End Sub - Public Sub LogError(pMessage As String, ParamArray pArgs As String()) + Public Sub LogError(pMessage As String, ParamArray pArgs As Object()) Logger.Error(pMessage, pArgs) JobSteps.Add(New StatusItem.HistoryStep With { .Message = String.Format(pMessage, pArgs), .Level = StatusItem.STEP_ERROR }) End Sub - - Public Function CompleteJob(pMessage As String) As Task(Of Boolean) ctx.Result = State.JobStatus.CompleteWithSuccess(ctx, JobSteps, pMessage) Return Task.FromResult(True) diff --git a/ECM.JobRunner.Windows/Scheduler/Jobs/FileImportJob.vb b/ECM.JobRunner.Windows/Scheduler/Jobs/FileImportJob.vb index 9a15acd..b3938ac 100644 --- a/ECM.JobRunner.Windows/Scheduler/Jobs/FileImportJob.vb +++ b/ECM.JobRunner.Windows/Scheduler/Jobs/FileImportJob.vb @@ -3,6 +3,7 @@ Imports Quartz Imports System.Text.RegularExpressions Imports DigitalData.Modules.Filesystem Imports ECM.JobRunner.Common +Imports FxResources.System Namespace Scheduler.Jobs @@ -176,11 +177,28 @@ Namespace Scheduler.Jobs 'Check if target folder exists If Windream.TestFolderExists(pProfile.TargetFolder) = False Then If Windream.NewFolder(pProfile.TargetFolder) = False Then - Logger.Warn("Folder [{0}] could not be created!", pProfile.TargetFolder) + Logger.Warn("Folder [{0}] could not be created! Exiting.", pProfile.TargetFolder) Return Nothing End If End If + Dim oFinalDirectoryPath = pProfile.TargetFolder + + If pProfile.SubfolderDateFormat <> String.Empty Then + ' ToString formatter needs the backslashes escaped again. + Dim oSubfolders = Now.ToString(pProfile.SubfolderDateFormat.Replace()) + Dim oFullPath = IO.Path.Combine(pProfile.TargetFolder, oSubfolders) + + Logger.Debug("Creating subfolder [{0}] in Target path [{1}]", oSubfolders, pProfile.TargetFolder) + + If Windream.NewFolder(oFullPath) = False Then + Logger.Warn("Folder [{0}] could not be created! Exiting.", oFullPath) + Return Nothing + End If + + oFinalDirectoryPath = oFullPath + End If + ' Generate new filepath and stream file Dim oFileName = IO.Path.GetFileName(pFile.FilePath) Dim oNewFilePath As String = IO.Path.Combine(pProfile.TargetFolder, oFileName) diff --git a/ECM.JobRunner.Windows/WCF/JobRunner.vb b/ECM.JobRunner.Windows/WCF/JobRunner.vb index 011142d..64631c6 100644 --- a/ECM.JobRunner.Windows/WCF/JobRunner.vb +++ b/ECM.JobRunner.Windows/WCF/JobRunner.vb @@ -44,7 +44,8 @@ Namespace WCF End Function Public Function GetJobHistory() As GetJobStatus.GetJobStatusResponse Implements IJobRunner.GetJobStatus - Logger.Info("Calling Method [GetJobHistory]") + ' No, we will not log this call because it will be called *A LOT*. + ' Nobody needs to see this in a log. Dim oMethod As New GetJobStatus.GetJobStatusMethod(LogConfig, Database, State, Scheduler) Return oMethod.Run() End Function