#48 made configurable the misfire instruction

This commit is contained in:
Fabio Formosa
2022-10-26 21:56:02 +02:00
parent 5ea8f2adb1
commit 4f8b75a8f9
10 changed files with 146 additions and 19 deletions

View File

@@ -100,18 +100,25 @@
>
</mat-form-field>
</div>
<br>
<div>
<h5>Misfire Policy</h5>
<div>RESCHEDULE NEXT WITH REMAINING COUNT</div>
<div class="small">
In case of misfire event, the trigger is re-scheduled to the next scheduled time after 'now' with the repeat count set to what it would be, if it had not missed any firings.
<br/>
<strong>Warning:</strong> This policy could cause the Trigger to go directly to the 'COMPLETE' state if all fire-times where missed.
</div>
<mat-form-field
[appearance]="enabledTriggerForm ? 'standard': 'none'"
class="full-size-input"
>
<mat-label>Misfire Instruction</mat-label>
<mat-select id="misfireInstruction" name="misfireInstruction" [(ngModel)]="simpleTriggerForm.misfireInstruction" [disabled]="!enabledTriggerForm">
<mat-option value="MISFIRE_INSTRUCTION_FIRE_NOW">FIRE NOW</mat-option>
<mat-option value="MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT">RESCHEDULE NOW WITH EXISTING REPEAT COUNT</mat-option>
<mat-option value="MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT">RESCHEDULE NOW WITH REMAINING REPEAT COUNT</mat-option>
<mat-option value="MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT">RESCHEDULE NEXT WITH REMAINING COUNT</mat-option>
<mat-option value="MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT">RESCHEDULE NEXT WITH EXISTING COUNT</mat-option>
</mat-select>
</mat-form-field>
<div class="small" [innerHTML]="getMisfireInstructionCaption()"> </div>
</div>
<br>
<br><br>
<button mat-raised-button
type="button"

View File

@@ -7,6 +7,7 @@ import {SimpleTriggerForm} from '../../model/simple-trigger.form';
import * as moment from 'moment';
import {TriggerKey} from '../../model/triggerKey.model';
import JobService from '../../services/job.service';
import {MisfireInstruction, MisfireInstructionCaption} from '../../model/misfire-instruction.model';
@Component({
selector: 'qrzmng-simple-trigger-config',
@@ -112,6 +113,7 @@ export class SimpleTriggerConfigComponent implements OnInit {
command.repeatInterval = simpleTrigger.repeatInterval;
command.startDate = moment(simpleTrigger.startTime);
command.endDate = moment(simpleTrigger.endTime);
command.misfireInstruction = MisfireInstruction[simpleTrigger.misfireInstruction];
return command;
}
@@ -123,7 +125,12 @@ export class SimpleTriggerConfigComponent implements OnInit {
simpleTriggerCommand.repeatInterval = simpleTriggerForm.repeatInterval;
simpleTriggerCommand.startDate = simpleTriggerForm.startDate?.toDate();
simpleTriggerCommand.endDate = simpleTriggerForm.endDate?.toDate();
simpleTriggerCommand.misfireInstruction = simpleTriggerForm.misfireInstruction;
return simpleTriggerCommand;
}
getMisfireInstructionCaption(): string {
const misfireInstructionKey = this.simpleTriggerForm.misfireInstruction as unknown as keyof typeof MisfireInstruction;
return MisfireInstructionCaption.get(MisfireInstruction[misfireInstructionKey]);
}
}

View File

@@ -0,0 +1,56 @@
export enum MisfireInstruction {
MISFIRE_INSTRUCTION_FIRE_NOW = 1,
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT = 2,
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT = 3 ,
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT = 4,
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT = 5
}
export function getMisfireInstructionByIndex(index: number) {
return Object.keys(MisfireInstruction)[index];
}
// function enumFromStringValue<T> (enm: { [s: string]: T}, value: string): T | undefined {
// return (Object.values(enm) as unknown as string[]).includes(value)
// ? value as unknown as T
// : undefined;
// }
//
// export function parseMisfireInstruction(str: string): MisfireInstruction {
// return enumFromStringValue<MisfireInstruction>(MisfireInstruction, str);
// // return (<any>MisfireInstruction)[str]
// // const indexOfStr = Object.values(MisfireInstruction).indexOf(str as unknown as MisfireInstruction);
// // const key = Object.keys(Sizes)[indexOfStr];
// // return MisfireInstruction[k]
// // return Object.values(MisfireInstruction).find(val => val === str);
// }
export const MisfireInstructionCaption = new Map<number, string>([
[MisfireInstruction.MISFIRE_INSTRUCTION_FIRE_NOW,
`The job is executed immediately after the scheduler discovers misfire situation.<br/>
In case of the trigger has been set with a repeat count, this policy is equals to RESCHEDULE NOW WITH REMAINING REPEAT COUNT`
],
[MisfireInstruction.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT,
`First misfired trigger is executed immediately. Then the scheduler waits desired interval and executes all remaining triggers.<br/>
Effectively the first fire time of the misfired trigger is moved to current time with no other changes.`
],
[MisfireInstruction.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT,
`First misfired execution runs immediately. Remaining misfired executions are discarded. Remaining not-yet-fired triggers are executed
with desired interval, starting from the recovered misfired execution.<br/>
Use this policy if your constraint is to honor the end date time.<br/>
<strong>Warning</strong> The actual number of job executions could be less than initially set,
because some of the misfired triggers are ignored. The end date time you set is always `
],
[MisfireInstruction.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT,
`In case of misfire event, the scheduler won't do anything immediately. Instead it will wait for next scheduled time the trigger and
run all triggers with scheduled interval. Misfired trigger are simply post-poned but not ignored.<br/>
Use this policy if your constraint is to execute the job for the all times equals to the repeation counter.<br/>' +
'<strong>Warning</strong> The scheduler can completed over the end date time you set `],
[MisfireInstruction.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT,
`In case of misfire event, the trigger is re-scheduled to the next scheduled time after 'now'
with the repeat count set to what it would be if it had not missed any firings.<br/>
Use this policy if no jobs must run after the end date time.<br/>
<strong>Warning</strong> The actual number of job executions could be less than initially set, because the misfired trigger are ignored.<br/>
This policy could cause the Trigger to go directly to the 'COMPLETE' state if all fire-times where missed.`
]
]);

View File

@@ -5,4 +5,5 @@ export class SimpleTriggerCommand {
endDate: Date;
repeatCount: number;
repeatInterval: number;
misfireInstruction: string;
}

View File

@@ -7,4 +7,5 @@ export class SimpleTriggerForm {
endDate: Moment;
repeatCount: number;
repeatInterval: number;
misfireInstruction: string;
}

View File

@@ -19,14 +19,38 @@ public class SimpleTriggerCommandDTOToSimpleTrigger implements Converter<SimpleT
if(triggerCommandDTO.getSimpleTriggerInputDTO().getEndDate() != null)
triggerTriggerBuilder.endAt(triggerCommandDTO.getSimpleTriggerInputDTO().getEndDate());
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMilliseconds(triggerCommandDTO.getSimpleTriggerInputDTO().getRepeatInterval())
.withRepeatCount(triggerCommandDTO.getSimpleTriggerInputDTO().getRepeatCount())
.withMisfireHandlingInstructionNextWithRemainingCount();
setTheMisfireInstruction(triggerCommandDTO, scheduleBuilder);
SimpleTrigger newSimpleTrigger = triggerTriggerBuilder.withSchedule(
SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMilliseconds(triggerCommandDTO.getSimpleTriggerInputDTO().getRepeatInterval())
.withRepeatCount(triggerCommandDTO.getSimpleTriggerInputDTO().getRepeatCount())
.withMisfireHandlingInstructionNextWithRemainingCount()
scheduleBuilder
)
.withIdentity(triggerCommandDTO.getTriggerName())
.build();
.withIdentity(triggerCommandDTO.getTriggerName()).build();
return newSimpleTrigger;
}
private static void setTheMisfireInstruction(SimpleTriggerCommandDTO triggerCommandDTO, SimpleScheduleBuilder scheduleBuilder) {
switch (triggerCommandDTO.getSimpleTriggerInputDTO().getMisfireInstruction()){
case MISFIRE_INSTRUCTION_FIRE_NOW:
scheduleBuilder.withMisfireHandlingInstructionFireNow();
break;
case MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT:
scheduleBuilder.withMisfireHandlingInstructionNowWithExistingCount();
break;
case MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT:
scheduleBuilder.withMisfireHandlingInstructionNowWithRemainingCount();
break;
case MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT:
scheduleBuilder.withMisfireHandlingInstructionNextWithRemainingCount();
break;
case MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT:
scheduleBuilder.withMisfireHandlingInstructionNextWithExistingCount();
break;
}
}
}

View File

@@ -13,6 +13,7 @@ public class SimpleTriggerToSimpleTriggerDTO extends TriggerToTriggerDTO<SimpleT
target.setTimesTriggered(source.getTimesTriggered());
target.setRepeatCount(source.getRepeatCount());
target.setRepeatInterval(source.getRepeatInterval());
target.setMisfireInstruction(source.getMisfireInstruction());
}
@Override

View File

@@ -0,0 +1,27 @@
package it.fabioformosa.quartzmanager.api.dto;
import lombok.Getter;
import java.util.Arrays;
public enum MisfireInstruction {
MISFIRE_INSTRUCTION_FIRE_NOW(1),
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT(2),
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT(3),
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT(4),
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT(5);
@Getter
private int num;
MisfireInstruction(int num) {
this.num = num;
}
static public MisfireInstruction parseInt(int num) {
return Arrays.stream(MisfireInstruction.values())
.filter(misfireInstruction -> misfireInstruction.getNum() == num)
.findFirst().orElseThrow(() -> new IllegalArgumentException(num + " is not a valid misfire instruction code!"));
}
}

View File

@@ -23,4 +23,7 @@ public class TriggerCommandDTO {
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private Date endDate;
private MisfireInstruction misfireInstruction = MisfireInstruction.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT;
}

View File

@@ -31,10 +31,10 @@
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-starter-ui</artifactId>
</dependency>
<dependency>
<groupId>it.fabioformosa.quartz-manager</groupId>
<artifactId>quartz-manager-starter-security</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>it.fabioformosa.quartz-manager</groupId>-->
<!-- <artifactId>quartz-manager-starter-security</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>it.fabioformosa.quartz-manager</groupId>-->
<!-- <artifactId>quartz-manager-starter-persistence</artifactId>-->