improve Scheduled Job start/stop user experience, utilize start time when setting next job execution
This commit is contained in:
		@ -36,13 +36,13 @@ else
 | 
			
		||||
            <td>@context.NextExecution</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                @if (context.IsStarted)
 | 
			
		||||
                    {
 | 
			
		||||
                {
 | 
			
		||||
                    <button type="button" class="btn btn-danger" @onclick="(async () => await StopJob(context.JobId))">@Localizer["Stop"]</button>
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    <button type="button" class="btn btn-success" @onclick="(async () => await StartJob(context.JobId))">@Localizer["Start"]</button>
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            </td>
 | 
			
		||||
        </Row>
 | 
			
		||||
    </Pager>
 | 
			
		||||
@ -100,11 +100,6 @@ else
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (interval > 1)
 | 
			
		||||
        {
 | 
			
		||||
            result += Localizer["s"];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -114,6 +109,7 @@ else
 | 
			
		||||
        {
 | 
			
		||||
            await JobService.DeleteJobAsync(job.JobId);
 | 
			
		||||
            await logger.LogInformation("Job Deleted {Job}", job);
 | 
			
		||||
			_jobs = await JobService.GetJobsAsync();
 | 
			
		||||
            StateHasChanged();
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
@ -125,12 +121,36 @@ else
 | 
			
		||||
 | 
			
		||||
    private async Task StartJob(int jobId)
 | 
			
		||||
    {
 | 
			
		||||
        await JobService.StartJobAsync(jobId);
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
			await JobService.StartJobAsync(jobId);
 | 
			
		||||
            await logger.LogInformation("Job Started {JobId}", jobId);
 | 
			
		||||
            AddModuleMessage(Localizer["Message.Job.Start"], MessageType.Success);
 | 
			
		||||
			_jobs = await JobService.GetJobsAsync();
 | 
			
		||||
            StateHasChanged();
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            await logger.LogError(ex, "Error Starting Job {JobId} {Error}", jobId, ex.Message);
 | 
			
		||||
            AddModuleMessage(Localizer["Error.Job.Start"], MessageType.Error);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async Task StopJob(int jobId)
 | 
			
		||||
    {
 | 
			
		||||
        await JobService.StopJobAsync(jobId);
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
			await JobService.StopJobAsync(jobId);
 | 
			
		||||
            await logger.LogInformation("Job Stopped {JobId}", jobId);
 | 
			
		||||
            AddModuleMessage(Localizer["Message.Job.Stop"], MessageType.Success);
 | 
			
		||||
			_jobs = await JobService.GetJobsAsync();
 | 
			
		||||
            StateHasChanged();
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            await logger.LogError(ex, "Error Stopping Job {JobId} {Error}", jobId, ex.Message);
 | 
			
		||||
            AddModuleMessage(Localizer["Error.Job.Stop"], MessageType.Error);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async Task Refresh()
 | 
			
		||||
 | 
			
		||||
@ -144,9 +144,6 @@
 | 
			
		||||
  <data name="Month" xml:space="preserve">
 | 
			
		||||
    <value>Month</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="s" xml:space="preserve">
 | 
			
		||||
    <value>s</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="Error.Job.Delete" xml:space="preserve">
 | 
			
		||||
    <value>Error Deleting Job</value>
 | 
			
		||||
  </data>
 | 
			
		||||
@ -177,4 +174,16 @@
 | 
			
		||||
  <data name="JobLog.Text" xml:space="preserve">
 | 
			
		||||
    <value>Log</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="Error.Job.Start" xml:space="preserve">
 | 
			
		||||
    <value>An error occurred when starting the job</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="Error.Job.Stop" xml:space="preserve">
 | 
			
		||||
    <value>An error occurred when stopping the job</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="Message.Job.Start" xml:space="preserve">
 | 
			
		||||
    <value>The process responsible for executing this job has been started. The next execution will be based on the schedule criteria for the job.</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="Message.Job.Stop" xml:space="preserve">
 | 
			
		||||
    <value>The process responsible for executing this job has been stopped. In order to restart the process you will need to use the Start button or restart the application.</value>
 | 
			
		||||
  </data>
 | 
			
		||||
</root>
 | 
			
		||||
@ -114,7 +114,7 @@ namespace Oqtane.Infrastructure
 | 
			
		||||
                                jobLogs.UpdateJobLog(log);
 | 
			
		||||
 | 
			
		||||
                                // update the job
 | 
			
		||||
                                job.NextExecution = CalculateNextExecution(NextExecution, job.Frequency, job.Interval);
 | 
			
		||||
                                job.NextExecution = CalculateNextExecution(NextExecution, job);
 | 
			
		||||
                                job.IsExecuting = false;
 | 
			
		||||
                                jobs.UpdateJob(job);
 | 
			
		||||
 | 
			
		||||
@ -140,21 +140,31 @@ namespace Oqtane.Infrastructure
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private DateTime CalculateNextExecution(DateTime nextExecution, string frequency, int interval)
 | 
			
		||||
        private DateTime CalculateNextExecution(DateTime nextExecution, Job job)
 | 
			
		||||
        {
 | 
			
		||||
            switch (frequency)
 | 
			
		||||
            switch (job.Frequency)
 | 
			
		||||
            {
 | 
			
		||||
                case "m": // minutes
 | 
			
		||||
                    nextExecution = nextExecution.AddMinutes(interval);
 | 
			
		||||
                    nextExecution = nextExecution.AddMinutes(job.Interval);
 | 
			
		||||
                    break;
 | 
			
		||||
                case "H": // hours
 | 
			
		||||
                    nextExecution = nextExecution.AddHours(interval);
 | 
			
		||||
                    nextExecution = nextExecution.AddHours(job.Interval);
 | 
			
		||||
                    break;
 | 
			
		||||
                case "d": // days
 | 
			
		||||
                    nextExecution = nextExecution.AddDays(interval);
 | 
			
		||||
                    nextExecution = nextExecution.AddDays(job.Interval);
 | 
			
		||||
                    if (job.StartDate != null && job.StartDate.Value.TimeOfDay.TotalSeconds != 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        // set the start time
 | 
			
		||||
                        nextExecution = nextExecution.Date.Add(job.StartDate.Value.TimeOfDay);
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                case "M": // months
 | 
			
		||||
                    nextExecution = nextExecution.AddMonths(interval);
 | 
			
		||||
                    nextExecution = nextExecution.AddMonths(job.Interval);
 | 
			
		||||
                    if (job.StartDate != null && job.StartDate.Value.TimeOfDay.TotalSeconds != 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        // set the start time
 | 
			
		||||
                        nextExecution = nextExecution.Date.Add(job.StartDate.Value.TimeOfDay);
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            if (nextExecution < DateTime.UtcNow)
 | 
			
		||||
@ -168,7 +178,6 @@ namespace Oqtane.Infrastructure
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                // set IsExecuting to false in case this job was forcefully terminated previously 
 | 
			
		||||
                using (var scope = _serviceScopeFactory.CreateScope())
 | 
			
		||||
                {
 | 
			
		||||
                    string jobTypeName = Utilities.GetFullTypeName(GetType().AssemblyQualifiedName);
 | 
			
		||||
@ -176,15 +185,17 @@ namespace Oqtane.Infrastructure
 | 
			
		||||
                    Job job = jobs.GetJobs().Where(item => item.JobType == jobTypeName).FirstOrDefault();
 | 
			
		||||
                    if (job != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        // reset in case this job was forcefully terminated previously 
 | 
			
		||||
                        job.IsStarted = true;
 | 
			
		||||
                        job.IsExecuting = false;
 | 
			
		||||
                        jobs.UpdateJob(job);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        // auto registration - does not run on initial installation but will run after restart
 | 
			
		||||
                        // auto registration - job will not run on initial installation but will run after restart
 | 
			
		||||
                        job = new Job { JobType = jobTypeName };
 | 
			
		||||
                        // optional properties
 | 
			
		||||
 | 
			
		||||
                        // optional HostedServiceBase properties
 | 
			
		||||
                        var jobType = Type.GetType(jobTypeName);
 | 
			
		||||
                        var jobObject = ActivatorUtilities.CreateInstance(scope.ServiceProvider, jobType) as HostedServiceBase;
 | 
			
		||||
                        if (jobObject.Name != "")
 | 
			
		||||
@ -203,6 +214,7 @@ namespace Oqtane.Infrastructure
 | 
			
		||||
                        job.IsEnabled = jobObject.IsEnabled;
 | 
			
		||||
                        job.IsStarted = true;
 | 
			
		||||
                        job.IsExecuting = false;
 | 
			
		||||
                        job.NextExecution = null;
 | 
			
		||||
                        jobs.AddJob(job);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@ -224,13 +236,27 @@ namespace Oqtane.Infrastructure
 | 
			
		||||
 | 
			
		||||
        public async Task StopAsync(CancellationToken cancellationToken)
 | 
			
		||||
        {
 | 
			
		||||
            if (_executingTask == null)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                using (var scope = _serviceScopeFactory.CreateScope())
 | 
			
		||||
                {
 | 
			
		||||
                    string jobTypeName = Utilities.GetFullTypeName(GetType().AssemblyQualifiedName);
 | 
			
		||||
                    IJobRepository jobs = scope.ServiceProvider.GetRequiredService<IJobRepository>();
 | 
			
		||||
                    Job job = jobs.GetJobs().Where(item => item.JobType == jobTypeName).FirstOrDefault();
 | 
			
		||||
                    if (job != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        // reset job 
 | 
			
		||||
                        job.IsStarted = false;
 | 
			
		||||
                        job.IsExecuting = false;
 | 
			
		||||
                        jobs.UpdateJob(job);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (_executingTask == null)
 | 
			
		||||
                {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                _cancellationTokenSource.Cancel();
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user