@ruiapp/rapid-core 0.6.4 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @ruiapp/rapid-core
2
2
 
3
+ ## 0.7.0
4
+
5
+ - feature: added server.registerCronJob to allow plugins register cron jobs.
6
+
3
7
  ## 0.2.4
4
8
 
5
9
  ### Patch Changes
@@ -28,6 +28,8 @@ declare class PluginManager {
28
28
  configureServices(applicationConfig: RpdApplicationConfig): Promise<void>;
29
29
  /** 配置路由 */
30
30
  configureRoutes(applicationConfig: RpdApplicationConfig): Promise<void>;
31
+ /** 配置定时任务 */
32
+ registerCronJobs(): Promise<void>;
31
33
  /** 在应用配置加载完成后调用。此时插件可以进行一些数据的初始化工作。 */
32
34
  onApplicationLoaded(applicationConfig: RpdApplicationConfig): Promise<void>;
33
35
  /** 在应用准备完成后调用。此时服务器已经可以处理网络请求。 */
@@ -21,7 +21,7 @@ export declare class RouteContext {
21
21
  set(headerName: string, headerValue: string): void;
22
22
  json(obj: any, status?: HttpStatus, headers?: HeadersInit): void;
23
23
  redirect(url: string, status?: HttpStatus): void;
24
- getDbTransactionClient(): IDatabaseClient | null;
24
+ getDbTransactionClient(): IDatabaseClient | undefined;
25
25
  beginDbTransaction(): Promise<IDatabaseClient>;
26
26
  commitDbTransaction(): Promise<void>;
27
27
  rollbackDbTransaction(): Promise<void>;
@@ -4,6 +4,7 @@ import { Next, RouteContext } from "./routeContext";
4
4
  import EntityManager from "../dataAccess/entityManager";
5
5
  import { Logger } from "../facilities/log/LogFacility";
6
6
  import { FacilityFactory } from "./facility";
7
+ import { CronJobConfiguration } from "../types/cron-job-types";
7
8
  export interface IRpdServer {
8
9
  config: RapidServerConfig;
9
10
  databaseConfig: IDatabaseConfig;
@@ -32,6 +33,8 @@ export interface IRpdServer {
32
33
  beforeRunRouteActions(handlerContext: ActionHandlerContext): Promise<void>;
33
34
  beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
34
35
  beforeUpdateEntity(model: RpdDataModel, options: UpdateEntityByIdOptions, currentEntity: any): Promise<void>;
36
+ registerCronJob(job: CronJobConfiguration): void;
37
+ listCronJobs(): CronJobConfiguration[];
35
38
  }
36
39
  export type RpdConfigurationItemTypes = "integer" | "text" | "boolean" | "date" | "datetime" | "json";
37
40
  export interface RpdConfigurationItemOptions {
@@ -94,6 +97,8 @@ export interface RapidPlugin {
94
97
  configureServices?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
95
98
  /** 配置路由 */
96
99
  configureRoutes?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
100
+ /** 注册定时任务 */
101
+ registerCronJobs?: (server: IRpdServer) => Promise<any>;
97
102
  /** 在应用配置加载完成后调用。此时插件可以进行一些数据的初始化工作。 */
98
103
  onApplicationLoaded?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
99
104
  /** 在应用准备完成后调用。此时服务器已经可以处理网络请求,可以对外广播消息。 */
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./types";
2
+ export * from "./types/cron-job-types";
2
3
  export * from "./server";
3
4
  export * from "./core/facility";
4
5
  export * from "./core/request";
package/dist/index.js CHANGED
@@ -839,6 +839,14 @@ class PluginManager {
839
839
  }
840
840
  }
841
841
  }
842
+ /** 配置定时任务 */
843
+ async registerCronJobs() {
844
+ for (const plugin of this.#plugins) {
845
+ if (plugin.registerCronJobs) {
846
+ await plugin.registerCronJobs(this.#server);
847
+ }
848
+ }
849
+ }
842
850
  /** 在应用配置加载完成后调用。此时插件可以进行一些数据的初始化工作。 */
843
851
  async onApplicationLoaded(applicationConfig) {
844
852
  for (const plugin of this.#plugins) {
@@ -1067,7 +1075,6 @@ class RouteContext {
1067
1075
  }
1068
1076
  constructor(server, request) {
1069
1077
  this.#server = server;
1070
- this.#dbTransactionClient = null;
1071
1078
  this.databaseAccessor = server.getDatabaseAccessor();
1072
1079
  this.request = request;
1073
1080
  this.state = {};
@@ -4262,6 +4269,9 @@ class RapidServer {
4262
4269
  #entityBeforeResponseEventEmitters;
4263
4270
  #entityWatchers;
4264
4271
  #appEntityWatchers;
4272
+ #cronJobs;
4273
+ #appCronJobs;
4274
+ #disableCronJobs;
4265
4275
  #cachedEntityManager;
4266
4276
  #services;
4267
4277
  queryBuilder;
@@ -4305,6 +4315,9 @@ class RapidServer {
4305
4315
  this.registerEventHandler("entity.beforeResponse", this.#handleEntityEvent.bind(this, "entity.beforeResponse"));
4306
4316
  this.#entityWatchers = [];
4307
4317
  this.#appEntityWatchers = options.entityWatchers || [];
4318
+ this.#cronJobs = [];
4319
+ this.#appCronJobs = options.cronJobs || [];
4320
+ this.#disableCronJobs = !!options.disableCronJobs;
4308
4321
  this.#services = new Map();
4309
4322
  this.queryBuilder = new QueryBuilder({
4310
4323
  dbDefaultSchema: options.databaseConfig.dbDefaultSchema,
@@ -4457,6 +4470,16 @@ class RapidServer {
4457
4470
  getService(name) {
4458
4471
  return this.#services.get(name);
4459
4472
  }
4473
+ registerCronJob(job) {
4474
+ const jobDuplicate = lodash.find(this.#cronJobs, (item) => item.code === job.code);
4475
+ if (jobDuplicate) {
4476
+ this.#logger.warn(`Duplicated cron job with code "${job.code}"`);
4477
+ }
4478
+ this.#cronJobs.push(job);
4479
+ }
4480
+ listCronJobs() {
4481
+ return [...this.#cronJobs, ...this.#appCronJobs];
4482
+ }
4460
4483
  async start() {
4461
4484
  this.#logger.info("Starting rapid server...");
4462
4485
  const pluginManager = this.#pluginManager;
@@ -4498,6 +4521,9 @@ class RapidServer {
4498
4521
  }
4499
4522
  }
4500
4523
  await this.configureApplication();
4524
+ if (!this.#disableCronJobs) {
4525
+ await pluginManager.registerCronJobs();
4526
+ }
4501
4527
  this.#logger.info(`Rapid server ready.`);
4502
4528
  await pluginManager.onApplicationReady(this.#applicationConfig);
4503
4529
  }
@@ -8421,10 +8447,8 @@ var runCronJob = {
8421
8447
  var pluginRoutes$1 = [runCronJob];
8422
8448
 
8423
8449
  class CronJobPlugin {
8424
- #jobs;
8425
- constructor(options) {
8426
- this.#jobs = options.jobs || [];
8427
- }
8450
+ #server;
8451
+ constructor() { }
8428
8452
  get code() {
8429
8453
  return "cronJob";
8430
8454
  }
@@ -8440,7 +8464,9 @@ class CronJobPlugin {
8440
8464
  get configurations() {
8441
8465
  return [];
8442
8466
  }
8443
- async initPlugin(server) { }
8467
+ async initPlugin(server) {
8468
+ this.#server = server;
8469
+ }
8444
8470
  async registerMiddlewares(server) { }
8445
8471
  async registerActionHandlers(server) {
8446
8472
  for (const actionHandler of pluginActionHandlers$1) {
@@ -8458,7 +8484,8 @@ class CronJobPlugin {
8458
8484
  }
8459
8485
  async onApplicationLoaded(server, applicationConfig) { }
8460
8486
  async onApplicationReady(server, applicationConfig) {
8461
- for (const job of this.#jobs) {
8487
+ const cronJobs = server.listCronJobs();
8488
+ for (const job of cronJobs) {
8462
8489
  const jobInstance = cron__namespace.CronJob.from({
8463
8490
  ...(job.jobOptions || {}),
8464
8491
  cronTime: job.cronTime,
@@ -8471,7 +8498,7 @@ class CronJobPlugin {
8471
8498
  }
8472
8499
  }
8473
8500
  getJobConfigurationByCode(code) {
8474
- return lodash.find(this.#jobs, (job) => job.code === code);
8501
+ return lodash.find(this.#server.listCronJobs(), (job) => job.code === code);
8475
8502
  }
8476
8503
  async executeJob(server, job) {
8477
8504
  const logger = server.getLogger();
@@ -1,9 +1,9 @@
1
1
  import type { RpdApplicationConfig } from "../../types";
2
- import { CronJobConfiguration, CronJobPluginInitOptions } from "./CronJobPluginTypes";
2
+ import { CronJobConfiguration } from "../../types/cron-job-types";
3
3
  import { IRpdServer, RapidPlugin, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "../../core/server";
4
4
  declare class CronJobPlugin implements RapidPlugin {
5
5
  #private;
6
- constructor(options: CronJobPluginInitOptions);
6
+ constructor();
7
7
  get code(): string;
8
8
  get description(): string;
9
9
  get extendingAbilities(): RpdServerPluginExtendingAbilities[];
@@ -1,50 +1,3 @@
1
- import { ActionHandlerContext } from "../../core/actionHandler";
2
- export interface CronJobConfiguration {
3
- /**
4
- * 定时任务编号
5
- */
6
- code: string;
7
- /**
8
- * 定时任务描述
9
- */
10
- description?: string;
11
- /**
12
- * crontab 表达式
13
- */
14
- cronTime: string;
15
- /**
16
- * 任务设置
17
- */
18
- jobOptions?: CronJobOptions;
19
- /**
20
- * 任务处理程序编号。当指定处理程序编号时,忽略 handler 配置。
21
- */
22
- actionHandlerCode?: string;
23
- /**
24
- * 定时任务处理程序
25
- * @param ctx
26
- * @param options
27
- * @returns
28
- */
29
- handler?: (ctx: ActionHandlerContext, options: any) => Promise<void>;
30
- /**
31
- * 处理定时任务时的设置选项
32
- */
33
- handleOptions?: any;
34
- }
35
- export interface CronJobOptions {
36
- /**
37
- * Instantly triggers the onTick function post initialization. Default is false.
38
- */
39
- runOnInit?: boolean;
40
- /**
41
- * If true, no additional instances of the onTick callback function will run until the current onTick callback has completed. Any new scheduled executions that occur while the current callback is running will be skipped entirely. Default is false.
42
- */
43
- waitForCompletion?: boolean;
44
- }
45
- export interface CronJobPluginInitOptions {
46
- jobs: CronJobConfiguration[];
47
- }
48
1
  export type RunCronJobActionHandlerOptions = {
49
2
  code?: string;
50
3
  };
package/dist/server.d.ts CHANGED
@@ -5,6 +5,7 @@ import { Next } from "./core/routeContext";
5
5
  import EntityManager from "./dataAccess/entityManager";
6
6
  import { Logger } from "./facilities/log/LogFacility";
7
7
  import { FacilityFactory } from "./core/facility";
8
+ import { CronJobConfiguration } from "./types/cron-job-types";
8
9
  export interface InitServerOptions {
9
10
  logger: Logger;
10
11
  databaseAccessor: IDatabaseAccessor;
@@ -14,6 +15,14 @@ export interface InitServerOptions {
14
15
  facilityFactories?: FacilityFactory[];
15
16
  plugins?: RapidPlugin[];
16
17
  entityWatchers?: EntityWatcherType[];
18
+ /**
19
+ * Application level cron jobs.
20
+ */
21
+ cronJobs?: CronJobConfiguration[];
22
+ /**
23
+ * All cron jobs of the server will be disabled if set `true`.
24
+ */
25
+ disableCronJobs?: boolean;
17
26
  }
18
27
  export declare class RapidServer implements IRpdServer {
19
28
  #private;
@@ -37,6 +46,8 @@ export declare class RapidServer implements IRpdServer {
37
46
  emitEvent<TEventName extends keyof RpdServerEventTypes>(event: EmitServerEventOptions<TEventName>): Promise<void>;
38
47
  registerService(name: string, service: any): void;
39
48
  getService<TService>(name: string): TService;
49
+ registerCronJob(job: CronJobConfiguration): void;
50
+ listCronJobs(): CronJobConfiguration[];
40
51
  start(): Promise<void>;
41
52
  configureApplication(): Promise<void>;
42
53
  registerFacilityFactory(factory: FacilityFactory): void;
@@ -0,0 +1,44 @@
1
+ import { ActionHandlerContext } from "../core/actionHandler";
2
+ export interface CronJobConfiguration {
3
+ /**
4
+ * 定时任务编号
5
+ */
6
+ code: string;
7
+ /**
8
+ * 定时任务描述
9
+ */
10
+ description?: string;
11
+ /**
12
+ * crontab 表达式
13
+ */
14
+ cronTime: string;
15
+ /**
16
+ * 任务设置
17
+ */
18
+ jobOptions?: CronJobOptions;
19
+ /**
20
+ * 任务处理程序编号。当指定处理程序编号时,忽略 handler 配置。
21
+ */
22
+ actionHandlerCode?: string;
23
+ /**
24
+ * 定时任务处理程序
25
+ * @param ctx
26
+ * @param options
27
+ * @returns
28
+ */
29
+ handler?: (ctx: ActionHandlerContext, options: any) => Promise<void>;
30
+ /**
31
+ * 处理定时任务时的设置选项
32
+ */
33
+ handleOptions?: any;
34
+ }
35
+ export interface CronJobOptions {
36
+ /**
37
+ * Instantly triggers the onTick function post initialization. Default is false.
38
+ */
39
+ runOnInit?: boolean;
40
+ /**
41
+ * If true, no additional instances of the onTick callback function will run until the current onTick callback has completed. Any new scheduled executions that occur while the current callback is running will be skipped entirely. Default is false.
42
+ */
43
+ waitForCompletion?: boolean;
44
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruiapp/rapid-core",
3
- "version": "0.6.4",
3
+ "version": "0.7.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -117,6 +117,15 @@ class PluginManager {
117
117
  }
118
118
  }
119
119
 
120
+ /** 配置定时任务 */
121
+ async registerCronJobs() {
122
+ for (const plugin of this.#plugins) {
123
+ if (plugin.registerCronJobs) {
124
+ await plugin.registerCronJobs(this.#server);
125
+ }
126
+ }
127
+ }
128
+
120
129
  /** 在应用配置加载完成后调用。此时插件可以进行一些数据的初始化工作。 */
121
130
  async onApplicationLoaded(applicationConfig: RpdApplicationConfig) {
122
131
  for (const plugin of this.#plugins) {
@@ -20,7 +20,7 @@ export class RouteContext {
20
20
  params: Record<string, string>;
21
21
  routeConfig: any;
22
22
  #server: IRpdServer;
23
- #dbTransactionClient: IDatabaseClient | null;
23
+ #dbTransactionClient: IDatabaseClient | undefined;
24
24
 
25
25
  static newSystemOperationContext(server: IRpdServer) {
26
26
  return new RouteContext(server);
@@ -28,7 +28,6 @@ export class RouteContext {
28
28
 
29
29
  constructor(server: IRpdServer, request?: RapidRequest) {
30
30
  this.#server = server;
31
- this.#dbTransactionClient = null;
32
31
  this.databaseAccessor = server.getDatabaseAccessor();
33
32
  this.request = request;
34
33
  this.state = {};
@@ -68,7 +67,7 @@ export class RouteContext {
68
67
  this.response.redirect(url, status);
69
68
  }
70
69
 
71
- getDbTransactionClient(): IDatabaseClient | null {
70
+ getDbTransactionClient(): IDatabaseClient | undefined {
72
71
  return this.#dbTransactionClient;
73
72
  }
74
73
 
@@ -21,6 +21,7 @@ import { Next, RouteContext } from "./routeContext";
21
21
  import EntityManager from "~/dataAccess/entityManager";
22
22
  import { Logger } from "~/facilities/log/LogFacility";
23
23
  import { FacilityFactory } from "./facility";
24
+ import { CronJobConfiguration } from "~/types/cron-job-types";
24
25
 
25
26
  export interface IRpdServer {
26
27
  config: RapidServerConfig;
@@ -53,6 +54,9 @@ export interface IRpdServer {
53
54
  beforeRunRouteActions(handlerContext: ActionHandlerContext): Promise<void>;
54
55
  beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
55
56
  beforeUpdateEntity(model: RpdDataModel, options: UpdateEntityByIdOptions, currentEntity: any): Promise<void>;
57
+
58
+ registerCronJob(job: CronJobConfiguration): void;
59
+ listCronJobs(): CronJobConfiguration[];
56
60
  }
57
61
 
58
62
  export type RpdConfigurationItemTypes = "integer" | "text" | "boolean" | "date" | "datetime" | "json";
@@ -130,6 +134,8 @@ export interface RapidPlugin {
130
134
  configureServices?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
131
135
  /** 配置路由 */
132
136
  configureRoutes?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
137
+ /** 注册定时任务 */
138
+ registerCronJobs?: (server: IRpdServer) => Promise<any>;
133
139
  /** 在应用配置加载完成后调用。此时插件可以进行一些数据的初始化工作。 */
134
140
  onApplicationLoaded?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
135
141
  /** 在应用准备完成后调用。此时服务器已经可以处理网络请求,可以对外广播消息。 */
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ import { fixBigIntJSONSerialize } from "./polyfill";
2
2
  fixBigIntJSONSerialize();
3
3
 
4
4
  export * from "./types";
5
+ export * from "./types/cron-job-types";
5
6
  export * from "./server";
6
7
 
7
8
  export * from "./core/facility";
@@ -2,7 +2,7 @@ import * as cron from "cron";
2
2
  import type { RpdApplicationConfig } from "~/types";
3
3
  import pluginActionHandlers from "./actionHandlers";
4
4
  import pluginRoutes from "./routes";
5
- import { CronJobConfiguration, CronJobPluginInitOptions } from "./CronJobPluginTypes";
5
+ import { CronJobConfiguration } from "~/types/cron-job-types";
6
6
  import {
7
7
  IRpdServer,
8
8
  RapidPlugin,
@@ -14,11 +14,9 @@ import { ActionHandlerContext } from "~/core/actionHandler";
14
14
  import { find } from "lodash";
15
15
 
16
16
  class CronJobPlugin implements RapidPlugin {
17
- #jobs: CronJobConfiguration[];
17
+ #server: IRpdServer;
18
18
 
19
- constructor(options: CronJobPluginInitOptions) {
20
- this.#jobs = options.jobs || [];
21
- }
19
+ constructor() {}
22
20
 
23
21
  get code(): string {
24
22
  return "cronJob";
@@ -40,7 +38,9 @@ class CronJobPlugin implements RapidPlugin {
40
38
  return [];
41
39
  }
42
40
 
43
- async initPlugin(server: IRpdServer): Promise<any> {}
41
+ async initPlugin(server: IRpdServer): Promise<any> {
42
+ this.#server = server;
43
+ }
44
44
 
45
45
  async registerMiddlewares(server: IRpdServer): Promise<any> {}
46
46
 
@@ -69,7 +69,8 @@ class CronJobPlugin implements RapidPlugin {
69
69
  async onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {}
70
70
 
71
71
  async onApplicationReady(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
72
- for (const job of this.#jobs) {
72
+ const cronJobs = server.listCronJobs();
73
+ for (const job of cronJobs) {
73
74
  const jobInstance = cron.CronJob.from({
74
75
  ...(job.jobOptions || {}),
75
76
  cronTime: job.cronTime,
@@ -83,7 +84,7 @@ class CronJobPlugin implements RapidPlugin {
83
84
  }
84
85
 
85
86
  getJobConfigurationByCode(code: string) {
86
- return find(this.#jobs, (job) => job.code === code);
87
+ return find(this.#server.listCronJobs(), (job) => job.code === code);
87
88
  }
88
89
 
89
90
  async executeJob(server: IRpdServer, job: CronJobConfiguration) {
@@ -1,61 +1,3 @@
1
- import { ActionHandlerContext } from "~/core/actionHandler";
2
-
3
- export interface CronJobConfiguration {
4
- /**
5
- * 定时任务编号
6
- */
7
- code: string;
8
-
9
- /**
10
- * 定时任务描述
11
- */
12
- description?: string;
13
-
14
- /**
15
- * crontab 表达式
16
- */
17
- cronTime: string;
18
-
19
- /**
20
- * 任务设置
21
- */
22
- jobOptions?: CronJobOptions;
23
-
24
- /**
25
- * 任务处理程序编号。当指定处理程序编号时,忽略 handler 配置。
26
- */
27
- actionHandlerCode?: string;
28
-
29
- /**
30
- * 定时任务处理程序
31
- * @param ctx
32
- * @param options
33
- * @returns
34
- */
35
- handler?: (ctx: ActionHandlerContext, options: any) => Promise<void>;
36
-
37
- /**
38
- * 处理定时任务时的设置选项
39
- */
40
- handleOptions?: any;
41
- }
42
-
43
- export interface CronJobOptions {
44
- /**
45
- * Instantly triggers the onTick function post initialization. Default is false.
46
- */
47
- runOnInit?: boolean;
48
-
49
- /**
50
- * If true, no additional instances of the onTick callback function will run until the current onTick callback has completed. Any new scheduled executions that occur while the current callback is running will be skipped entirely. Default is false.
51
- */
52
- waitForCompletion?: boolean;
53
- }
54
-
55
- export interface CronJobPluginInitOptions {
56
- jobs: CronJobConfiguration[];
57
- }
58
-
59
1
  export type RunCronJobActionHandlerOptions = {
60
2
  code?: string;
61
3
  };
package/src/server.ts CHANGED
@@ -33,6 +33,7 @@ import EntityManager from "./dataAccess/entityManager";
33
33
  import { bind, cloneDeep, find, forEach, merge, omit } from "lodash";
34
34
  import { Logger } from "./facilities/log/LogFacility";
35
35
  import { FacilityFactory } from "./core/facility";
36
+ import { CronJobConfiguration } from "./types/cron-job-types";
36
37
 
37
38
  export interface InitServerOptions {
38
39
  logger: Logger;
@@ -43,6 +44,16 @@ export interface InitServerOptions {
43
44
  facilityFactories?: FacilityFactory[];
44
45
  plugins?: RapidPlugin[];
45
46
  entityWatchers?: EntityWatcherType[];
47
+
48
+ /**
49
+ * Application level cron jobs.
50
+ */
51
+ cronJobs?: CronJobConfiguration[];
52
+
53
+ /**
54
+ * All cron jobs of the server will be disabled if set `true`.
55
+ */
56
+ disableCronJobs?: boolean;
46
57
  }
47
58
 
48
59
  export class RapidServer implements IRpdServer {
@@ -70,6 +81,10 @@ export class RapidServer implements IRpdServer {
70
81
  #entityWatchers: EntityWatcherType[];
71
82
  #appEntityWatchers: EntityWatcherType[];
72
83
 
84
+ #cronJobs: CronJobConfiguration[];
85
+ #appCronJobs: CronJobConfiguration[];
86
+ #disableCronJobs: boolean;
87
+
73
88
  #cachedEntityManager: Map<string, EntityManager>;
74
89
  #services: Map<string, any>;
75
90
  queryBuilder: IQueryBuilder;
@@ -121,6 +136,10 @@ export class RapidServer implements IRpdServer {
121
136
  this.#entityWatchers = [];
122
137
  this.#appEntityWatchers = options.entityWatchers || [];
123
138
 
139
+ this.#cronJobs = [];
140
+ this.#appCronJobs = options.cronJobs || [];
141
+ this.#disableCronJobs = !!options.disableCronJobs;
142
+
124
143
  this.#services = new Map();
125
144
 
126
145
  this.queryBuilder = new QueryBuilder({
@@ -298,6 +317,19 @@ export class RapidServer implements IRpdServer {
298
317
  return this.#services.get(name);
299
318
  }
300
319
 
320
+ registerCronJob(job: CronJobConfiguration): void {
321
+ const jobDuplicate = find(this.#cronJobs, (item: CronJobConfiguration) => item.code === job.code);
322
+ if (jobDuplicate) {
323
+ this.#logger.warn(`Duplicated cron job with code "${job.code}"`);
324
+ }
325
+
326
+ this.#cronJobs.push(job);
327
+ }
328
+
329
+ listCronJobs() {
330
+ return [...this.#cronJobs, ...this.#appCronJobs];
331
+ }
332
+
301
333
  async start() {
302
334
  this.#logger.info("Starting rapid server...");
303
335
  const pluginManager = this.#pluginManager;
@@ -336,6 +368,10 @@ export class RapidServer implements IRpdServer {
336
368
 
337
369
  await this.configureApplication();
338
370
 
371
+ if (!this.#disableCronJobs) {
372
+ await pluginManager.registerCronJobs();
373
+ }
374
+
339
375
  this.#logger.info(`Rapid server ready.`);
340
376
  await pluginManager.onApplicationReady(this.#applicationConfig);
341
377
  }
@@ -0,0 +1,53 @@
1
+ import { ActionHandlerContext } from "~/core/actionHandler";
2
+
3
+ export interface CronJobConfiguration {
4
+ /**
5
+ * 定时任务编号
6
+ */
7
+ code: string;
8
+
9
+ /**
10
+ * 定时任务描述
11
+ */
12
+ description?: string;
13
+
14
+ /**
15
+ * crontab 表达式
16
+ */
17
+ cronTime: string;
18
+
19
+ /**
20
+ * 任务设置
21
+ */
22
+ jobOptions?: CronJobOptions;
23
+
24
+ /**
25
+ * 任务处理程序编号。当指定处理程序编号时,忽略 handler 配置。
26
+ */
27
+ actionHandlerCode?: string;
28
+
29
+ /**
30
+ * 定时任务处理程序
31
+ * @param ctx
32
+ * @param options
33
+ * @returns
34
+ */
35
+ handler?: (ctx: ActionHandlerContext, options: any) => Promise<void>;
36
+
37
+ /**
38
+ * 处理定时任务时的设置选项
39
+ */
40
+ handleOptions?: any;
41
+ }
42
+
43
+ export interface CronJobOptions {
44
+ /**
45
+ * Instantly triggers the onTick function post initialization. Default is false.
46
+ */
47
+ runOnInit?: boolean;
48
+
49
+ /**
50
+ * If true, no additional instances of the onTick callback function will run until the current onTick callback has completed. Any new scheduled executions that occur while the current callback is running will be skipped entirely. Default is false.
51
+ */
52
+ waitForCompletion?: boolean;
53
+ }