mirror of
https://github.com/fabioformosa/quartz-manager.git
synced 2025-12-30 22:23:15 +09:00
Changed API and frontend to handle stored triggers and jobs
This commit is contained in:
@@ -108,11 +108,11 @@
|
||||
"defaultProject": "angular-spring-starter",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"prefix": "app",
|
||||
"prefix": "qrzmng",
|
||||
"style": "css"
|
||||
},
|
||||
"@schematics/angular:directive": {
|
||||
"prefix": "app"
|
||||
"prefix": "qrzmng"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,35 +2,56 @@
|
||||
<mat-card-header>
|
||||
<mat-card-title><b>SCHEDULER CONFIG</b></mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
|
||||
<!-- ADD BUTTON -->
|
||||
<mat-card-content *ngIf="!shouldShowTriggerConfig() && !enabledTriggerForm">
|
||||
<button mat-fab color="primary">
|
||||
<mat-icon (click)="enableTriggerForm()">add</mat-icon>
|
||||
</button>
|
||||
</mat-card-content>
|
||||
|
||||
<!-- TRIGGER DETAILS -->
|
||||
<mat-card-content *ngIf="shouldShowTriggerConfig() || enabledTriggerForm">
|
||||
<div fxLayout="column">
|
||||
<form name="configForm" fxFlex="1 1 100%" #configForm="ngForm">
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="Freq [Num per day]" [(ngModel)]="config.triggerPerDay" name="triggerPerDay" type="number">
|
||||
<mat-form-field >
|
||||
<input [readonly]="!enabledTriggerForm"
|
||||
matInput placeholder="Freq [Num per day]" name="triggerPerDay" type="number"
|
||||
[(ngModel)]="config.triggerPerDay"
|
||||
>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="Max Occurrences" [(ngModel)]="config.maxCount" name="maxCount" type="number">
|
||||
<input [readonly]="!enabledTriggerForm"
|
||||
matInput placeholder="Max Occurrences" name="maxCount" type="number"
|
||||
[(ngModel)]="config.maxCount"
|
||||
>
|
||||
</mat-form-field>
|
||||
|
||||
|
||||
<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.
|
||||
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.
|
||||
<strong>Warning:</strong> This policy could cause the Trigger to go directly to the 'COMPLETE' state if all fire-times where missed.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
<button mat-raised-button
|
||||
type="button"
|
||||
type="button"
|
||||
*ngIf="enabledTriggerForm"
|
||||
(click)="submitConfig()">
|
||||
Submit
|
||||
</button>
|
||||
<button mat-raised-button type="button"
|
||||
*ngIf="!enabledTriggerForm"
|
||||
(click)="enabledTriggerForm = true">
|
||||
Reschedule
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
@@ -1,40 +1,65 @@
|
||||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { SchedulerService } from '../../services';
|
||||
import { SchedulerConfig } from '../../model/schedulerConfig.model'
|
||||
import {Scheduler} from '../../model/scheduler.model';
|
||||
|
||||
@Component({
|
||||
selector: 'scheduler-config',
|
||||
selector: 'qrzmng-scheduler-config',
|
||||
templateUrl: './scheduler-config.component.html',
|
||||
styleUrls: ['./scheduler-config.component.scss']
|
||||
})
|
||||
export class SchedulerConfigComponent implements OnInit {
|
||||
|
||||
config: SchedulerConfig = new SchedulerConfig()
|
||||
configBackup: SchedulerConfig = new SchedulerConfig()
|
||||
scheduler: Scheduler;
|
||||
|
||||
triggerLoading = true;
|
||||
enabledTriggerForm = false;
|
||||
private fetchedTriggers = false;
|
||||
private triggerInProgress = false;
|
||||
|
||||
constructor(
|
||||
private schedulerService: SchedulerService
|
||||
) { }
|
||||
|
||||
config : SchedulerConfig = new SchedulerConfig()
|
||||
configBackup : SchedulerConfig = new SchedulerConfig()
|
||||
|
||||
ngOnInit() {
|
||||
this.retrieveConfig()
|
||||
this.triggerLoading = true;
|
||||
this._getScheduler();
|
||||
this.retrieveConfig();
|
||||
}
|
||||
|
||||
retrieveConfig = () => {
|
||||
this.schedulerService.getConfig()
|
||||
.subscribe(res => {
|
||||
this.config = new SchedulerConfig(res.triggerPerDay, res.maxCount)
|
||||
this.config = new SchedulerConfig(res.triggerPerDay, res.maxCount, res.timesTriggered)
|
||||
this.configBackup = res
|
||||
this.triggerLoading = false;
|
||||
this.triggerInProgress = res.timesTriggered < res.maxCount;
|
||||
})
|
||||
}
|
||||
|
||||
private _getScheduler() {
|
||||
this.schedulerService.getScheduler()
|
||||
.subscribe( res => {
|
||||
this.scheduler = <Scheduler>res;
|
||||
this.fetchedTriggers = this.scheduler.triggerKeys.length > 0
|
||||
})
|
||||
}
|
||||
|
||||
shouldShowTriggerConfig = (): boolean => this.fetchedTriggers && this.triggerInProgress;
|
||||
|
||||
submitConfig = () => {
|
||||
this.schedulerService.updateConfig(this.config)
|
||||
.subscribe(res => {
|
||||
this.configBackup = this.config;
|
||||
this.enabledTriggerForm = false;
|
||||
this.fetchedTriggers = true;
|
||||
this.triggerInProgress = true;
|
||||
}, error => {
|
||||
this.config = this.configBackup;
|
||||
});
|
||||
};
|
||||
|
||||
enableTriggerForm = () => this.enabledTriggerForm = true;
|
||||
}
|
||||
|
||||
13
quartz-manager-frontend/src/app/model/scheduler.model.ts
Normal file
13
quartz-manager-frontend/src/app/model/scheduler.model.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import {TriggerKey} from './triggerKey.model';
|
||||
|
||||
export class Scheduler {
|
||||
name: string;
|
||||
instanceId: string;
|
||||
triggerKeys: TriggerKey[];
|
||||
|
||||
constructor(name: string, instanceId: string, triggerKeys: TriggerKey[]) {
|
||||
this.name = name;
|
||||
this.instanceId = instanceId;
|
||||
this.triggerKeys = triggerKeys;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
export class SchedulerConfig {
|
||||
|
||||
triggerPerDay : number = 0
|
||||
maxCount : number = 0
|
||||
triggerPerDay = 0;
|
||||
maxCount = 0;
|
||||
timesTriggered = 0;
|
||||
|
||||
constructor(triggerPerDay = 0, maxCount = 0) {
|
||||
this.triggerPerDay = triggerPerDay
|
||||
this.maxCount = maxCount
|
||||
constructor(triggerPerDay = 0, maxCount = 0, timesTriggered = 0) {
|
||||
this.triggerPerDay = triggerPerDay;
|
||||
this.maxCount = maxCount;
|
||||
this.timesTriggered = timesTriggered;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
export class TriggerKey {
|
||||
name: string;
|
||||
group: string;
|
||||
|
||||
constructor(name: string, group: string) {
|
||||
this.name = name;
|
||||
this.group = group;
|
||||
}
|
||||
}
|
||||
@@ -12,20 +12,24 @@ export class SchedulerService {
|
||||
startScheduler = () => {
|
||||
return this.apiService.get(getBaseUrl() + '/quartz-manager/scheduler/run')
|
||||
}
|
||||
|
||||
|
||||
stopScheduler = () => {
|
||||
return this.apiService.get(getBaseUrl() + '/quartz-manager/scheduler/stop')
|
||||
}
|
||||
|
||||
|
||||
pauseScheduler = () => {
|
||||
return this.apiService.get(getBaseUrl() + '/quartz-manager/scheduler/pause')
|
||||
}
|
||||
|
||||
|
||||
resumeScheduler = () => {
|
||||
return this.apiService.get(getBaseUrl() + '/quartz-manager/scheduler/resume')
|
||||
}
|
||||
|
||||
getStatus = () => {
|
||||
return this.apiService.get(getBaseUrl() + '/quartz-manager/scheduler/status')
|
||||
}
|
||||
|
||||
getScheduler = () => {
|
||||
return this.apiService.get(getBaseUrl() + '/quartz-manager/scheduler')
|
||||
}
|
||||
|
||||
@@ -34,6 +38,8 @@ export class SchedulerService {
|
||||
}
|
||||
|
||||
updateConfig = (config: Object) => {
|
||||
return this.apiService.post(getBaseUrl() + '/quartz-manager/scheduler/config', config)
|
||||
return this.apiService.post(getBaseUrl() + '/quartz-manager/triggers/mytrigger', config)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
<div fxLayout="column">
|
||||
<scheduler-control></scheduler-control>
|
||||
<br/>
|
||||
<scheduler-config></scheduler-config>
|
||||
<qrzmng-scheduler-config></qrzmng-scheduler-config>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div fxFlex="1 1 70%" style="margin-left: 20px">
|
||||
<div fxLayout="column">
|
||||
<div fxFlex="1 1 100%"><progress-panel></progress-panel></div>
|
||||
<br/>
|
||||
<div fxFlex="1 1 100%"><logs-panel></logs-panel></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package it.fabioformosa.quartzmanager.common.utils;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class Try<R> {
|
||||
|
||||
private final Throwable failure;
|
||||
private final R success;
|
||||
|
||||
public Try(Throwable failure, R success) {
|
||||
this.failure = failure;
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
public R getSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public static <R> Try success(R r){
|
||||
return new Try<>(null, r);
|
||||
}
|
||||
|
||||
public static <ExceptionType> Try failure(Throwable e){
|
||||
return new Try<>(e, null);
|
||||
}
|
||||
|
||||
public static <T, R> Function<T, Try<R>> with(CheckedFunction<T, R> checkedFunction){
|
||||
return t -> {
|
||||
try {
|
||||
return Try.success(checkedFunction.apply(t));
|
||||
} catch (java.lang.Exception e) {
|
||||
return Try.failure(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static <T, R> Function<T, R> sneakyThrow(CheckedFunction<T, R> checkedFunction){
|
||||
return t -> Try.with(checkedFunction).apply(t).getSuccess();
|
||||
}
|
||||
|
||||
public boolean isSuccess(){
|
||||
return this.failure == null;
|
||||
}
|
||||
|
||||
public boolean isFailure(){
|
||||
return this.failure != null;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public static interface CheckedFunction<T, R> {
|
||||
R apply(T t) throws java.lang.Exception;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,128 +1,135 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>it.fabioformosa.quartz-manager</groupId>
|
||||
<artifactId>quartz-manager-parent</artifactId>
|
||||
<version>3.0.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>quartz-manager-starter-api</artifactId>
|
||||
|
||||
<name>Quartz Manager Starter API</name>
|
||||
<description>REST API layer for your scheduler and triggered jobs, to be included in your spring webapp</description>
|
||||
|
||||
<url>https://github.com/fabioformosa/quartz-manager</url>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<springfox.version>2.9.2</springfox.version>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>it.fabioformosa.quartz-manager</groupId>
|
||||
<artifactId>quartz-manager-common</artifactId>
|
||||
</dependency>
|
||||
<!-- SPRING -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- MISC -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- QUARTZ -->
|
||||
<dependency>
|
||||
<groupId>org.quartz-scheduler</groupId>
|
||||
<artifactId>quartz</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>1.3.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Reactor -->
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-net</artifactId>
|
||||
<version>2.0.8.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor.spring</groupId>
|
||||
<artifactId>reactor-spring-context</artifactId>
|
||||
<version>2.0.7.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SWAGGER -->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>${springfox.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
<version>${springfox.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>it.fabioformosa.quartz-manager</groupId>
|
||||
<artifactId>quartz-manager-parent</artifactId>
|
||||
<version>3.0.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>quartz-manager-starter-api</artifactId>
|
||||
|
||||
<name>Quartz Manager Starter API</name>
|
||||
<description>REST API layer for your scheduler and triggered jobs, to be included in your spring webapp</description>
|
||||
|
||||
<url>https://github.com/fabioformosa/quartz-manager</url>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<springfox.version>2.9.2</springfox.version>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>it.fabioformosa.quartz-manager</groupId>
|
||||
<artifactId>quartz-manager-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SPRING -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- MISC -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>it.fabioformosa</groupId>
|
||||
<artifactId>metamorphosis-core</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- QUARTZ -->
|
||||
<dependency>
|
||||
<groupId>org.quartz-scheduler</groupId>
|
||||
<artifactId>quartz</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>1.3.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Reactor -->
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-net</artifactId>
|
||||
<version>2.0.8.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor.spring</groupId>
|
||||
<artifactId>reactor-spring-context</artifactId>
|
||||
<version>2.0.7.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SWAGGER -->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>${springfox.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
<version>${springfox.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package it.fabioformosa.quartzmanager.aspects;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import it.fabioformosa.quartzmanager.dto.TriggerStatus;
|
||||
import it.fabioformosa.quartzmanager.services.SchedulerService;
|
||||
import org.quartz.DailyTimeIntervalTrigger;
|
||||
import org.quartz.Scheduler;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.quartz.SimpleTrigger;
|
||||
import org.quartz.Trigger;
|
||||
@@ -11,8 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.messaging.simp.SimpMessageSendingOperations;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import it.fabioformosa.quartzmanager.dto.TriggerStatus;
|
||||
import it.fabioformosa.quartzmanager.scheduler.TriggerMonitor;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -28,11 +26,14 @@ public class WebSocketProgressNotifier implements ProgressNotifier {
|
||||
@Autowired
|
||||
private SimpMessageSendingOperations messagingTemplate;
|
||||
|
||||
@Resource
|
||||
private Scheduler scheduler;
|
||||
// @Resource
|
||||
// private Scheduler scheduler;
|
||||
|
||||
@Resource
|
||||
private TriggerMonitor triggerMonitor;
|
||||
private SchedulerService schedulerService;
|
||||
|
||||
// @Resource
|
||||
// private TriggerMonitor triggerMonitor;
|
||||
|
||||
//@AfterReturning("execution(* logAndSend(..))")
|
||||
// @Override
|
||||
@@ -44,7 +45,7 @@ public class WebSocketProgressNotifier implements ProgressNotifier {
|
||||
public void send() throws SchedulerException {
|
||||
TriggerStatus currTriggerStatus = new TriggerStatus();
|
||||
|
||||
Trigger trigger = scheduler.getTrigger(triggerMonitor.getTrigger().getKey());
|
||||
Trigger trigger = schedulerService.getOneSimpleTrigger().get();
|
||||
currTriggerStatus.setFinalFireTime(trigger.getFinalFireTime());
|
||||
currTriggerStatus.setNextFireTime(trigger.getNextFireTime());
|
||||
currTriggerStatus.setPreviousFireTime(trigger.getPreviousFireTime());
|
||||
@@ -62,7 +63,7 @@ public class WebSocketProgressNotifier implements ProgressNotifier {
|
||||
repeatCount = dailyTrigger.getRepeatCount();
|
||||
}
|
||||
|
||||
Trigger jobTrigger = triggerMonitor.getTrigger();
|
||||
Trigger jobTrigger = schedulerService.getOneSimpleTrigger().get();
|
||||
if (jobTrigger != null && jobTrigger.getJobKey() != null) {
|
||||
currTriggerStatus.setJobKey(jobTrigger.getJobKey().getName());
|
||||
currTriggerStatus.setJobClass(jobTrigger.getClass().getSimpleName());
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package it.fabioformosa.quartzmanager.configuration;
|
||||
|
||||
import it.fabioformosa.metamorphosis.core.EnableMetamorphosisConversions;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@EnableMetamorphosisConversions(basePackages = { "it.fabioformosa.quartzmanager" })
|
||||
public class ConversionConfig {
|
||||
}
|
||||
@@ -1,15 +1,12 @@
|
||||
package it.fabioformosa.quartzmanager.configuration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import it.fabioformosa.quartzmanager.common.properties.QuartzModuleProperties;
|
||||
import it.fabioformosa.quartzmanager.scheduler.AutowiringSpringBeanJobFactory;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobDetail;
|
||||
import org.quartz.SimpleTrigger;
|
||||
import org.quartz.Trigger;
|
||||
import org.quartz.spi.JobFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@@ -22,10 +19,8 @@ import org.springframework.scheduling.quartz.JobDetailFactoryBean;
|
||||
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
|
||||
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;
|
||||
|
||||
import it.fabioformosa.quartzmanager.common.properties.QuartzModuleProperties;
|
||||
import it.fabioformosa.quartzmanager.scheduler.AutowiringSpringBeanJobFactory;
|
||||
import it.fabioformosa.quartzmanager.scheduler.TriggerMonitor;
|
||||
import it.fabioformosa.quartzmanager.scheduler.TriggerMonitorImpl;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
@ComponentScan(basePackages = {"it.fabioformosa.quartzmanager.controllers"})
|
||||
@Configuration
|
||||
@@ -59,12 +54,14 @@ public class SchedulerConfig {
|
||||
@Autowired(required = false)
|
||||
private QuartzModuleProperties quartzModuleProperties;
|
||||
|
||||
@Bean(name = "triggerMonitor")
|
||||
public TriggerMonitor createTriggerMonitor(@Qualifier("jobTrigger") Trigger trigger) {
|
||||
TriggerMonitor triggerMonitor = new TriggerMonitorImpl();
|
||||
triggerMonitor.setTrigger(trigger);
|
||||
return triggerMonitor;
|
||||
}
|
||||
|
||||
// REMOVEME
|
||||
// @Bean(name = "triggerMonitor")
|
||||
// public TriggerMonitor createTriggerMonitor(@Qualifier("jobTrigger") Trigger trigger) {
|
||||
// TriggerMonitor triggerMonitor = new TriggerMonitorImpl();
|
||||
// triggerMonitor.setTrigger(trigger);
|
||||
// return triggerMonitor;
|
||||
// }
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -88,15 +85,16 @@ public class SchedulerConfig {
|
||||
return propertiesFactoryBean.getObject();
|
||||
}
|
||||
|
||||
@Bean(name = "jobTrigger")
|
||||
public SimpleTriggerFactoryBean sampleJobTrigger(@Qualifier("jobDetail") JobDetail jobDetail,
|
||||
@Value("${job.frequency}") long frequency, @Value("${job.repeatCount}") int repeatCount) {
|
||||
return createTrigger(jobDetail, frequency, repeatCount);
|
||||
}
|
||||
// @Bean(name = "jobTrigger")
|
||||
// public SimpleTriggerFactoryBean sampleJobTrigger(@Qualifier("jobDetail") JobDetail jobDetail,
|
||||
// @Value("${job.frequency}") long frequency, @Value("${job.repeatCount}") int repeatCount) {
|
||||
// return createTrigger(jobDetail, frequency, repeatCount);
|
||||
// }
|
||||
|
||||
@Bean(name = "scheduler")
|
||||
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory,
|
||||
@Qualifier("jobTrigger") Trigger sampleJobTrigger) throws IOException {
|
||||
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) throws IOException {
|
||||
// public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory,
|
||||
// @Qualifier("jobTrigger") Trigger sampleJobTrigger) throws IOException {
|
||||
SchedulerFactoryBean factory = new SchedulerFactoryBean();
|
||||
factory.setJobFactory(jobFactory);
|
||||
Properties mergedProperties = new Properties();
|
||||
@@ -104,8 +102,8 @@ public class SchedulerConfig {
|
||||
if(quartzModuleProperties != null)
|
||||
mergedProperties.putAll(quartzModuleProperties.getProperties());
|
||||
factory.setQuartzProperties(mergedProperties);
|
||||
factory.setTriggers(sampleJobTrigger);
|
||||
//factory.setTriggers(sampleJobTrigger);
|
||||
factory.setAutoStartup(false);
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,161 +1,158 @@
|
||||
package it.fabioformosa.quartzmanager.controllers;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.quartz.Scheduler;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.quartz.SimpleScheduleBuilder;
|
||||
import org.quartz.SimpleTrigger;
|
||||
import org.quartz.Trigger;
|
||||
import org.quartz.TriggerBuilder;
|
||||
import org.quartz.impl.triggers.SimpleTriggerImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import it.fabioformosa.quartzmanager.dto.SchedulerConfigParam;
|
||||
import it.fabioformosa.quartzmanager.dto.SchedulerDTO;
|
||||
import it.fabioformosa.quartzmanager.dto.TriggerStatus;
|
||||
import it.fabioformosa.quartzmanager.enums.SchedulerStates;
|
||||
import it.fabioformosa.quartzmanager.scheduler.TriggerMonitor;
|
||||
import it.fabioformosa.quartzmanager.services.SchedulerService;
|
||||
import org.quartz.*;
|
||||
import org.quartz.impl.triggers.SimpleTriggerImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This controller provides scheduler info about config and status. It provides
|
||||
* also methods to set new config and start/stop/resume the scheduler.
|
||||
*
|
||||
* @author Fabio.Formosa
|
||||
*
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/quartz-manager/scheduler")
|
||||
@Api(value = "scheduler")
|
||||
public class SchedulerController {
|
||||
|
||||
private static final int MILLS_IN_A_DAY = 1000 * 60 * 60 * 24;
|
||||
private static final int SEC_IN_A_DAY = 60 * 60 * 24;
|
||||
private final Logger log = LoggerFactory.getLogger(SchedulerController.class);
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(SchedulerController.class);
|
||||
private SchedulerService schedulerService;
|
||||
|
||||
@Resource
|
||||
private Scheduler scheduler;
|
||||
public SchedulerController(SchedulerService schedulerService, ConversionService conversionService) {
|
||||
this.schedulerService = schedulerService;
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
@Resource
|
||||
private TriggerMonitor triggerMonitor;
|
||||
// @Resource
|
||||
// private Scheduler scheduler;
|
||||
|
||||
private long fromMillsIntervalToTriggerPerDay(long repeatIntervalInMills) {
|
||||
return (int) Math.ceil(MILLS_IN_A_DAY / repeatIntervalInMills);
|
||||
//TODO REMOVEME
|
||||
// @Resource
|
||||
// private TriggerMonitor triggerMonitor;
|
||||
|
||||
@Resource
|
||||
private ConversionService conversionService;
|
||||
|
||||
@GetMapping("/config")
|
||||
public SchedulerConfigParam getConfig() throws SchedulerException {
|
||||
log.debug("SCHEDULER - GET CONFIG params");
|
||||
|
||||
SchedulerConfigParam schedulerConfigParam = schedulerService.getOneSimpleTrigger()
|
||||
.map(SchedulerController::fromSimpleTriggerToSchedulerConfigParam)
|
||||
.orElse(new SchedulerConfigParam(0, 0, 0));
|
||||
|
||||
return schedulerConfigParam;
|
||||
}
|
||||
|
||||
public static SchedulerConfigParam fromSimpleTriggerToSchedulerConfigParam(SimpleTrigger simpleTrigger){
|
||||
int timesTriggered = simpleTrigger.getTimesTriggered();
|
||||
int maxCount = simpleTrigger.getRepeatCount() + 1;
|
||||
long triggersPerDay = SchedulerService.fromMillsIntervalToTriggerPerDay(simpleTrigger.getRepeatInterval());
|
||||
return new SchedulerConfigParam(triggersPerDay, maxCount, timesTriggered);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@GetMapping
|
||||
public SchedulerDTO getScheduler() {
|
||||
log.debug("SCHEDULER - GET Scheduler...");
|
||||
SchedulerDTO schedulerDTO = conversionService.convert(schedulerService.getScheduler(), SchedulerDTO.class);
|
||||
return schedulerDTO;
|
||||
}
|
||||
|
||||
@GetMapping("/progress")
|
||||
public TriggerStatus getProgressInfo() throws SchedulerException {
|
||||
log.trace("SCHEDULER - GET PROGRESS INFO");
|
||||
TriggerStatus progress = new TriggerStatus();
|
||||
|
||||
SimpleTriggerImpl jobTrigger = (SimpleTriggerImpl) schedulerService.getOneSimpleTrigger().get();
|
||||
if (jobTrigger != null && jobTrigger.getJobKey() != null) {
|
||||
progress.setJobKey(jobTrigger.getJobKey().getName());
|
||||
progress.setJobClass(jobTrigger.getClass().getSimpleName());
|
||||
progress.setTimesTriggered(jobTrigger.getTimesTriggered());
|
||||
progress.setRepeatCount(jobTrigger.getRepeatCount());
|
||||
progress.setFinalFireTime(jobTrigger.getFinalFireTime());
|
||||
progress.setNextFireTime(jobTrigger.getNextFireTime());
|
||||
progress.setPreviousFireTime(jobTrigger.getPreviousFireTime());
|
||||
}
|
||||
|
||||
private int fromTriggerPerDayToMillsInterval(long triggerPerDay) {
|
||||
return (int) Math.ceil(Long.valueOf(MILLS_IN_A_DAY) / triggerPerDay); // with ceil the triggerPerDay is a max value
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private int fromTriggerPerDayToSecInterval(long triggerPerDay) {
|
||||
return (int) Math.ceil(Long.valueOf(SEC_IN_A_DAY) / triggerPerDay);
|
||||
}
|
||||
@GetMapping(value = "/status", produces = "application/json")
|
||||
public Map<String, String> getStatus() throws SchedulerException {
|
||||
log.trace("SCHEDULER - GET STATUS");
|
||||
String schedulerState = "";
|
||||
if (schedulerService.getScheduler().isShutdown() || !schedulerService.getScheduler().isStarted())
|
||||
schedulerState = SchedulerStates.STOPPED.toString();
|
||||
else if (schedulerService.getScheduler().isStarted() && schedulerService.getScheduler().isInStandbyMode())
|
||||
schedulerState = SchedulerStates.PAUSED.toString();
|
||||
else
|
||||
schedulerState = SchedulerStates.RUNNING.toString();
|
||||
return Collections.singletonMap("data", schedulerState.toLowerCase());
|
||||
}
|
||||
|
||||
@GetMapping("/config")
|
||||
public SchedulerConfigParam getConfig() throws SchedulerException {
|
||||
log.debug("SCHEDULER - GET CONFIG params");
|
||||
@GetMapping("/pause")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void pause() throws SchedulerException {
|
||||
log.info("SCHEDULER - PAUSE COMMAND");
|
||||
schedulerService.getScheduler().standby();
|
||||
}
|
||||
|
||||
SimpleTrigger jobTrigger = (SimpleTrigger) scheduler.getTrigger(triggerMonitor.getTrigger().getKey());
|
||||
int maxCount = jobTrigger.getRepeatCount() + 1;
|
||||
long triggersPerDay = fromMillsIntervalToTriggerPerDay(jobTrigger.getRepeatInterval());
|
||||
// @PostMapping("/config")
|
||||
// public SchedulerConfigParam postConfig(@RequestBody SchedulerConfigParam config) throws SchedulerException {
|
||||
// log.info("SCHEDULER - NEW CONFIG {}", config);
|
||||
//
|
||||
// int intervalInMills = SchedulerService.fromTriggerPerDayToMillsInterval(config.getTriggerPerDay());
|
||||
//
|
||||
// Trigger newTrigger = TriggerBuilder.newTrigger()
|
||||
// .withSchedule(
|
||||
// SimpleScheduleBuilder.simpleSchedule()
|
||||
// .withIntervalInMilliseconds(intervalInMills)
|
||||
// .withRepeatCount(config.getMaxCount() - 1)
|
||||
// .withMisfireHandlingInstructionNextWithRemainingCount()
|
||||
// )
|
||||
// .build();
|
||||
//
|
||||
// schedulerService.getScheduler().rescheduleJob(schedulerService.getOneTriggerKey().get(), newTrigger);
|
||||
//// triggerMonitor.setTrigger(newTrigger); REMOVEME
|
||||
// return config;
|
||||
// }
|
||||
|
||||
return new SchedulerConfigParam(triggersPerDay, maxCount);
|
||||
}
|
||||
@GetMapping("/resume")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void resume() throws SchedulerException {
|
||||
log.info("SCHEDULER - RESUME COMMAND");
|
||||
schedulerService.getScheduler().start();
|
||||
}
|
||||
|
||||
@GetMapping("/progress")
|
||||
public TriggerStatus getProgressInfo() throws SchedulerException {
|
||||
log.trace("SCHEDULER - GET PROGRESS INFO");
|
||||
TriggerStatus progress = new TriggerStatus();
|
||||
@GetMapping("/run")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void run() throws SchedulerException {
|
||||
log.info("SCHEDULER - START COMMAND");
|
||||
schedulerService.getScheduler().start();
|
||||
}
|
||||
|
||||
SimpleTriggerImpl jobTrigger = (SimpleTriggerImpl) scheduler.getTrigger(triggerMonitor.getTrigger().getKey());
|
||||
if (jobTrigger != null && jobTrigger.getJobKey() != null) {
|
||||
progress.setJobKey(jobTrigger.getJobKey().getName());
|
||||
progress.setJobClass(jobTrigger.getClass().getSimpleName());
|
||||
progress.setTimesTriggered(jobTrigger.getTimesTriggered());
|
||||
progress.setRepeatCount(jobTrigger.getRepeatCount());
|
||||
progress.setFinalFireTime(jobTrigger.getFinalFireTime());
|
||||
progress.setNextFireTime(jobTrigger.getNextFireTime());
|
||||
progress.setPreviousFireTime(jobTrigger.getPreviousFireTime());
|
||||
}
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
@GetMapping(produces = "application/json")
|
||||
public Map<String, String> getStatus() throws SchedulerException {
|
||||
log.trace("SCHEDULER - GET STATUS");
|
||||
String schedulerState = "";
|
||||
if (scheduler.isShutdown() || !scheduler.isStarted())
|
||||
schedulerState = SchedulerStates.STOPPED.toString();
|
||||
else if (scheduler.isStarted() && scheduler.isInStandbyMode())
|
||||
schedulerState = SchedulerStates.PAUSED.toString();
|
||||
else
|
||||
schedulerState = SchedulerStates.RUNNING.toString();
|
||||
return Collections.singletonMap("data", schedulerState.toLowerCase());
|
||||
}
|
||||
|
||||
@GetMapping("/pause")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void pause() throws SchedulerException {
|
||||
log.info("SCHEDULER - PAUSE COMMAND");
|
||||
scheduler.standby();
|
||||
}
|
||||
|
||||
@PostMapping("/config")
|
||||
public SchedulerConfigParam postConfig(@RequestBody SchedulerConfigParam config) throws SchedulerException {
|
||||
log.info("SCHEDULER - NEW CONFIG {}", config);
|
||||
SimpleTrigger trigger = (SimpleTrigger) triggerMonitor.getTrigger();
|
||||
|
||||
TriggerBuilder<SimpleTrigger> triggerBuilder = trigger.getTriggerBuilder();
|
||||
|
||||
int intervalInMills = fromTriggerPerDayToMillsInterval(config.getTriggerPerDay());
|
||||
|
||||
Trigger newTrigger = triggerBuilder
|
||||
.withSchedule(
|
||||
SimpleScheduleBuilder.simpleSchedule()
|
||||
.withIntervalInMilliseconds(intervalInMills)
|
||||
.withRepeatCount(config.getMaxCount() - 1)
|
||||
.withMisfireHandlingInstructionNextWithRemainingCount()
|
||||
)
|
||||
.build();
|
||||
|
||||
scheduler.rescheduleJob(triggerMonitor.getTrigger().getKey(), newTrigger);
|
||||
triggerMonitor.setTrigger(newTrigger);
|
||||
return config;
|
||||
}
|
||||
|
||||
@GetMapping("/resume")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void resume() throws SchedulerException {
|
||||
log.info("SCHEDULER - RESUME COMMAND");
|
||||
scheduler.start();
|
||||
}
|
||||
|
||||
@GetMapping("/run")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void run() throws SchedulerException {
|
||||
log.info("SCHEDULER - START COMMAND");
|
||||
scheduler.start();
|
||||
}
|
||||
|
||||
@GetMapping("/stop")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void stop() throws SchedulerException {
|
||||
log.info("SCHEDULER - STOP COMMAND");
|
||||
scheduler.shutdown(true);
|
||||
}
|
||||
@GetMapping("/stop")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void stop() throws SchedulerException {
|
||||
log.info("SCHEDULER - STOP COMMAND");
|
||||
schedulerService.getScheduler().shutdown(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package it.fabioformosa.quartzmanager.controllers;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import it.fabioformosa.quartzmanager.dto.SchedulerConfigParam;
|
||||
import it.fabioformosa.quartzmanager.dto.TriggerDTO;
|
||||
import it.fabioformosa.quartzmanager.services.SchedulerService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.*;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Slf4j
|
||||
@RequestMapping("/quartz-manager/triggers")
|
||||
@RestController
|
||||
@Api(value = "triggers")
|
||||
public class TriggerController {
|
||||
|
||||
@Value("${quartz-manager.jobClass}")
|
||||
private String jobClassname;
|
||||
|
||||
private Scheduler scheduler;
|
||||
private SchedulerService schedulerService;
|
||||
private ConversionService conversionService;
|
||||
|
||||
public TriggerController(Scheduler scheduler, SchedulerService schedulerService, ConversionService conversionService) {
|
||||
this.scheduler = scheduler;
|
||||
this.schedulerService = schedulerService;
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
@GetMapping("/{name}")
|
||||
public TriggerDTO getTrigger(@PathVariable String name) throws SchedulerException {
|
||||
Trigger trigger = scheduler.getTrigger(new TriggerKey(name));
|
||||
TriggerDTO triggerDTO = conversionService.convert(trigger, TriggerDTO.class);
|
||||
return triggerDTO;
|
||||
}
|
||||
|
||||
@PostMapping("/{name}")
|
||||
public TriggerDTO postTrigger(@PathVariable String name, @RequestBody SchedulerConfigParam config) throws SchedulerException, ClassNotFoundException {
|
||||
log.info("TRIGGER - POST trigger {}", config);
|
||||
int intervalInMills = SchedulerService.fromTriggerPerDayToMillsInterval(config.getTriggerPerDay());
|
||||
|
||||
Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(jobClassname);
|
||||
JobDetail jobDetail = JobBuilder.newJob()
|
||||
.ofType(jobClass)
|
||||
.storeDurably(false)
|
||||
.build();
|
||||
|
||||
Trigger newTrigger = TriggerBuilder.newTrigger()
|
||||
.withSchedule(
|
||||
SimpleScheduleBuilder.simpleSchedule()
|
||||
.withIntervalInMilliseconds(intervalInMills)
|
||||
.withRepeatCount(config.getMaxCount() - 1)
|
||||
.withMisfireHandlingInstructionNextWithRemainingCount()
|
||||
)
|
||||
.build();
|
||||
|
||||
// Optional<TriggerKey> optionalTriggerKey = schedulerService.getTriggerByKey(name);
|
||||
// TriggerKey triggerKey = optionalTriggerKey.orElse(TriggerKey.triggerKey(name));
|
||||
|
||||
scheduler.scheduleJob(jobDetail, newTrigger);
|
||||
// scheduler.rescheduleJob(triggerKey, newTrigger);
|
||||
|
||||
TriggerDTO newTriggerDTO = conversionService.convert(newTrigger, TriggerDTO.class);
|
||||
|
||||
log.info("Rescheduled new trigger {}", newTriggerDTO);
|
||||
return newTriggerDTO;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package it.fabioformosa.quartzmanager.converters;
|
||||
|
||||
import it.fabioformosa.metamorphosis.core.converters.AbstractBaseConverterToDTO;
|
||||
import it.fabioformosa.quartzmanager.dto.JobKeyDTO;
|
||||
import org.quartz.JobKey;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class JobKeyToJobKeyDTO extends AbstractBaseConverterToDTO<JobKey, JobKeyDTO> {
|
||||
@Override
|
||||
protected void convert(JobKey source, JobKeyDTO target) {
|
||||
target.setName(source.getName());
|
||||
target.setGroup(source.getGroup());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package it.fabioformosa.quartzmanager.converters;
|
||||
|
||||
import it.fabioformosa.metamorphosis.core.converters.AbstractBaseConverterToDTO;
|
||||
import it.fabioformosa.quartzmanager.dto.SchedulerDTO;
|
||||
import lombok.SneakyThrows;
|
||||
import org.quartz.Scheduler;
|
||||
import org.quartz.impl.matchers.GroupMatcher;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class SchedulerToSchedulerDTO extends AbstractBaseConverterToDTO<Scheduler, SchedulerDTO> {
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
protected void convert(Scheduler source, SchedulerDTO target) {
|
||||
target.setName(source.getSchedulerName());
|
||||
target.setInstanceId(source.getSchedulerInstanceId());
|
||||
target.setTriggerKeys(source.getTriggerKeys(GroupMatcher.anyTriggerGroup()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package it.fabioformosa.quartzmanager.converters;
|
||||
|
||||
import it.fabioformosa.metamorphosis.core.converters.AbstractBaseConverterToDTO;
|
||||
import it.fabioformosa.quartzmanager.dto.TriggerKeyDTO;
|
||||
import org.quartz.TriggerKey;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class TriggerKeyToTriggerKeyDTO extends AbstractBaseConverterToDTO<TriggerKey, TriggerKeyDTO> {
|
||||
|
||||
@Override
|
||||
protected void convert(TriggerKey source, TriggerKeyDTO target) {
|
||||
target.setName(source.getName());
|
||||
target.setGroup(source.getGroup());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package it.fabioformosa.quartzmanager.converters;
|
||||
|
||||
import it.fabioformosa.metamorphosis.core.converters.AbstractBaseConverterToDTO;
|
||||
import it.fabioformosa.quartzmanager.dto.JobKeyDTO;
|
||||
import it.fabioformosa.quartzmanager.dto.TriggerDTO;
|
||||
import it.fabioformosa.quartzmanager.dto.TriggerKeyDTO;
|
||||
import org.quartz.JobKey;
|
||||
import org.quartz.Trigger;
|
||||
import org.quartz.TriggerKey;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class TriggerToTriggerDTO extends AbstractBaseConverterToDTO<Trigger, TriggerDTO> {
|
||||
|
||||
@Override
|
||||
protected void convert(Trigger source, TriggerDTO target) {
|
||||
TriggerKey triggerKey = source.getKey();
|
||||
TriggerKeyDTO triggerKeyDTO = conversionService.convert(triggerKey, TriggerKeyDTO.class);
|
||||
target.setTriggerKeyDTO(triggerKeyDTO);
|
||||
|
||||
target.setStartTime(source.getStartTime());
|
||||
target.setDescription(source.getDescription());
|
||||
target.setEndTime(source.getEndTime());
|
||||
target.setFinalFireTime(source.getFinalFireTime());
|
||||
target.setMisfireInstruction(source.getMisfireInstruction());
|
||||
target.setNextFireTime(source.getNextFireTime());
|
||||
target.setPriority(source.getPriority());
|
||||
target.setMayFireAgain(source.mayFireAgain());
|
||||
|
||||
JobKey jobKey = source.getJobKey();
|
||||
JobKeyDTO jobKeyDTO = conversionService.convert(jobKey, JobKeyDTO.class);
|
||||
target.setJobKeyDTO(jobKeyDTO);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package it.fabioformosa.quartzmanager.dto;
|
||||
|
||||
public class JobKeyDTO {
|
||||
private String name;
|
||||
private String group;
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setGroup(String group) {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +1,14 @@
|
||||
package it.fabioformosa.quartzmanager.dto;
|
||||
|
||||
public class SchedulerConfigParam {
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class SchedulerConfigParam {
|
||||
public long triggerPerDay;
|
||||
public int maxCount;
|
||||
|
||||
public SchedulerConfigParam() {
|
||||
super();
|
||||
}
|
||||
|
||||
public SchedulerConfigParam(long triggerPerDay, int maxCount) {
|
||||
super();
|
||||
this.triggerPerDay = triggerPerDay;
|
||||
this.maxCount = maxCount;
|
||||
}
|
||||
|
||||
public int getMaxCount() {
|
||||
return maxCount;
|
||||
}
|
||||
|
||||
public long getTriggerPerDay() {
|
||||
return triggerPerDay;
|
||||
}
|
||||
|
||||
public void setMaxCount(int maxCount) {
|
||||
this.maxCount = maxCount;
|
||||
}
|
||||
|
||||
public void setTriggerPerDay(long triggerPerDay) {
|
||||
this.triggerPerDay = triggerPerDay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SchedulerConfigParam [triggerPerDay=" + triggerPerDay
|
||||
+ ", maxCount=" + maxCount + "]";
|
||||
}
|
||||
|
||||
public int timesTriggered;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package it.fabioformosa.quartzmanager.dto;
|
||||
|
||||
import org.quartz.TriggerKey;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class SchedulerDTO {
|
||||
private String name;
|
||||
private String instanceId;
|
||||
private Set<TriggerKey> triggerKeys;
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setInstanceId(String instanceId) {
|
||||
this.instanceId = instanceId;
|
||||
}
|
||||
|
||||
public String getInstanceId() {
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
public void setTriggerKeys(Set<TriggerKey> triggerKeys) {
|
||||
this.triggerKeys = triggerKeys;
|
||||
}
|
||||
|
||||
public Set<TriggerKey> getTriggerKeys() {
|
||||
return triggerKeys;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package it.fabioformosa.quartzmanager.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class TriggerDTO {
|
||||
private TriggerKeyDTO triggerKeyDTO;
|
||||
private int priority;
|
||||
private Date startTime;
|
||||
private String description;
|
||||
private Date endTime;
|
||||
private Date finalFireTime;
|
||||
private int misfireInstruction;
|
||||
private Date nextFireTime;
|
||||
private JobKeyDTO jobKeyDTO;
|
||||
private boolean mayFireAgain;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package it.fabioformosa.quartzmanager.dto;
|
||||
|
||||
public class TriggerKeyDTO {
|
||||
private String name;
|
||||
private String group;
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setGroup(String group) {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package it.fabioformosa.quartzmanager.services;
|
||||
|
||||
import it.fabioformosa.quartzmanager.common.utils.Try;
|
||||
import org.quartz.Scheduler;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.quartz.SimpleTrigger;
|
||||
import org.quartz.TriggerKey;
|
||||
import org.quartz.impl.matchers.GroupMatcher;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class SchedulerService {
|
||||
|
||||
public static final int MILLS_IN_A_DAY = 1000 * 60 * 60 * 24;
|
||||
public static final int SEC_IN_A_DAY = 60 * 60 * 24;
|
||||
|
||||
private Scheduler scheduler;
|
||||
|
||||
public SchedulerService(Scheduler scheduler) {
|
||||
this.scheduler = scheduler;
|
||||
}
|
||||
|
||||
public static int fromTriggerPerDayToMillsInterval(long triggerPerDay) {
|
||||
return (int) Math.ceil(Long.valueOf(SchedulerService.MILLS_IN_A_DAY) / triggerPerDay); // with ceil the triggerPerDay is a max value
|
||||
}
|
||||
|
||||
public static int fromTriggerPerDayToSecInterval(long triggerPerDay) {
|
||||
return (int) Math.ceil(Long.valueOf(SchedulerService.SEC_IN_A_DAY) / triggerPerDay);
|
||||
}
|
||||
|
||||
public static long fromMillsIntervalToTriggerPerDay(long repeatIntervalInMills) {
|
||||
return (int) Math.ceil(MILLS_IN_A_DAY / repeatIntervalInMills);
|
||||
}
|
||||
|
||||
public Scheduler getScheduler() {
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
public Optional<TriggerKey> getTriggerByKey(String triggerKeyName) throws SchedulerException {
|
||||
return scheduler.getTriggerKeys(GroupMatcher.anyGroup()).stream()
|
||||
.filter(triggerKey -> triggerKey.getName().equals(triggerKeyName))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
public Optional<SimpleTrigger> getOneSimpleTrigger() throws SchedulerException {
|
||||
return getOneTriggerKey()
|
||||
.map(Try.with(triggerKey -> scheduler.getTrigger(triggerKey)))
|
||||
.filter(Try::isSuccess).map(Try::getSuccess)
|
||||
.filter(trigger -> trigger instanceof SimpleTrigger)
|
||||
.map(trigger -> (SimpleTrigger) trigger);
|
||||
}
|
||||
|
||||
public Optional<TriggerKey> getOneTriggerKey() throws SchedulerException {
|
||||
return scheduler.getTriggerKeys(GroupMatcher.anyGroup()).stream()
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,69 +1,61 @@
|
||||
package it.fabioformosa.quartzmanager.persistence;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
import it.fabioformosa.quartzmanager.common.properties.QuartzModuleProperties;
|
||||
import liquibase.integration.spring.SpringLiquibase;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@PropertySource("classpath:quartz-manager-application-persistence.properties")
|
||||
public class PersistenceConfig {
|
||||
|
||||
@Data
|
||||
public class PersistenceDatasourceProps {
|
||||
private String url;
|
||||
private String changeLog;
|
||||
private String contexts;
|
||||
private String user;
|
||||
private String password;
|
||||
}
|
||||
|
||||
// @Data
|
||||
// public class QuartzModuleProperties{
|
||||
// private Properties properties;
|
||||
// }
|
||||
|
||||
@Bean
|
||||
public SpringLiquibase liquibase(PersistenceDatasourceProps persistenceDatasourceProps, DataSource quartzManagerDatasource) {
|
||||
SpringLiquibase liquibase = new SpringLiquibase();
|
||||
liquibase.setContexts(persistenceDatasourceProps.getContexts());
|
||||
liquibase.setChangeLog(persistenceDatasourceProps.getChangeLog());
|
||||
liquibase.setDataSource(quartzManagerDatasource);
|
||||
liquibase.setDropFirst(false);
|
||||
return liquibase;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "spring.liquibase")
|
||||
public PersistenceDatasourceProps persistenceDatasourceProps() {
|
||||
return new PersistenceDatasourceProps();
|
||||
}
|
||||
|
||||
@Bean("quartzPersistenceProperties")
|
||||
@ConfigurationProperties(prefix = "spring.quartz")
|
||||
public QuartzModuleProperties persistenceQuartzProps() {
|
||||
return new QuartzModuleProperties();
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public DataSource quartzManagerDatasource(PersistenceDatasourceProps persistenceDatasourceProps) {
|
||||
return DataSourceBuilder.create()
|
||||
.url(persistenceDatasourceProps.getUrl())
|
||||
.driverClassName("org.postgresql.Driver")
|
||||
.username(persistenceDatasourceProps.getUser())
|
||||
.password(persistenceDatasourceProps.getPassword())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
package it.fabioformosa.quartzmanager.persistence;
|
||||
|
||||
import it.fabioformosa.quartzmanager.common.properties.QuartzModuleProperties;
|
||||
import liquibase.integration.spring.SpringLiquibase;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:quartz-manager-application-persistence.properties")
|
||||
public class PersistenceConfig {
|
||||
|
||||
@Data
|
||||
public class PersistenceDatasourceProps {
|
||||
private String url;
|
||||
private String changeLog;
|
||||
private String contexts;
|
||||
private String user;
|
||||
private String password;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SpringLiquibase liquibase(PersistenceDatasourceProps persistenceDatasourceProps, DataSource quartzManagerDatasource) {
|
||||
SpringLiquibase liquibase = new SpringLiquibase();
|
||||
liquibase.setContexts(persistenceDatasourceProps.getContexts());
|
||||
liquibase.setChangeLog(persistenceDatasourceProps.getChangeLog());
|
||||
liquibase.setDataSource(quartzManagerDatasource);
|
||||
liquibase.setDropFirst(false);
|
||||
return liquibase;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "spring.liquibase")
|
||||
public PersistenceDatasourceProps persistenceDatasourceProps() {
|
||||
return new PersistenceDatasourceProps();
|
||||
}
|
||||
|
||||
@Bean("quartzPersistenceProperties")
|
||||
@ConfigurationProperties(prefix = "spring.quartz")
|
||||
public QuartzModuleProperties persistenceQuartzProps() {
|
||||
return new QuartzModuleProperties();
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public DataSource quartzManagerDatasource(PersistenceDatasourceProps persistenceDatasourceProps) {
|
||||
return DataSourceBuilder.create()
|
||||
.url(persistenceDatasourceProps.getUrl())
|
||||
.driverClassName("org.postgresql.Driver")
|
||||
.username(persistenceDatasourceProps.getUser())
|
||||
.password(persistenceDatasourceProps.getPassword())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
<logger name="it.fabioformosa" level="DEBUG" additivity="false">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
<logger name="it.fabioformosa.quartzmanager.security.helpers.impl.JwtTokenAuthenticationFilter" level="WARN" additivity="false">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
<logger name="org.springframework" level="WARN" additivity="false">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
@@ -23,4 +26,4 @@
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
||||
Reference in New Issue
Block a user