feat(schedule-application): enable scheduling application using config file (#19470)

- added schedule to app private config
- reschedule a schedule application job in quartz if it exists.

(cherry picked from commit 5482b94a57b58fc87575425326e297f2e6bdc680)
This commit is contained in:
Imri Paran 2025-01-27 09:09:46 +01:00 committed by sushi30
parent e0fa67726d
commit e9f55f61e9
5 changed files with 35 additions and 10 deletions

View File

@ -105,7 +105,7 @@ public class AbstractNativeApplication implements NativeApplication {
AppRuntime runtime = JsonUtils.convertValue(app.getRuntime(), ScheduledExecutionContext.class); AppRuntime runtime = JsonUtils.convertValue(app.getRuntime(), ScheduledExecutionContext.class);
validateServerExecutableApp(runtime); validateServerExecutableApp(runtime);
// Schedule New Application Run // Schedule New Application Run
AppScheduler.getInstance().addApplicationSchedule(app); AppScheduler.getInstance().scheduleApplication(app);
} }
public void scheduleExternal() { public void scheduleExternal() {

View File

@ -176,7 +176,7 @@ public class ApplicationHandler {
appRepository.getUpdater(currentApp, updatedApp, EntityRepository.Operation.PATCH); appRepository.getUpdater(currentApp, updatedApp, EntityRepository.Operation.PATCH);
updater.update(); updater.update();
AppScheduler.getInstance().deleteScheduledApplication(updatedApp); AppScheduler.getInstance().deleteScheduledApplication(updatedApp);
AppScheduler.getInstance().addApplicationSchedule(updatedApp); AppScheduler.getInstance().scheduleApplication(updatedApp);
LOG.info("migrated app configuration for {}", application.getName()); LOG.info("migrated app configuration for {}", application.getName());
} }
@ -197,7 +197,7 @@ public class ApplicationHandler {
LOG.info("corrupt entry for app {}, reinstalling", application.getName()); LOG.info("corrupt entry for app {}, reinstalling", application.getName());
App app = appRepository.getDao().findEntityByName(application.getName()); App app = appRepository.getDao().findEntityByName(application.getName());
AppScheduler.getInstance().deleteScheduledApplication(app); AppScheduler.getInstance().deleteScheduledApplication(app);
AppScheduler.getInstance().addApplicationSchedule(app); AppScheduler.getInstance().scheduleApplication(app);
} }
} }

View File

@ -156,10 +156,13 @@ public class AppScheduler {
throw new UnhandledServerException("App Scheduler is not Initialized"); throw new UnhandledServerException("App Scheduler is not Initialized");
} }
public void addApplicationSchedule(App application) { public void scheduleApplication(App application) {
try { try {
if (scheduler.getJobDetail(new JobKey(application.getName(), APPS_JOB_GROUP)) != null) { if (scheduler.getJobDetail(new JobKey(application.getName(), APPS_JOB_GROUP)) != null) {
LOG.info("Job already exists for the application, skipping the scheduling"); LOG.info(
"Job already exists for the application {}, rescheduling it", application.getName());
scheduler.rescheduleJob(
new TriggerKey(application.getName(), APPS_TRIGGER_GROUP), trigger(application));
return; return;
} }
AppRuntime context = getAppRuntime(application); AppRuntime context = getAppRuntime(application);

View File

@ -21,6 +21,9 @@
"description": "Flag to enable/disable preview for the application. If the app is in preview mode, it can't be installed.", "description": "Flag to enable/disable preview for the application. If the app is in preview mode, it can't be installed.",
"default": false "default": false
}, },
"schedule": {
"$ref": "../entity/applications/app.json#/definitions/appSchedule"
},
"parameters": { "parameters": {
"javaType": "org.openmetadata.schema.api.configuration.apps.Parameters", "javaType": "org.openmetadata.schema.api.configuration.apps.Parameters",
"description": "Parameters to initialize the Applications.", "description": "Parameters to initialize the Applications.",

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2024 Collate. * Copyright 2025 Collate.
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
@ -10,9 +10,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/**
/**
* This schema defines a list of configurations for the Application Framework * This schema defines a list of configurations for the Application Framework
*/ */
export interface AppsPrivateConfiguration { export interface AppsPrivateConfiguration {
@ -38,5 +36,26 @@ export interface AppPrivateConfig {
* Flag to enable/disable preview for the application. If the app is in preview mode, it * Flag to enable/disable preview for the application. If the app is in preview mode, it
* can't be installed. * can't be installed.
*/ */
preview?: boolean; preview?: boolean;
schedule?: any[] | boolean | AppScheduleClass | number | number | null | string;
}
export interface AppScheduleClass {
/**
* Cron Expression in case of Custom scheduled Trigger
*/
cronExpression?: string;
scheduleTimeline: ScheduleTimeline;
}
/**
* This schema defines the Application ScheduleTimeline Options
*/
export enum ScheduleTimeline {
Custom = "Custom",
Daily = " Daily",
Hourly = "Hourly",
Monthly = "Monthly",
None = "None",
Weekly = "Weekly",
} }