From f104b34d2c3ab40c28c852bbb440e167ca817105 Mon Sep 17 00:00:00 2001 From: jjnnzb Date: Tue, 1 Dec 2020 22:47:05 +0800 Subject: [PATCH 01/19] Modify README_enUS.md, correct spelling mistakes and change statements. --- README_enUS.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README_enUS.md b/README_enUS.md index badd96a8..6d8e4208 100644 --- a/README_enUS.md +++ b/README_enUS.md @@ -1,8 +1,8 @@ -

+

PowerJob

-

+

actions Maven Central GitHub release (latest SemVer) @@ -14,26 +14,26 @@ - Have you ever felt helpless when batches of business tasks require handling? - Have you ever felt depressed about tasks that carry with complex dependencies? -Well, PowerJob is there for you, it is the choice of a new generation.It is a powerful, business-oriented scheduling framework that provides distributed computing ability.Based on Akka architecture, it makes everything with scheduling easier.Just with several steps, PowerJob could be deployed and work for you! +Well, PowerJob is there for you, it is the choice of a new generation. It is a powerful, business-oriented scheduling framework that provides distributed computing ability. Based on Akka architecture, it makes everything with scheduling easier. Just with several steps, PowerJob could be deployed and work for you! # Introduction ### Features -- Simple to use: PowerJob provides a friendly front-end Web that allows developers to visually manage tasks (Create, Read, Update and Delete), monitor task status, and view operation logs online. +- Simple to use: PowerJob provides a friendly front-end Web that allows developers to visually manage tasks (Create, Read, Update and Delete), monitor tasks, and view logs online. - Complete timing strategy: PowerJob supports four different scheduling strategies, including CRON expression, fixed frequency timing, fixed delay timing as well as the Open API. -- Various execution modes: PowerJob supports four execution modes: stand-alone, broadcast, Map, and MapReduce. It's worth mentioning the Map and MapReduce modes. With the completion of several lines of codes, developers could take full advantage of PowerJob's distributed computing ability. -- Complete workflow support. PowerJob supports DAG(Directed acyclic graph) based online task configuration. Developers could arrange tasks on the console, while data could be transferred between tasks on the flow. +- Various execution modes: PowerJob supports four execution modes: stand-alone, broadcast, Map, and MapReduce. It's worth mentioning the Map and MapReduce modes. With several lines of codes, developers could take full advantage of PowerJob's distributed computing ability. +- Complete workflow support. PowerJob supports DAG(Directed acyclic graph) based online task configuration. Developers could arrange tasks on the console, while data could be transferred among tasks on the flow. - Extensive executor support: PowerJob supports multiple processors, including Spring Beans, ordinary Java objects, Shell, Python and so on. -- Simple in dependency: PowerJob aims to be simple in dependency. The only dependency is merely database (MySQL / Oracle / MS SQLServer ...), with MongoDB being the extra dependency for storing huge online logs. -- High availability and performance: Unlike traditional job-scheduling frameworks which rely on database locks, PowerJob server is lock-free when scheduling. PowerJob supports unlimited horizontal expansion. It's easy to achieve high availability and performance just by deploying as many PowerJob server instances as you need. +- Simple in dependency: PowerJob aims to be simple in dependency. The only dependency is merely database (MySQL / Oracle / MS SQLServer ...), with MongoDB being the extra dependency for storing large log files online. +- High availability and performance: Unlike traditional job-scheduling frameworks which rely on database locks, PowerJob server is lock-free. PowerJob supports unlimited horizontal expansion. It's easy to achieve high availability and performance by deploying as many PowerJob server instances as you need. - Quick failover and recovery support: Whenever any task failed, PowerJob server would retry according to the configured strategy. As long as there were enough nodes in the cluster, the failed tasks could execute successfully finally. -- Convenient to run and maintain: PowerJob supports online logging. Logs generated by the worker would be transferred and displayed on the console instantly, therefore reducing the cost of debugging and improving the efficiency for developers significantly. +- Convenient to run and maintain: PowerJob supports online logging. Logs generated by the worker would be transferred and displayed on the console instantly, therefore reducing the cost of debugging and improving the efficiency significantly. ### Applicable scene - Scenarios with timed tasks: such as full synchronization of data at midnight, generating business reports at desired time. - Scenarios that require all machines to run tasks simultaneously: such as log cleanup. -- Scenarios that require distributed processing: For example, a large amount of data requires updating, while the stand-alone execution takes quite a lot of time. The Map/MapReduce mode could be applied while the workers would join the cluster for PowerJob server to dispatch, to speed up the time-consuming process, therefore improving the computing ablility of whole cluster. +- Scenarios that require distributed processing: For example, a large amount of data requires updating, while the stand-alone execution takes quite a lot of time. The Map/MapReduce mode could be applied in which the workers would join the cluster for PowerJob server to dispatch, to speed up the time-consuming process, therefore improving the computing ability of the whole cluster. ### Comparison of similar products @@ -42,12 +42,12 @@ Well, PowerJob is there for you, it is the choice of a new generation.It is a po | Timing type | CRON | CRON | CRON, fixed frequency, fixed delay, OpenAPI | **CRON, fixed frequency, fixed delay, OpenAPI** | | Task type | Built-in Java | Built-in Java, GLUE Java, Shell, Python and other scripts | Built-in Java, external Java (FatJar), Shell, Python and other scripts | **Built-in Java, external Java (container), Shell, Python and other scripts** | | Distributed strategy | Unsupported | Static sharding | MapReduce dynamic sharding | **MapReduce dynamic sharding** | -| Online task management | Unsupported | Supported | Supported | **Supported** | +| Online task management | Unsupported | Supported | Supported | **Supported** | | Online logging | Unsupported | Supported | Unsupported | **Supported** | | Scheduling methods and performance | Based on database lock, there is a performance bottleneck | Based on database lock, there is a performance bottleneck | Unknown | **Lock-free design, powerful performance without upper limit** | -| Alarm monitoring | Unsupported | Email | SMS | **Email, WebHook, Dingtalk. An interface is provided for customization.** | -| System dependence | Any relational database (MySQL, Oracle ...) supported by JDBC | MySQL | RMB (free during public beta, hey, help to advertise) | **Any relational database (MySQL, Oracle ...) supported by Spring Data Jpa** | -| workflow | Unsupported | Unsupported | Supported | **Supported** | +| Alarm monitoring | Unsupported | Email | SMS | **Email, WebHook, DingTalk. An interface is provided for customization.** | +| System dependence | Any relational database (MySQL, Oracle ...) supported by JDBC | MySQL | RMB (Public Beta version for free, hey, helping to advertise) | **Any relational database (MySQL, Oracle ...) supported by Spring Data Jpa** | +| workflow | Unsupported | Unsupported | Supported | **Supported** | # Document **[GitHub Wiki](https://github.com/KFCFans/PowerJob/wiki)** @@ -56,7 +56,7 @@ Well, PowerJob is there for you, it is the choice of a new generation.It is a po # Others -- PowerJob is permanently open source software(Apache License, Version 2.0), please feel free to try, use or deploy! +- PowerJob is permanently open source software(Apache License, Version 2.0), please feel free to try, deploy and put into production! - Owner of PowerJob (@KFCFans) has abundant time for maintenance, and is willing to provide technical support if you have needs! - Welcome to contribute to PowerJob, both Pull Requests and Issues are precious. - Please STAR PowerJob if it is valuable. ~ =  ̄ω ̄ = From 6ce5765ff41a621770b1c8896d0c421c1ed0e86f Mon Sep 17 00:00:00 2001 From: jjnnzb Date: Wed, 2 Dec 2020 00:35:23 +0800 Subject: [PATCH 02/19] Modify README_enUS.md, add client registration, design goals and online trial. --- README_enUS.md | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/README_enUS.md b/README_enUS.md index 6d8e4208..19270a9f 100644 --- a/README_enUS.md +++ b/README_enUS.md @@ -29,13 +29,25 @@ Well, PowerJob is there for you, it is the choice of a new generation. It is a p - Quick failover and recovery support: Whenever any task failed, PowerJob server would retry according to the configured strategy. As long as there were enough nodes in the cluster, the failed tasks could execute successfully finally. - Convenient to run and maintain: PowerJob supports online logging. Logs generated by the worker would be transferred and displayed on the console instantly, therefore reducing the cost of debugging and improving the efficiency significantly. -### Applicable scene +### Applicable scenes - Scenarios with timed tasks: such as full synchronization of data at midnight, generating business reports at desired time. - Scenarios that require all machines to run tasks simultaneously: such as log cleanup. - Scenarios that require distributed processing: For example, a large amount of data requires updating, while the stand-alone execution takes quite a lot of time. The Map/MapReduce mode could be applied in which the workers would join the cluster for PowerJob server to dispatch, to speed up the time-consuming process, therefore improving the computing ability of the whole cluster. +- Scenarios with delayed tasks: For instance, disposal of overdue orders. -### Comparison of similar products +### Design goals + +PowerJob aims to be an enterprise-level scheduling middleware. By deploying PowerJob-server as the scheduling center, +all the applications could gain scheduling and distributed computing ability relying on PowerJob-worker. + +### Online trial + +Trial address: [Online Trial Address](http://try.powerjob.tech/) +Application name: powerjob-agent-test +Application password: 123 + +### Comparison with similar products | | QuartZ | xxl-job | SchedulerX 2.0 | PowerJob | | ---------------------------------- | --------------------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | @@ -54,6 +66,14 @@ Well, PowerJob is there for you, it is the choice of a new generation. It is a p **[中文文档](https://www.yuque.com/powerjob/product)** +# User Registration +[Click to register as PowerJob client and contribute to PowerJob!](https://github.com/KFCFans/PowerJob/issues/6) +ღ( ´・ᴗ・\` )ღ Many thanks to the following registered clients. ღ( ´・ᴗ・\` )ღ +

+PowerJob User +

+ + # Others - PowerJob is permanently open source software(Apache License, Version 2.0), please feel free to try, deploy and put into production! From e300885839da26c358ee561194136019151aa256 Mon Sep 17 00:00:00 2001 From: jjnnzb Date: Wed, 2 Dec 2020 00:37:41 +0800 Subject: [PATCH 03/19] Modify README_enUS.md, client--->user. --- README_enUS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README_enUS.md b/README_enUS.md index 19270a9f..01b72c44 100644 --- a/README_enUS.md +++ b/README_enUS.md @@ -67,8 +67,8 @@ Application password: 123 **[中文文档](https://www.yuque.com/powerjob/product)** # User Registration -[Click to register as PowerJob client and contribute to PowerJob!](https://github.com/KFCFans/PowerJob/issues/6) -ღ( ´・ᴗ・\` )ღ Many thanks to the following registered clients. ღ( ´・ᴗ・\` )ღ +[Click to register as PowerJob user and contribute to PowerJob!](https://github.com/KFCFans/PowerJob/issues/6) +ღ( ´・ᴗ・\` )ღ Many thanks to the following registered users. ღ( ´・ᴗ・\` )ღ

PowerJob User

From a4f768e46ce21fbe538190d271a165f40d05c67e Mon Sep 17 00:00:00 2001 From: jjnnzb Date: Wed, 2 Dec 2020 11:28:12 +0800 Subject: [PATCH 04/19] advertise--->promote --- README_enUS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_enUS.md b/README_enUS.md index 01b72c44..24a29d0d 100644 --- a/README_enUS.md +++ b/README_enUS.md @@ -58,7 +58,7 @@ Application password: 123 | Online logging | Unsupported | Supported | Unsupported | **Supported** | | Scheduling methods and performance | Based on database lock, there is a performance bottleneck | Based on database lock, there is a performance bottleneck | Unknown | **Lock-free design, powerful performance without upper limit** | | Alarm monitoring | Unsupported | Email | SMS | **Email, WebHook, DingTalk. An interface is provided for customization.** | -| System dependence | Any relational database (MySQL, Oracle ...) supported by JDBC | MySQL | RMB (Public Beta version for free, hey, helping to advertise) | **Any relational database (MySQL, Oracle ...) supported by Spring Data Jpa** | +| System dependence | Any relational database (MySQL, Oracle ...) supported by JDBC | MySQL | RMB (Public Beta version for free, hey, helping to promote) | **Any relational database (MySQL, Oracle ...) supported by Spring Data Jpa** | | workflow | Unsupported | Unsupported | Supported | **Supported** | # Document From ff81ac44857553c321e4e316f977dd3c3d63b808 Mon Sep 17 00:00:00 2001 From: KFCFans Date: Sat, 12 Dec 2020 10:37:24 +0800 Subject: [PATCH 05/19] feat: change version to 3.4.1 --- powerjob-client/pom.xml | 4 ++-- powerjob-common/pom.xml | 2 +- powerjob-server/pom.xml | 4 ++-- powerjob-worker-agent/pom.xml | 4 ++-- powerjob-worker-samples/pom.xml | 4 ++-- powerjob-worker-spring-boot-starter/pom.xml | 4 ++-- powerjob-worker/pom.xml | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/powerjob-client/pom.xml b/powerjob-client/pom.xml index ac7d0292..d49a6a17 100644 --- a/powerjob-client/pom.xml +++ b/powerjob-client/pom.xml @@ -10,13 +10,13 @@ 4.0.0 powerjob-client - 3.4.0 + 3.4.1 jar 5.6.1 1.2.68 - 3.4.0 + 3.4.1 3.2.4 diff --git a/powerjob-common/pom.xml b/powerjob-common/pom.xml index 29436f48..e92f4a92 100644 --- a/powerjob-common/pom.xml +++ b/powerjob-common/pom.xml @@ -10,7 +10,7 @@ 4.0.0 powerjob-common - 3.4.0 + 3.4.1 jar diff --git a/powerjob-server/pom.xml b/powerjob-server/pom.xml index 68036a10..1770b7d3 100644 --- a/powerjob-server/pom.xml +++ b/powerjob-server/pom.xml @@ -10,13 +10,13 @@ 4.0.0 powerjob-server - 3.4.0 + 3.4.1 jar 2.9.2 2.3.4.RELEASE - 3.4.0 + 3.4.1 8.0.19 19.7.0.0 diff --git a/powerjob-worker-agent/pom.xml b/powerjob-worker-agent/pom.xml index a201bf70..817bffdb 100644 --- a/powerjob-worker-agent/pom.xml +++ b/powerjob-worker-agent/pom.xml @@ -10,12 +10,12 @@ 4.0.0 powerjob-worker-agent - 3.4.0-bugfix + 3.4.1 jar - 3.4.0-bugfix + 3.4.1 1.2.3 4.3.2 diff --git a/powerjob-worker-samples/pom.xml b/powerjob-worker-samples/pom.xml index 0334a92f..cdacbb5e 100644 --- a/powerjob-worker-samples/pom.xml +++ b/powerjob-worker-samples/pom.xml @@ -10,11 +10,11 @@ 4.0.0 powerjob-worker-samples - 3.4.0 + 3.4.1 2.2.6.RELEASE - 3.4.0-bugfix + 3.4.1 1.2.68 diff --git a/powerjob-worker-spring-boot-starter/pom.xml b/powerjob-worker-spring-boot-starter/pom.xml index 9865d9d2..dfddbb77 100644 --- a/powerjob-worker-spring-boot-starter/pom.xml +++ b/powerjob-worker-spring-boot-starter/pom.xml @@ -10,11 +10,11 @@ 4.0.0 powerjob-worker-spring-boot-starter - 3.4.0-bugfix + 3.4.1 jar - 3.4.0-bugfix + 3.4.1 2.2.6.RELEASE diff --git a/powerjob-worker/pom.xml b/powerjob-worker/pom.xml index aee5b742..9a73566b 100644 --- a/powerjob-worker/pom.xml +++ b/powerjob-worker/pom.xml @@ -10,12 +10,12 @@ 4.0.0 powerjob-worker - 3.4.0-bugfix + 3.4.1 jar 5.2.4.RELEASE - 3.4.0 + 3.4.1 1.4.200 3.4.2 5.6.1 From 3029673612569e73e89436c19467662df33b17a0 Mon Sep 17 00:00:00 2001 From: tjq Date: Sun, 13 Dec 2020 18:14:44 +0800 Subject: [PATCH 06/19] refactor: use aop to redirect request #131 --- .../powerjob/server/akka/OhMyServer.java | 6 ++ .../server/akka/actors/FriendActor.java | 60 +++++++----- .../akka/requests/RemoteProcessReq.java | 25 +++++ .../akka/requests/RunJobOrWorkflowReq.java | 27 ------ .../common/redirect/DesignateServer.java | 24 +++++ .../redirect/DesignateServerAspect.java | 93 +++++++++++++++++++ .../powerjob/server/service/JobService.java | 34 ++----- .../service/instance/InstanceService.java | 7 +- .../timing/schedule/OmsScheduleService.java | 10 +- .../service/workflow/WorkflowService.java | 31 +------ .../web/controller/InstanceController.java | 4 +- .../server/web/controller/JobController.java | 4 +- .../web/controller/OpenAPIController.java | 6 +- .../web/controller/WorkflowController.java | 2 +- 14 files changed, 214 insertions(+), 119 deletions(-) create mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/requests/RemoteProcessReq.java delete mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/requests/RunJobOrWorkflowReq.java create mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServer.java create mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServerAspect.java diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/OhMyServer.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/OhMyServer.java index f818675a..78de213d 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/OhMyServer.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/OhMyServer.java @@ -18,6 +18,7 @@ import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import java.time.Duration; import java.util.Map; @@ -51,6 +52,11 @@ public class OhMyServer { PropertyUtils.init(); Properties properties = PropertyUtils.getProperties(); int port = Integer.parseInt(properties.getProperty(PowerJobServerConfigKey.AKKA_PORT, "10086")); + String portFromJVM = System.getProperty(PowerJobServerConfigKey.AKKA_PORT); + if (StringUtils.isNotEmpty(portFromJVM)) { + log.info("[OhMyWorker] use port from jvm params: {}", portFromJVM); + port = Integer.parseInt(portFromJVM); + } // 启动 ActorSystem Map overrideConfig = Maps.newHashMap(); diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/actors/FriendActor.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/actors/FriendActor.java index eb28c112..d9d41a84 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/actors/FriendActor.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/actors/FriendActor.java @@ -1,18 +1,19 @@ package com.github.kfcfans.powerjob.server.akka.actors; import akka.actor.AbstractActor; -import com.github.kfcfans.powerjob.common.PowerJobException; +import com.alibaba.fastjson.JSONObject; import com.github.kfcfans.powerjob.common.model.SystemMetrics; import com.github.kfcfans.powerjob.common.response.AskResponse; import com.github.kfcfans.powerjob.server.akka.requests.FriendQueryWorkerClusterStatusReq; import com.github.kfcfans.powerjob.server.akka.requests.Ping; -import com.github.kfcfans.powerjob.server.akka.requests.RunJobOrWorkflowReq; +import com.github.kfcfans.powerjob.server.akka.requests.RemoteProcessReq; import com.github.kfcfans.powerjob.server.common.utils.SpringUtils; -import com.github.kfcfans.powerjob.server.service.JobService; import com.github.kfcfans.powerjob.server.service.ha.WorkerManagerService; -import com.github.kfcfans.powerjob.server.service.workflow.WorkflowService; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.springframework.util.ReflectionUtils; +import java.lang.reflect.Method; import java.util.Map; /** @@ -27,7 +28,7 @@ public class FriendActor extends AbstractActor { public Receive createReceive() { return receiveBuilder() .match(Ping.class, this::onReceivePing) - .match(RunJobOrWorkflowReq.class, this::onReceiveFriendResendRunRequest) + .match(RemoteProcessReq.class, this::onReceiveRemoteProcessReq) .match(FriendQueryWorkerClusterStatusReq.class, this::onReceiveFriendQueryWorkerClusterStatusReq) .matchAny(obj -> log.warn("[FriendActor] receive unknown request: {}.", obj)) .build(); @@ -49,26 +50,39 @@ public class FriendActor extends AbstractActor { getSender().tell(askResponse, getSelf()); } - /** - * 处理 run 转发 - */ - private void onReceiveFriendResendRunRequest(RunJobOrWorkflowReq req) { + private void onReceiveRemoteProcessReq(RemoteProcessReq req) { + + AskResponse response = new AskResponse(); + response.setSuccess(true); try { - Long resultId; - switch (req.getType()) { - case RunJobOrWorkflowReq.WORKFLOW: - resultId = SpringUtils.getBean(WorkflowService.class).runWorkflow(req.getId(), req.getAppId(), req.getParams(), req.getDelay()); - break; - case RunJobOrWorkflowReq.JOB: - resultId = SpringUtils.getBean(JobService.class).runJob(req.getId(), req.getParams(), req.getDelay()); - break; - default: - throw new PowerJobException("unknown type: " + req.getType()); + + Object[] args = req.getArgs(); + String[] parameterTypes = req.getParameterTypes(); + Class[] parameters = new Class[parameterTypes.length]; + + for (int i = 0; i < parameterTypes.length; i++) { + parameters[i] = Class.forName(parameterTypes[i]); + Object arg = args[i]; + if (arg != null) { + args[i] = JSONObject.parseObject(JSONObject.toJSONBytes(arg), parameters[i]); + } } - getSender().tell(AskResponse.succeed(String.valueOf(resultId)), getSelf()); - } catch (Exception e) { - log.error("[FriendActor] process run request [{}] failed!", req, e); - getSender().tell(AskResponse.failed(e.getMessage()), getSelf()); + + Class clz = Class.forName(req.getClassName()); + + Object bean = SpringUtils.getBean(clz); + Method method = ReflectionUtils.findMethod(clz, req.getMethodName(), parameters); + + assert method != null; + Object invokeResult = ReflectionUtils.invokeMethod(method, bean, args); + + response.setData(JSONObject.toJSONBytes(invokeResult)); + + } catch (Throwable t) { + log.error("[FriendActor] process remote request[{}] failed!", req, t); + response.setSuccess(false); + response.setMessage(ExceptionUtils.getMessage(t)); } + getSender().tell(response, getSelf()); } } diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/requests/RemoteProcessReq.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/requests/RemoteProcessReq.java new file mode 100644 index 00000000..5a2724c1 --- /dev/null +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/requests/RemoteProcessReq.java @@ -0,0 +1,25 @@ +package com.github.kfcfans.powerjob.server.akka.requests; + +import com.github.kfcfans.powerjob.common.OmsSerializable; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + * 原创执行命令 + * + * @author tjq + * @since 12/13/20 + */ +@Getter +@Setter +@Accessors(chain = true) +public class RemoteProcessReq implements OmsSerializable { + + private String className; + private String methodName; + private String[] parameterTypes; + + private Object[] args; + +} diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/requests/RunJobOrWorkflowReq.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/requests/RunJobOrWorkflowReq.java deleted file mode 100644 index 517be316..00000000 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/akka/requests/RunJobOrWorkflowReq.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.github.kfcfans.powerjob.server.akka.requests; - -import com.github.kfcfans.powerjob.common.OmsSerializable; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 运行 Job 或 工作流,需要转发到 server 进行,否则没有集群信息 - * - * @author tjq - * @since 11/7/20 - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class RunJobOrWorkflowReq implements OmsSerializable { - public static final int JOB = 1; - public static final int WORKFLOW = 2; - - private int type; - private long id; - private long delay; - private String params; - - private long appId; -} diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServer.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServer.java new file mode 100644 index 00000000..bc31aafd --- /dev/null +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServer.java @@ -0,0 +1,24 @@ +package com.github.kfcfans.powerjob.server.common.redirect; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 执行服务器运行 + * 注意:该注解所在方法的参数必须为对象,不可以是 long 等基本类型 + * + * @author tjq + * @since 12/13/20 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface DesignateServer { + + /** + * 转发请求需要 AppInfo 下的 currentServer 信息,因此必须要有 appId 作为入参,该字段指定了 appId 字段的参数名称 + * @return appId 参数名称 + */ + String appIdParameterName(); +} diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServerAspect.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServerAspect.java new file mode 100644 index 00000000..87a47448 --- /dev/null +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServerAspect.java @@ -0,0 +1,93 @@ +package com.github.kfcfans.powerjob.server.common.redirect; + +import akka.pattern.Patterns; +import com.alibaba.fastjson.JSONObject; +import com.github.kfcfans.powerjob.common.PowerJobException; +import com.github.kfcfans.powerjob.common.RemoteConstant; +import com.github.kfcfans.powerjob.common.response.AskResponse; +import com.github.kfcfans.powerjob.server.akka.OhMyServer; +import com.github.kfcfans.powerjob.server.akka.requests.RemoteProcessReq; +import com.github.kfcfans.powerjob.server.persistence.core.model.AppInfoDO; +import com.github.kfcfans.powerjob.server.persistence.core.repository.AppInfoRepository; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.time.Duration; +import java.util.Arrays; +import java.util.Objects; +import java.util.concurrent.CompletionStage; + +/** + * 执行服务器运行切面 + * + * @author tjq + * @since 12/13/20 + */ +@Slf4j +@Aspect +@Component +public class DesignateServerAspect { + + @Resource + private AppInfoRepository appInfoRepository; + + @Around(value = "@annotation(designateServer))") + public Object execute(ProceedingJoinPoint point, DesignateServer designateServer) throws Throwable { + + // 参数 + Object[] args = point.getArgs(); + // 方法名 + String methodName = point.getSignature().getName(); + // 类名 + String className = point.getSignature().getDeclaringTypeName(); + Signature signature = point.getSignature(); + // 方法签名 + MethodSignature methodSignature = (MethodSignature) signature; + String[] parameterNames = methodSignature.getParameterNames(); + String[] parameterTypes = Arrays.stream(methodSignature.getParameterTypes()).map(Class::getName).toArray(String[]::new); + + Long appId = null; + for (int i = 0; i < parameterNames.length; i++) { + if (StringUtils.equals(parameterNames[i], designateServer.appIdParameterName())) { + appId = Long.parseLong(String.valueOf(args[i])); + break; + } + } + + if (appId == null) { + throw new PowerJobException("can't find appId in params!"); + } + + // 获取执行机器 + AppInfoDO appInfo = appInfoRepository.findById(appId).orElseThrow(() -> new PowerJobException("can't find app info")); + String targetServer = appInfo.getCurrentServer(); + + // 目标IP与本地符合则本地执行 + if (Objects.equals(targetServer, OhMyServer.getActorSystemAddress())) { + return point.proceed(); + } + + log.info("[DesignateServerAspect] the method[{}] should execute in server[{}], so this request will be redirect to remote server!", signature.toShortString(), targetServer); + // 转发请求,远程执行后返回结果 + RemoteProcessReq remoteProcessReq = new RemoteProcessReq() + .setClassName(className) + .setMethodName(methodName) + .setParameterTypes(parameterTypes) + .setArgs(args); + + CompletionStage askCS = Patterns.ask(OhMyServer.getFriendActor(targetServer), remoteProcessReq, Duration.ofMillis(RemoteConstant.DEFAULT_TIMEOUT_MS)); + AskResponse askResponse = (AskResponse) askCS.toCompletableFuture().get(); + + if (!askResponse.isSuccess()) { + throw new PowerJobException("remote process failed: " + askResponse.getMessage()); + } + return JSONObject.parseObject(askResponse.getData(), methodSignature.getReturnType()); + } +} diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/JobService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/JobService.java index fc345083..f2e35534 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/JobService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/JobService.java @@ -5,15 +5,12 @@ import com.github.kfcfans.powerjob.common.PowerJobException; import com.github.kfcfans.powerjob.common.TimeExpressionType; import com.github.kfcfans.powerjob.common.request.http.SaveJobInfoRequest; import com.github.kfcfans.powerjob.common.response.JobInfoDTO; -import com.github.kfcfans.powerjob.server.akka.OhMyServer; -import com.github.kfcfans.powerjob.server.akka.requests.RunJobOrWorkflowReq; import com.github.kfcfans.powerjob.server.common.SJ; import com.github.kfcfans.powerjob.server.common.constans.SwitchableStatus; +import com.github.kfcfans.powerjob.server.common.redirect.DesignateServer; import com.github.kfcfans.powerjob.server.common.utils.CronExpression; -import com.github.kfcfans.powerjob.server.persistence.core.model.AppInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.model.InstanceInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.model.JobInfoDO; -import com.github.kfcfans.powerjob.server.persistence.core.repository.AppInfoRepository; import com.github.kfcfans.powerjob.server.persistence.core.repository.InstanceInfoRepository; import com.github.kfcfans.powerjob.server.persistence.core.repository.JobInfoRepository; import com.github.kfcfans.powerjob.server.service.instance.InstanceService; @@ -26,7 +23,6 @@ import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.util.Date; import java.util.List; -import java.util.Objects; import java.util.Optional; /** @@ -49,8 +45,6 @@ public class JobService { @Resource private InstanceInfoRepository instanceInfoRepository; - @Resource - private AppInfoRepository appInfoRepository; /** * 保存/修改任务 @@ -108,30 +102,13 @@ public class JobService { * @param delay 延迟时间,单位 毫秒 * @return 任务实例ID */ - public long runJob(Long jobId, String instanceParams, long delay) { + @DesignateServer(appIdParameterName = "appId") + public long runJob(Long appId, Long jobId, String instanceParams, Long delay) { + delay = delay == null ? 0 : delay; JobInfoDO jobInfo = jobInfoRepository.findById(jobId).orElseThrow(() -> new IllegalArgumentException("can't find job by id:" + jobId)); - AppInfoDO appInfo = appInfoRepository.findById(jobInfo.getAppId()).orElseThrow(() -> new IllegalArgumentException("can't find appInfo by appId: " + jobInfo.getAppId())); - String targetServer = appInfo.getCurrentServer(); - - if (Objects.equals(targetServer, OhMyServer.getActorSystemAddress())) { - return realRunJob(jobInfo, instanceParams, delay); - } - - // 转发请求 - log.info("[Job-{}] redirect run request[params={}] to target server: {}", jobId, instanceParams, targetServer); - RunJobOrWorkflowReq req = new RunJobOrWorkflowReq(RunJobOrWorkflowReq.JOB, jobId, delay, instanceParams, jobInfo.getAppId()); - try { - return Long.parseLong(OhMyServer.askFriend(targetServer, req)); - }catch (Exception e) { - log.error("[Job-{}] redirect run request[params={}] to target server[{}] failed!", jobId, instanceParams, targetServer); - throw new PowerJobException("redirect run request failed!", e); - } - } - - private long realRunJob(JobInfoDO jobInfo, String instanceParams, long delay) { - log.info("[Job-{}] try to run job, instanceParams={},delay={} ms.", jobInfo.getId(), instanceParams, delay); + log.info("[Job-{}] try to run job in app[{}], instanceParams={},delay={} ms.", jobInfo.getId(), appId, instanceParams, delay); Long instanceId = instanceService.create(jobInfo.getId(), jobInfo.getAppId(), instanceParams, null, System.currentTimeMillis() + Math.max(delay, 0)); instanceInfoRepository.flush(); if (delay <= 0) { @@ -145,6 +122,7 @@ public class JobService { return instanceId; } + /** * 删除某个任务 * @param jobId 任务ID diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/instance/InstanceService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/instance/InstanceService.java index 6ad8b12f..aafebb7d 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/instance/InstanceService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/instance/InstanceService.java @@ -13,6 +13,7 @@ import com.github.kfcfans.powerjob.common.response.AskResponse; import com.github.kfcfans.powerjob.common.response.InstanceInfoDTO; import com.github.kfcfans.powerjob.server.akka.OhMyServer; import com.github.kfcfans.powerjob.server.common.constans.InstanceType; +import com.github.kfcfans.powerjob.server.common.redirect.DesignateServer; import com.github.kfcfans.powerjob.server.common.utils.timewheel.TimerFuture; import com.github.kfcfans.powerjob.server.persistence.core.model.InstanceInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.model.JobInfoDO; @@ -132,7 +133,11 @@ public class InstanceService { * 重试任务(只有结束的任务运行重试) * @param instanceId 任务实例ID */ - public void retryInstance(Long instanceId) { + @DesignateServer(appIdParameterName = "appId") + public void retryInstance(Long appId, Long instanceId) { + + log.info("[Instance-{}] retry instance in appId: {}", instanceId, appId); + InstanceInfoDO instanceInfo = fetchInstanceInfo(instanceId); if (!InstanceStatus.finishedStatus.contains(instanceInfo.getStatus())) { throw new PowerJobException("Only stopped instance can be retry!"); diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/timing/schedule/OmsScheduleService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/timing/schedule/OmsScheduleService.java index f036b374..144af178 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/timing/schedule/OmsScheduleService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/timing/schedule/OmsScheduleService.java @@ -30,10 +30,7 @@ import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; /** @@ -239,7 +236,10 @@ public class OmsScheduleService { } log.info("[FrequentScheduler] These frequent jobs will be scheduled: {}.", notRunningJobIds); - notRunningJobIds.forEach(jobId -> jobService.runJob(jobId, null, 0)); + notRunningJobIds.forEach(jobId -> { + Optional jobInfoOpt = jobInfoRepository.findById(jobId); + jobInfoOpt.ifPresent(jobInfoDO -> jobService.runJob(jobInfoDO.getAppId(), jobId, null, 0L)); + }); }catch (Exception e) { log.error("[FrequentScheduler] schedule frequent job failed.", e); } diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/workflow/WorkflowService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/workflow/WorkflowService.java index 53ae028b..71bda99d 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/workflow/WorkflowService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/workflow/WorkflowService.java @@ -5,15 +5,12 @@ import com.github.kfcfans.powerjob.common.PowerJobException; import com.github.kfcfans.powerjob.common.TimeExpressionType; import com.github.kfcfans.powerjob.common.request.http.SaveWorkflowRequest; import com.github.kfcfans.powerjob.common.response.WorkflowInfoDTO; -import com.github.kfcfans.powerjob.server.akka.OhMyServer; -import com.github.kfcfans.powerjob.server.akka.requests.RunJobOrWorkflowReq; import com.github.kfcfans.powerjob.server.common.SJ; import com.github.kfcfans.powerjob.server.common.constans.SwitchableStatus; +import com.github.kfcfans.powerjob.server.common.redirect.DesignateServer; import com.github.kfcfans.powerjob.server.common.utils.CronExpression; import com.github.kfcfans.powerjob.server.common.utils.WorkflowDAGUtils; -import com.github.kfcfans.powerjob.server.persistence.core.model.AppInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.model.WorkflowInfoDO; -import com.github.kfcfans.powerjob.server.persistence.core.repository.AppInfoRepository; import com.github.kfcfans.powerjob.server.persistence.core.repository.WorkflowInfoRepository; import com.github.kfcfans.powerjob.server.service.instance.InstanceTimeWheelService; import lombok.extern.slf4j.Slf4j; @@ -22,7 +19,6 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.Date; -import java.util.Objects; /** * Workflow 服务 @@ -34,8 +30,6 @@ import java.util.Objects; @Service public class WorkflowService { - @Resource - private AppInfoRepository appInfoRepository; @Resource private WorkflowInstanceManager workflowInstanceManager; @Resource @@ -144,29 +138,12 @@ public class WorkflowService { * @param delay 延迟时间 * @return 该 workflow 实例的 instanceId(wfInstanceId) */ - public Long runWorkflow(Long wfId, Long appId, String initParams, long delay) { + @DesignateServer(appIdParameterName = "appId") + public Long runWorkflow(Long wfId, Long appId, String initParams, Long delay) { + delay = delay == null ? 0 : delay; WorkflowInfoDO wfInfo = permissionCheck(wfId, appId); - AppInfoDO appInfo = appInfoRepository.findById(appId).orElseThrow(() -> new IllegalArgumentException("can't find appInfo by appId: " + appId)); - - String targetServer = appInfo.getCurrentServer(); - if (Objects.equals(targetServer, OhMyServer.getActorSystemAddress())) { - return realRunWorkflow(wfInfo, initParams, delay); - } - - log.info("[WorkflowService-{}] redirect run request[initParams={}] to target server: {}", wfId, initParams, targetServer); - // 转发请求 - RunJobOrWorkflowReq req = new RunJobOrWorkflowReq(RunJobOrWorkflowReq.WORKFLOW, wfId, delay, initParams, appId); - try { - return Long.valueOf(OhMyServer.askFriend(targetServer, req)); - }catch (Exception e) { - log.error("[WorkflowService-{}] redirect run request[params={}] to target server[{}] failed!", wfId, initParams, targetServer); - throw new PowerJobException("redirect run request failed!", e); - } - } - - private Long realRunWorkflow(WorkflowInfoDO wfInfo, String initParams, long delay) { log.info("[WorkflowService-{}] try to run workflow, initParams={},delay={} ms.", wfInfo.getId(), initParams, delay); Long wfInstanceId = workflowInstanceManager.create(wfInfo, initParams, System.currentTimeMillis() + delay); if (delay <= 0) { diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/InstanceController.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/InstanceController.java index 26121d31..d3495717 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/InstanceController.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/InstanceController.java @@ -68,8 +68,8 @@ public class InstanceController { } @GetMapping("/retry") - public ResultDTO retryInstance(Long instanceId) { - instanceService.retryInstance(instanceId); + public ResultDTO retryInstance(String appId, Long instanceId) { + instanceService.retryInstance(Long.valueOf(appId), instanceId); return ResultDTO.success(null); } diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/JobController.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/JobController.java index 9a0af481..6925d315 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/JobController.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/JobController.java @@ -57,8 +57,8 @@ public class JobController { } @GetMapping("/run") - public ResultDTO runImmediately(String jobId) { - return ResultDTO.success(jobService.runJob(Long.valueOf(jobId), null, 0)); + public ResultDTO runImmediately(String appId, String jobId) { + return ResultDTO.success(jobService.runJob(Long.valueOf(appId), Long.valueOf(jobId), null, 0L)); } @PostMapping("/list") diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/OpenAPIController.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/OpenAPIController.java index a846f73c..7ee1cc58 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/OpenAPIController.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/OpenAPIController.java @@ -82,7 +82,7 @@ public class OpenAPIController { @PostMapping(OpenAPIConstant.RUN_JOB) public ResultDTO runJob(Long appId, Long jobId, @RequestParam(required = false) String instanceParams, @RequestParam(required = false) Long delay) { checkJobIdValid(jobId, appId); - return ResultDTO.success(jobService.runJob(jobId, instanceParams, delay == null ? 0 : delay)); + return ResultDTO.success(jobService.runJob(appId, jobId, instanceParams, delay)); } /* ************* Instance 区 ************* */ @@ -104,7 +104,7 @@ public class OpenAPIController { @PostMapping(OpenAPIConstant.RETRY_INSTANCE) public ResultDTO retryInstance(Long instanceId, Long appId) { checkInstanceIdValid(instanceId, appId); - instanceService.retryInstance(instanceId); + instanceService.retryInstance(appId, instanceId); return ResultDTO.success(null); } @@ -151,7 +151,7 @@ public class OpenAPIController { @PostMapping(OpenAPIConstant.RUN_WORKFLOW) public ResultDTO runWorkflow(Long workflowId, Long appId, @RequestParam(required = false) String initParams, @RequestParam(required = false) Long delay) { - return ResultDTO.success(workflowService.runWorkflow(workflowId, appId, initParams, delay == null ? 0 : delay)); + return ResultDTO.success(workflowService.runWorkflow(workflowId, appId, initParams, delay)); } /* ************* Workflow Instance 区 ************* */ diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/WorkflowController.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/WorkflowController.java index 9eb1b589..3fce641d 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/WorkflowController.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/WorkflowController.java @@ -79,7 +79,7 @@ public class WorkflowController { @GetMapping("/run") public ResultDTO runWorkflow(Long workflowId, Long appId) { - return ResultDTO.success(workflowService.runWorkflow(workflowId, appId, null, 0)); + return ResultDTO.success(workflowService.runWorkflow(workflowId, appId, null, 0L)); } private static PageResult convertPage(Page originPage) { From d799c0f2bd08e3de66b088dc5e576864fcfce384 Mon Sep 17 00:00:00 2001 From: tjq Date: Sun, 13 Dec 2020 18:19:25 +0800 Subject: [PATCH 07/19] feat: develop web console to suit the modify --- .../com/github/kfcfans/powerjob/common/OmsSerializable.java | 2 +- powerjob-server/src/main/resources/static/js/6.js | 2 +- powerjob-server/src/main/resources/static/js/9.js | 2 +- powerjob-server/src/main/resources/static/js/app.js | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/powerjob-common/src/main/java/com/github/kfcfans/powerjob/common/OmsSerializable.java b/powerjob-common/src/main/java/com/github/kfcfans/powerjob/common/OmsSerializable.java index 07eeed9a..36243db5 100644 --- a/powerjob-common/src/main/java/com/github/kfcfans/powerjob/common/OmsSerializable.java +++ b/powerjob-common/src/main/java/com/github/kfcfans/powerjob/common/OmsSerializable.java @@ -3,7 +3,7 @@ package com.github.kfcfans.powerjob.common; import java.io.Serializable; /** - * OMS 序列化标记接口 + * PowerJob 序列化标记接口 * * @author tjq * @since 2020/4/16 diff --git a/powerjob-server/src/main/resources/static/js/6.js b/powerjob-server/src/main/resources/static/js/6.js index d7d001e7..39e5e714 100644 --- a/powerjob-server/src/main/resources/static/js/6.js +++ b/powerjob-server/src/main/resources/static/js/6.js @@ -20,7 +20,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n//\n//\n//\n//\n//\n//\n//\n/ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _common_TimeExpressionValidator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common/TimeExpressionValidator */ \"./src/components/common/TimeExpressionValidator.vue\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n name: \"JobManager\",\n components: {\n TimeExpressionValidator: _common_TimeExpressionValidator__WEBPACK_IMPORTED_MODULE_0__[\"default\"]\n },\n data: function data() {\n return {\n modifiedJobFormVisible: false,\n // 新建任务对象\n modifiedJobForm: {\n id: undefined,\n jobName: \"\",\n jobDescription: \"\",\n appId: this.$store.state.appInfo.id,\n jobParams: \"\",\n timeExpressionType: \"\",\n timeExpression: \"\",\n executeType: \"\",\n processorType: \"\",\n processorInfo: \"\",\n maxInstanceNum: 0,\n concurrency: 5,\n instanceTimeLimit: 0,\n instanceRetryNum: 0,\n taskRetryNum: 1,\n minCpuCores: 0,\n minMemorySpace: 0,\n minDiskSpace: 0,\n enable: true,\n designatedWorkers: \"\",\n maxWorkerCount: 0,\n notifyUserIds: []\n },\n // 任务查询请求对象\n jobQueryContent: {\n appId: this.$store.state.appInfo.id,\n index: 0,\n pageSize: 10,\n jobId: undefined,\n keyword: undefined\n },\n // 任务列表(查询结果),包含index、pageSize、totalPages、totalItems、data(List类型)\n jobInfoPageResult: {\n pageSize: 10,\n totalItems: 0,\n data: []\n },\n // 时间表达式选择类型\n timeExpressionTypeOptions: [{\n key: \"API\",\n label: \"API\"\n }, {\n key: \"CRON\",\n label: \"CRON\"\n }, {\n key: \"FIX_RATE\",\n label: this.$t('message.fixRate')\n }, {\n key: \"FIX_DELAY\",\n label: this.$t('message.fixDelay')\n }, {\n key: \"WORKFLOW\",\n label: this.$t('message.workflow')\n }],\n // 处理器类型\n processorTypeOptions: [{\n key: \"EMBEDDED_JAVA\",\n label: \"JAVA\"\n }, {\n key: \"JAVA_CONTAINER\",\n label: this.$t('message.javaContainer')\n }, {\n key: \"SHELL\",\n label: \"SHELL\"\n }, {\n key: \"PYTHON\",\n label: \"PYTHON\"\n }],\n // 执行方式类型\n executeTypeOptions: [{\n key: \"STANDALONE\",\n label: this.$t('message.standalone')\n }, {\n key: \"BROADCAST\",\n label: this.$t('message.broadcast')\n }, {\n key: \"MAP\",\n label: this.$t('message.map')\n }, {\n key: \"MAP_REDUCE\",\n label: this.$t('message.mapReduce')\n }],\n // 用户列表\n userList: [],\n // 时间表达式校验窗口\n timeExpressionValidatorVisible: false\n };\n },\n methods: {\n // 保存变更,包括新增和修改\n saveJob: function saveJob() {\n var _this = this;\n\n var that = this;\n this.axios.post(\"/job/save\", this.modifiedJobForm).then(function () {\n that.modifiedJobFormVisible = false;\n that.$message.success(_this.$t('message.success')); // 重新加载数据\n\n that.listJobInfos();\n }, function () {\n return that.modifiedJobFormVisible = false;\n });\n },\n // 列出符合当前搜索条件的任务\n listJobInfos: function listJobInfos() {\n var that = this;\n this.axios.post(\"/job/list\", this.jobQueryContent).then(function (res) {\n that.jobInfoPageResult = res;\n });\n },\n // 修改任务状态\n changeJobStatus: function changeJobStatus(data) {\n // switch 会自动更改 enable 的值\n var that = this;\n\n if (data.enable === false) {\n // 仅有,有特殊逻辑(关闭秒级任务),走单独接口\n that.axios.get(\"/job/disable?jobId=\" + data.id).then(function () {\n return that.listJobInfos();\n });\n } else {\n // 启用,则发起正常的保存操作\n this.modifiedJobForm = data;\n this.saveJob();\n }\n },\n // 新增任务,去除旧数据\n onClickNewJob: function onClickNewJob() {\n this.modifiedJobForm.id = undefined;\n this.modifiedJobForm.jobName = undefined;\n this.modifiedJobForm.jobDescription = undefined;\n this.modifiedJobForm.jobParams = undefined;\n this.modifiedJobForm.timeExpression = undefined;\n this.modifiedJobForm.timeExpressionType = undefined;\n this.modifiedJobForm.processorInfo = undefined;\n this.modifiedJobForm.processorType = undefined;\n this.modifiedJobForm.executeType = undefined;\n this.modifiedJobFormVisible = true;\n },\n // 点击 编辑按钮\n onClickModify: function onClickModify(data) {\n // 修复点击编辑后再点击新增 行数据被清空 的问题\n this.modifiedJobForm = JSON.parse(JSON.stringify(data));\n this.modifiedJobFormVisible = true;\n },\n // 点击 立即运行按钮\n onClickRun: function onClickRun(data) {\n var _this2 = this;\n\n var that = this;\n var url = \"/job/run?jobId=\" + data.id;\n this.axios.get(url).then(function () {\n return that.$message.success(_this2.$t('message.success'));\n });\n },\n // 点击 删除任务\n onClickDeleteJob: function onClickDeleteJob(data) {\n var _this3 = this;\n\n var that = this;\n var url = \"/job/delete?jobId=\" + data.id;\n this.axios.get(url).then(function () {\n that.$message.success(_this3.$t('message.success'));\n that.listJobInfos();\n });\n },\n // 点击 历史记录\n onClickRunHistory: function onClickRunHistory(data) {\n console.log(JSON.stringify(data));\n this.$router.push({\n name: 'instanceManager',\n params: {\n jobId: data.id\n }\n });\n },\n // 点击 换页\n onClickChangePage: function onClickChangePage(index) {\n // 后端从0开始,前端从1开始\n this.jobQueryContent.index = index - 1;\n this.listJobInfos();\n },\n // 点击重置按钮\n onClickReset: function onClickReset() {\n this.jobQueryContent.keyword = undefined;\n this.jobQueryContent.jobId = undefined;\n this.listJobInfos();\n },\n verifyPlaceholder: function verifyPlaceholder(processorType) {\n var res;\n\n switch (processorType) {\n case \"EMBEDDED_JAVA\":\n res = this.$t('message.javaProcessorInfoPLH');\n break;\n\n case \"JAVA_CONTAINER\":\n res = this.$t('message.containerProcessorInfoPLH');\n break;\n\n case \"SHELL\":\n res = this.$t('message.shellProcessorInfoPLH');\n break;\n\n case \"PYTHON\":\n res = this.$t('message.pythonProcessorInfoPLH');\n }\n\n return res;\n },\n // 翻译执行类型\n translateExecuteType: function translateExecuteType(executeType) {\n switch (executeType) {\n case \"STANDALONE\":\n return this.$t('message.standalone');\n\n case \"BROADCAST\":\n return this.$t('message.broadcast');\n\n case \"MAP_REDUCE\":\n return this.$t('message.mapReduce');\n\n case \"MAP\":\n return this.$t('message.map');\n\n default:\n return \"UNKNOWN\";\n }\n },\n // 翻译处理器类型\n translateProcessorType: function translateProcessorType(processorType) {\n if (processorType === \"JAVA_CONTAINER\") {\n return this.$t('message.javaContainer');\n }\n\n return processorType;\n },\n // 点击校验\n onClickValidateTimeExpression: function onClickValidateTimeExpression() {\n this.timeExpressionValidatorVisible = true;\n }\n },\n mounted: function mounted() {\n // 加载用户信息\n var that = this;\n that.axios.get(\"/user/list\").then(function (res) {\n return that.userList = res;\n }); // 加载任务信息\n\n this.listJobInfos();\n }\n});\n\n//# sourceURL=webpack:///./src/components/views/JobManager.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _common_TimeExpressionValidator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common/TimeExpressionValidator */ \"./src/components/common/TimeExpressionValidator.vue\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n name: \"JobManager\",\n components: {\n TimeExpressionValidator: _common_TimeExpressionValidator__WEBPACK_IMPORTED_MODULE_0__[\"default\"]\n },\n data: function data() {\n return {\n modifiedJobFormVisible: false,\n // 新建任务对象\n modifiedJobForm: {\n id: undefined,\n jobName: \"\",\n jobDescription: \"\",\n appId: this.$store.state.appInfo.id,\n jobParams: \"\",\n timeExpressionType: \"\",\n timeExpression: \"\",\n executeType: \"\",\n processorType: \"\",\n processorInfo: \"\",\n maxInstanceNum: 0,\n concurrency: 5,\n instanceTimeLimit: 0,\n instanceRetryNum: 0,\n taskRetryNum: 1,\n minCpuCores: 0,\n minMemorySpace: 0,\n minDiskSpace: 0,\n enable: true,\n designatedWorkers: \"\",\n maxWorkerCount: 0,\n notifyUserIds: []\n },\n // 任务查询请求对象\n jobQueryContent: {\n appId: this.$store.state.appInfo.id,\n index: 0,\n pageSize: 10,\n jobId: undefined,\n keyword: undefined\n },\n // 任务列表(查询结果),包含index、pageSize、totalPages、totalItems、data(List类型)\n jobInfoPageResult: {\n pageSize: 10,\n totalItems: 0,\n data: []\n },\n // 时间表达式选择类型\n timeExpressionTypeOptions: [{\n key: \"API\",\n label: \"API\"\n }, {\n key: \"CRON\",\n label: \"CRON\"\n }, {\n key: \"FIX_RATE\",\n label: this.$t('message.fixRate')\n }, {\n key: \"FIX_DELAY\",\n label: this.$t('message.fixDelay')\n }, {\n key: \"WORKFLOW\",\n label: this.$t('message.workflow')\n }],\n // 处理器类型\n processorTypeOptions: [{\n key: \"EMBEDDED_JAVA\",\n label: \"JAVA\"\n }, {\n key: \"JAVA_CONTAINER\",\n label: this.$t('message.javaContainer')\n }, {\n key: \"SHELL\",\n label: \"SHELL\"\n }, {\n key: \"PYTHON\",\n label: \"PYTHON\"\n }],\n // 执行方式类型\n executeTypeOptions: [{\n key: \"STANDALONE\",\n label: this.$t('message.standalone')\n }, {\n key: \"BROADCAST\",\n label: this.$t('message.broadcast')\n }, {\n key: \"MAP\",\n label: this.$t('message.map')\n }, {\n key: \"MAP_REDUCE\",\n label: this.$t('message.mapReduce')\n }],\n // 用户列表\n userList: [],\n // 时间表达式校验窗口\n timeExpressionValidatorVisible: false\n };\n },\n methods: {\n // 保存变更,包括新增和修改\n saveJob: function saveJob() {\n var _this = this;\n\n var that = this;\n this.axios.post(\"/job/save\", this.modifiedJobForm).then(function () {\n that.modifiedJobFormVisible = false;\n that.$message.success(_this.$t('message.success')); // 重新加载数据\n\n that.listJobInfos();\n }, function () {\n return that.modifiedJobFormVisible = false;\n });\n },\n // 列出符合当前搜索条件的任务\n listJobInfos: function listJobInfos() {\n var that = this;\n this.axios.post(\"/job/list\", this.jobQueryContent).then(function (res) {\n that.jobInfoPageResult = res;\n });\n },\n // 修改任务状态\n changeJobStatus: function changeJobStatus(data) {\n // switch 会自动更改 enable 的值\n var that = this;\n\n if (data.enable === false) {\n // 仅有,有特殊逻辑(关闭秒级任务),走单独接口\n that.axios.get(\"/job/disable?jobId=\" + data.id).then(function () {\n return that.listJobInfos();\n });\n } else {\n // 启用,则发起正常的保存操作\n this.modifiedJobForm = data;\n this.saveJob();\n }\n },\n // 新增任务,去除旧数据\n onClickNewJob: function onClickNewJob() {\n this.modifiedJobForm.id = undefined;\n this.modifiedJobForm.jobName = undefined;\n this.modifiedJobForm.jobDescription = undefined;\n this.modifiedJobForm.jobParams = undefined;\n this.modifiedJobForm.timeExpression = undefined;\n this.modifiedJobForm.timeExpressionType = undefined;\n this.modifiedJobForm.processorInfo = undefined;\n this.modifiedJobForm.processorType = undefined;\n this.modifiedJobForm.executeType = undefined;\n this.modifiedJobFormVisible = true;\n },\n // 点击 编辑按钮\n onClickModify: function onClickModify(data) {\n // 修复点击编辑后再点击新增 行数据被清空 的问题\n this.modifiedJobForm = JSON.parse(JSON.stringify(data));\n this.modifiedJobFormVisible = true;\n },\n // 点击 立即运行按钮\n onClickRun: function onClickRun(data) {\n var _this2 = this;\n\n var that = this;\n var url = \"/job/run?jobId=\" + data.id + \"&appId=\" + that.$store.state.appInfo.id;\n this.axios.get(url).then(function () {\n return that.$message.success(_this2.$t('message.success'));\n });\n },\n // 点击 删除任务\n onClickDeleteJob: function onClickDeleteJob(data) {\n var _this3 = this;\n\n var that = this;\n var url = \"/job/delete?jobId=\" + data.id;\n this.axios.get(url).then(function () {\n that.$message.success(_this3.$t('message.success'));\n that.listJobInfos();\n });\n },\n // 点击 历史记录\n onClickRunHistory: function onClickRunHistory(data) {\n console.log(JSON.stringify(data));\n this.$router.push({\n name: 'instanceManager',\n params: {\n jobId: data.id\n }\n });\n },\n // 点击 换页\n onClickChangePage: function onClickChangePage(index) {\n // 后端从0开始,前端从1开始\n this.jobQueryContent.index = index - 1;\n this.listJobInfos();\n },\n // 点击重置按钮\n onClickReset: function onClickReset() {\n this.jobQueryContent.keyword = undefined;\n this.jobQueryContent.jobId = undefined;\n this.listJobInfos();\n },\n verifyPlaceholder: function verifyPlaceholder(processorType) {\n var res;\n\n switch (processorType) {\n case \"EMBEDDED_JAVA\":\n res = this.$t('message.javaProcessorInfoPLH');\n break;\n\n case \"JAVA_CONTAINER\":\n res = this.$t('message.containerProcessorInfoPLH');\n break;\n\n case \"SHELL\":\n res = this.$t('message.shellProcessorInfoPLH');\n break;\n\n case \"PYTHON\":\n res = this.$t('message.pythonProcessorInfoPLH');\n }\n\n return res;\n },\n // 翻译执行类型\n translateExecuteType: function translateExecuteType(executeType) {\n switch (executeType) {\n case \"STANDALONE\":\n return this.$t('message.standalone');\n\n case \"BROADCAST\":\n return this.$t('message.broadcast');\n\n case \"MAP_REDUCE\":\n return this.$t('message.mapReduce');\n\n case \"MAP\":\n return this.$t('message.map');\n\n default:\n return \"UNKNOWN\";\n }\n },\n // 翻译处理器类型\n translateProcessorType: function translateProcessorType(processorType) {\n if (processorType === \"JAVA_CONTAINER\") {\n return this.$t('message.javaContainer');\n }\n\n return processorType;\n },\n // 点击校验\n onClickValidateTimeExpression: function onClickValidateTimeExpression() {\n this.timeExpressionValidatorVisible = true;\n }\n },\n mounted: function mounted() {\n // 加载用户信息\n var that = this;\n that.axios.get(\"/user/list\").then(function (res) {\n return that.userList = res;\n }); // 加载任务信息\n\n this.listJobInfos();\n }\n});\n\n//# sourceURL=webpack:///./src/components/views/JobManager.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), diff --git a/powerjob-server/src/main/resources/static/js/9.js b/powerjob-server/src/main/resources/static/js/9.js index cf83fa7b..34cb3277 100644 --- a/powerjob-server/src/main/resources/static/js/9.js +++ b/powerjob-server/src/main/resources/static/js/9.js @@ -8,7 +8,7 @@ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _common_InstanceDetail__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common/InstanceDetail */ \"./src/components/common/InstanceDetail.vue\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n name: \"InstanceManager\",\n components: {\n InstanceDetail: _common_InstanceDetail__WEBPACK_IMPORTED_MODULE_0__[\"default\"]\n },\n data: function data() {\n return {\n // 实例查询对象\n instanceQueryContent: {\n appId: this.$store.state.appInfo.id,\n index: 0,\n pageSize: 10,\n instanceId: undefined,\n wfInstanceId: undefined,\n status: \"\",\n jobId: undefined,\n type: \"NORMAL\"\n },\n // 实例查询结果\n instancePageResult: {\n pageSize: 10,\n totalItems: 0,\n data: []\n },\n // 详细信息弹出框是否可见\n instanceDetailVisible: false,\n // 日志查询对象\n logQueryContent: {\n instanceId: undefined,\n index: 0\n },\n // 日志对象\n paginableInstanceLog: {\n index: 0,\n totalPages: 0,\n data: \"\"\n },\n // 日志弹出框是否可见\n instanceLogVisible: false,\n currentInstanceId: undefined,\n // 任务实例状态选择\n instanceStatusOptions: [{\n key: \"\",\n label: this.$t('message.all')\n }, {\n key: \"WAITING_DISPATCH\",\n label: this.$t('message.waitingDispatch')\n }, {\n key: \"WAITING_WORKER_RECEIVE\",\n label: this.$t('message.waitingWorkerReceive')\n }, {\n key: \"RUNNING\",\n label: this.$t('message.running')\n }, {\n key: \"FAILED\",\n label: this.$t('message.failed')\n }, {\n key: \"SUCCEED\",\n label: this.$t('message.success')\n }, {\n key: \"CANCELED\",\n label: this.$t('message.canceled')\n }, {\n key: \"STOPPED\",\n label: this.$t('message.stopped')\n }]\n };\n },\n methods: {\n // 查询任务实例信息\n listInstanceInfos: function listInstanceInfos() {\n var that = this;\n that.axios.post(\"/instance/list\", that.instanceQueryContent).then(function (res) {\n that.instancePageResult = res;\n });\n },\n // 点击重置按钮\n onClickRest: function onClickRest() {\n this.instanceQueryContent.jobId = undefined;\n this.instanceQueryContent.instanceId = undefined;\n this.instanceQueryContent.wfInstanceId = undefined;\n this.instanceQueryContent.status = \"\";\n this.listInstanceInfos();\n },\n // 点击查询详情\n onClickShowDetail: function onClickShowDetail(data) {\n this.instanceDetailVisible = true;\n this.currentInstanceId = data.instanceId;\n },\n // 点击重跑\n onClickRetryJob: function onClickRetryJob(data) {\n var _this = this;\n\n var that = this;\n var url = \"/instance/retry?instanceId=\" + data.instanceId;\n this.axios.get(url).then(function () {\n that.$message.success(_this.$t('message.success'));\n that.listInstanceInfos();\n });\n },\n // 点击停止实例\n onClickStop: function onClickStop(data) {\n var _this2 = this;\n\n var that = this;\n var url = \"/instance/stop?instanceId=\" + data.instanceId;\n this.axios.get(url).then(function () {\n that.$message.success(_this2.$t('message.success')); // 重新加载列表\n\n that.listInstanceInfos();\n });\n },\n // 换页\n onClickChangeInstancePage: function onClickChangeInstancePage(index) {\n // 后端从0开始,前端从1开始\n this.instanceQueryContent.index = index - 1;\n this.listInstanceInfos();\n },\n instanceTableRowClassName: function instanceTableRowClassName(_ref) {\n var row = _ref.row;\n\n switch (row.status) {\n // 失败\n case 4:\n return 'error-row';\n // 成功\n\n case 5:\n return 'success-row';\n\n case 9:\n case 10:\n return 'warning-row';\n }\n },\n // 查看日志\n queryLog: function queryLog() {\n var that = this;\n var url = \"/instance/log?instanceId=\" + this.logQueryContent.instanceId + \"&index=\" + this.logQueryContent.index;\n this.axios.get(url).then(function (res) {\n that.paginableInstanceLog = res;\n that.instanceLogVisible = true;\n });\n },\n // 查看在线日志\n onClickShowLog: function onClickShowLog(data) {\n this.logQueryContent.instanceId = data.instanceId;\n this.logQueryContent.index = 0;\n this.queryLog();\n },\n // 查看其它页的在线日志\n onClickChangeLogPage: function onClickChangeLogPage(index) {\n this.logQueryContent.index = index - 1;\n this.queryLog();\n },\n // 下载日志\n onclickDownloadLog: function onclickDownloadLog() {\n var url = \"/instance/downloadLogUrl?instanceId=\" + this.logQueryContent.instanceId;\n this.axios.get(url).then(function (res) {\n return window.open(res);\n });\n },\n // 获取状态\n fetchStatus: function fetchStatus(s) {\n return this.common.translateInstanceStatus(s);\n }\n },\n mounted: function mounted() {\n // 读取传递的参数\n var jobId = this.$route.params.jobId;\n\n if (jobId !== undefined) {\n this.instanceQueryContent.jobId = jobId;\n }\n\n this.listInstanceInfos();\n }\n});\n\n//# sourceURL=webpack:///./src/components/views/InstanceManager.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _common_InstanceDetail__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common/InstanceDetail */ \"./src/components/common/InstanceDetail.vue\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n name: \"InstanceManager\",\n components: {\n InstanceDetail: _common_InstanceDetail__WEBPACK_IMPORTED_MODULE_0__[\"default\"]\n },\n data: function data() {\n return {\n // 实例查询对象\n instanceQueryContent: {\n appId: this.$store.state.appInfo.id,\n index: 0,\n pageSize: 10,\n instanceId: undefined,\n wfInstanceId: undefined,\n status: \"\",\n jobId: undefined,\n type: \"NORMAL\"\n },\n // 实例查询结果\n instancePageResult: {\n pageSize: 10,\n totalItems: 0,\n data: []\n },\n // 详细信息弹出框是否可见\n instanceDetailVisible: false,\n // 日志查询对象\n logQueryContent: {\n instanceId: undefined,\n index: 0\n },\n // 日志对象\n paginableInstanceLog: {\n index: 0,\n totalPages: 0,\n data: \"\"\n },\n // 日志弹出框是否可见\n instanceLogVisible: false,\n currentInstanceId: undefined,\n // 任务实例状态选择\n instanceStatusOptions: [{\n key: \"\",\n label: this.$t('message.all')\n }, {\n key: \"WAITING_DISPATCH\",\n label: this.$t('message.waitingDispatch')\n }, {\n key: \"WAITING_WORKER_RECEIVE\",\n label: this.$t('message.waitingWorkerReceive')\n }, {\n key: \"RUNNING\",\n label: this.$t('message.running')\n }, {\n key: \"FAILED\",\n label: this.$t('message.failed')\n }, {\n key: \"SUCCEED\",\n label: this.$t('message.success')\n }, {\n key: \"CANCELED\",\n label: this.$t('message.canceled')\n }, {\n key: \"STOPPED\",\n label: this.$t('message.stopped')\n }]\n };\n },\n methods: {\n // 查询任务实例信息\n listInstanceInfos: function listInstanceInfos() {\n var that = this;\n that.axios.post(\"/instance/list\", that.instanceQueryContent).then(function (res) {\n that.instancePageResult = res;\n });\n },\n // 点击重置按钮\n onClickRest: function onClickRest() {\n this.instanceQueryContent.jobId = undefined;\n this.instanceQueryContent.instanceId = undefined;\n this.instanceQueryContent.wfInstanceId = undefined;\n this.instanceQueryContent.status = \"\";\n this.listInstanceInfos();\n },\n // 点击查询详情\n onClickShowDetail: function onClickShowDetail(data) {\n this.instanceDetailVisible = true;\n this.currentInstanceId = data.instanceId;\n },\n // 点击重跑\n onClickRetryJob: function onClickRetryJob(data) {\n var _this = this;\n\n var that = this;\n var url = \"/instance/retry?instanceId=\" + data.instanceId + \"&appId=\" + that.$store.state.appInfo.id;\n this.axios.get(url).then(function () {\n that.$message.success(_this.$t('message.success'));\n that.listInstanceInfos();\n });\n },\n // 点击停止实例\n onClickStop: function onClickStop(data) {\n var _this2 = this;\n\n var that = this;\n var url = \"/instance/stop?instanceId=\" + data.instanceId;\n this.axios.get(url).then(function () {\n that.$message.success(_this2.$t('message.success')); // 重新加载列表\n\n that.listInstanceInfos();\n });\n },\n // 换页\n onClickChangeInstancePage: function onClickChangeInstancePage(index) {\n // 后端从0开始,前端从1开始\n this.instanceQueryContent.index = index - 1;\n this.listInstanceInfos();\n },\n instanceTableRowClassName: function instanceTableRowClassName(_ref) {\n var row = _ref.row;\n\n switch (row.status) {\n // 失败\n case 4:\n return 'error-row';\n // 成功\n\n case 5:\n return 'success-row';\n\n case 9:\n case 10:\n return 'warning-row';\n }\n },\n // 查看日志\n queryLog: function queryLog() {\n var that = this;\n var url = \"/instance/log?instanceId=\" + this.logQueryContent.instanceId + \"&index=\" + this.logQueryContent.index;\n this.axios.get(url).then(function (res) {\n that.paginableInstanceLog = res;\n that.instanceLogVisible = true;\n });\n },\n // 查看在线日志\n onClickShowLog: function onClickShowLog(data) {\n this.logQueryContent.instanceId = data.instanceId;\n this.logQueryContent.index = 0;\n this.queryLog();\n },\n // 查看其它页的在线日志\n onClickChangeLogPage: function onClickChangeLogPage(index) {\n this.logQueryContent.index = index - 1;\n this.queryLog();\n },\n // 下载日志\n onclickDownloadLog: function onclickDownloadLog() {\n var url = \"/instance/downloadLogUrl?instanceId=\" + this.logQueryContent.instanceId;\n this.axios.get(url).then(function (res) {\n return window.open(res);\n });\n },\n // 获取状态\n fetchStatus: function fetchStatus(s) {\n return this.common.translateInstanceStatus(s);\n }\n },\n mounted: function mounted() {\n // 读取传递的参数\n var jobId = this.$route.params.jobId;\n\n if (jobId !== undefined) {\n this.instanceQueryContent.jobId = jobId;\n }\n\n this.listInstanceInfos();\n }\n});\n\n//# sourceURL=webpack:///./src/components/views/InstanceManager.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), diff --git a/powerjob-server/src/main/resources/static/js/app.js b/powerjob-server/src/main/resources/static/js/app.js index 75b634db..a200db6f 100644 --- a/powerjob-server/src/main/resources/static/js/app.js +++ b/powerjob-server/src/main/resources/static/js/app.js @@ -676,7 +676,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue_ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/objectSpread2 */ \"./node_modules/@babel/runtime/helpers/esm/objectSpread2.js\");\n/* harmony import */ var element_ui_lib_locale_lang_zh_CN__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! element-ui/lib/locale/lang/zh-CN */ \"./node_modules/element-ui/lib/locale/lang/zh-CN.js\");\n/* harmony import */ var element_ui_lib_locale_lang_zh_CN__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(element_ui_lib_locale_lang_zh_CN__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\nvar cn = Object(_Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({\n message: {\n // common\n 'save': '保存',\n 'cancel': '取消',\n 'refresh': '刷新',\n 'query': '查询',\n 'reset': '重置',\n 'keyword': '关键字',\n 'run': '运行',\n 'edit': '编辑',\n 'delete': '删除',\n 'success': '成功',\n 'failed': '失败',\n 'detail': '详情',\n 'download': '下载',\n 'stop': '停止',\n 'back': '返回',\n 'all': '全部',\n 'more': '| 更多',\n // 欢迎界面\n 'appRegister': '执行应用注册',\n 'userRegister': '报警用户录入',\n 'appNameInputPLH': '请输入应用名称',\n 'appName': '应用名称',\n 'appPassword': '密码',\n 'register': '注册',\n 'name': '姓名',\n 'phone': '手机号',\n 'email': '邮箱地址',\n 'webhook': 'WebHook',\n 'welcomeTitle': '欢迎使用 PowerJob!',\n 'login': '登陆',\n 'logout': '退出',\n 'changeAppInfo': '修改应用信息',\n 'newPassword': '新密码',\n 'newPassword2': '确认密码',\n 'stayLogged': '保持登录状态',\n // 左侧tab栏\n 'tabHome': '系统首页',\n 'tabJobManage': '任务管理',\n 'tabJobInstance': '任务实例',\n 'tabWorkflowManage': '工作流管理',\n 'tabWfInstance': '工作流实例',\n 'tabContainerOps': '容器',\n 'tabTemplate': '模版生成',\n 'tabContainerManager': '容器运维',\n // 系统首页\n 'omsServerTime': '调度服务器时间',\n 'omsServerTimezone': '调度服务器时区',\n 'localBrowserTime': '本地时间',\n 'localBrowserTimezone': '本地时区',\n 'githubURL': '项目地址',\n 'docURL': '文档地址',\n 'totalJobNum': '任务总数',\n 'runningInstanceNum': '当前运行实例数',\n 'recentFailedInstanceNum': '近期失败任务数',\n 'workerNum': '集群机器数',\n 'workerAddress': '机器地址',\n 'cpuLoad': 'CPU 占用',\n 'memoryLoad': '内存占用',\n 'diskLoad': '磁盘占用',\n // 任务管理\n 'jobId': '任务ID',\n 'instanceId': '任务实例ID',\n 'jobName': '任务名称',\n 'scheduleInfo': '定时信息',\n 'executeType': '执行类型',\n 'processorType': '处理器类型',\n 'status': '状态',\n 'operation': '操作',\n 'newJob': '新建任务',\n 'jobDescription': '任务描述',\n 'jobParams': '任务参数',\n 'timeExpressionType': '时间表达式类型',\n 'timeExpressionPlaceHolder': 'CRON填写CRON表达式,秒级任务填写整数,API无需填写',\n 'executeConfig': '执行配置',\n 'javaProcessorInfoPLH': '全限定类名,eg:com.github.kfcfans.DemoProcessor',\n 'containerProcessorInfoPLH': '容器ID#全限定类名,eg:1#com.github.kfcfans.DemoProcessor',\n 'shellProcessorInfoPLH': 'SHELL脚本文件内容',\n 'pythonProcessorInfoPLH': 'Python脚本文件内容',\n 'runtimeConfig': '运行时配置',\n 'maxInstanceNum': '最大实例数',\n 'threadConcurrency': '单机线程并发度',\n 'timeout': '运行时间限制(毫秒)',\n 'retryConfig': '重试配置',\n 'taskRetryTimes': 'Instance重试次数',\n 'subTaskRetryTimes': \"Task重试次数\",\n 'workerConfig': '机器配置',\n 'minCPU': '最低CPU核心数',\n 'minMemory': '最低内存(GB)',\n 'minDisk': '最低磁盘空间(GB)',\n 'clusterConfig': '集群配置',\n 'designatedWorkerAddress': '执行机器地址',\n 'designatedWorkerAddressPLH': '执行机器地址(可选,不指定代表全部;多值英文逗号分割)',\n 'maxWorkerNum': '最大执行机器数量',\n 'maxWorkerNumPLH': '最大执行机器数量(0代表不限)',\n 'alarmConfig': '报警配置',\n 'alarmSelectorPLH': '选择报警通知人员',\n 'standalone': '单机执行',\n 'broadcast': '广播执行',\n 'map': 'Map执行',\n 'mapReduce': 'MapReduce执行',\n 'fixRate': '固定频率(毫秒)',\n 'fixDelay': '固定延迟(毫秒)',\n 'workflow': '工作流',\n 'validateTimeExpression': '校验定时参数',\n 'javaContainer': 'Java(容器)',\n 'runHistory': '运行记录',\n 'reRun': '重跑',\n // 任务实例管理\n 'wfInstanceId': '工作流实例ID',\n 'normalInstance': '普通任务实例',\n 'wfInstance': '工作流任务实例',\n 'triggerTime': '触发时间',\n 'finishedTime': '结束时间',\n 'log': '日志',\n 'runningTimes': '运行次数',\n 'taskTrackerAddress': 'TaskTracker 地址',\n 'startTime': '开始时间',\n 'expectedTriggerTime': '预计执行时间',\n 'result': '任务结果',\n 'subTaskInfo': 'Task 信息',\n 'secondlyJobHistory': '最近 10 条秒级任务历史记录(秒级任务专用)',\n 'subInstanceId': '子任务实例ID',\n 'instanceParams': '任务实例参数',\n // 工作流管理\n 'wfId': '工作流ID',\n 'wfName': '工作流名称',\n 'newWorkflow': '新建工作流',\n 'wfDescription': '工作流描述',\n 'importJob': '导入任务',\n 'deleteJob': '删除任务',\n 'newStartPoint': '新增起点',\n 'newEndPoint': '新增终点',\n 'deleteEdge': '删除边',\n 'importJobTitle': \"请选择需要导入工作流的任务\",\n 'wfTimeExpressionPLH': 'CRON填写CRON表达式,API无需填写',\n 'import': '导入',\n 'ntfClickNeedDeleteNode': '请点击需要删除的节点',\n 'ntfClickStartPoint': '请点击起始节点',\n 'ntfClickTargetPoint': '请点击目标节点',\n 'ntfClickDeleteEdge': '请点击需要删除的边',\n 'ntfAddStartPointFirst': '请先添加起点!',\n 'ntfInvalidEdge': '非法操作(起点终点相同)!',\n // 工作流实例\n 'wfTips': 'tips:点击节点可查看任务实例详情',\n 'ntfClickWaitingNode': '等待上游任务中...未生成任务实例,无法查看详情!',\n 'wfInitParams': '启动参数',\n // 容器\n 'newContainer': '新增容器',\n 'containerType': '容器类型',\n 'containerGitURL': 'Git仓库地址',\n 'branchName': '分支名称',\n 'username': '用户名',\n 'oldPassword': '旧密码',\n 'password': '密码',\n 'containerId': '容器ID',\n 'containerName': '容器名称',\n 'containerVersion': '容器版本',\n 'deployTime': '部署时间',\n 'deploy': '部署',\n 'deployedWorkerList': '机器列表',\n 'uploadTips': '拖拽或点击文件后会自动上传',\n // 任务实例状态\n 'waitingDispatch': '等待派发',\n 'waitingWorkerReceive': '等待Worker接收',\n 'running': '运行中',\n 'stopped': '手动停止',\n 'canceled': '手动取消',\n 'wfWaiting': '等待调度',\n 'waitingUpstream': '等待上游节点'\n }\n}, element_ui_lib_locale_lang_zh_CN__WEBPACK_IMPORTED_MODULE_1___default.a);\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (cn);\n\n//# sourceURL=webpack:///./src/i18n/langs/cn.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Users_salieri_Desktop_code_PowerJob_Console_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/objectSpread2 */ \"./node_modules/@babel/runtime/helpers/esm/objectSpread2.js\");\n/* harmony import */ var element_ui_lib_locale_lang_zh_CN__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! element-ui/lib/locale/lang/zh-CN */ \"./node_modules/element-ui/lib/locale/lang/zh-CN.js\");\n/* harmony import */ var element_ui_lib_locale_lang_zh_CN__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(element_ui_lib_locale_lang_zh_CN__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\nvar cn = Object(_Users_salieri_Desktop_code_PowerJob_Console_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({\n message: {\n // common\n 'save': '保存',\n 'cancel': '取消',\n 'refresh': '刷新',\n 'query': '查询',\n 'reset': '重置',\n 'keyword': '关键字',\n 'run': '运行',\n 'edit': '编辑',\n 'delete': '删除',\n 'success': '成功',\n 'failed': '失败',\n 'detail': '详情',\n 'download': '下载',\n 'stop': '停止',\n 'back': '返回',\n 'all': '全部',\n 'more': '| 更多',\n // 欢迎界面\n 'appRegister': '执行应用注册',\n 'userRegister': '报警用户录入',\n 'appNameInputPLH': '请输入应用名称',\n 'appName': '应用名称',\n 'appPassword': '密码',\n 'register': '注册',\n 'name': '姓名',\n 'phone': '手机号',\n 'email': '邮箱地址',\n 'webhook': 'WebHook',\n 'welcomeTitle': '欢迎使用 PowerJob!',\n 'login': '登陆',\n 'logout': '退出',\n 'changeAppInfo': '修改应用信息',\n 'newPassword': '新密码',\n 'newPassword2': '确认密码',\n 'stayLogged': '保持登录状态',\n // 左侧tab栏\n 'tabHome': '系统首页',\n 'tabJobManage': '任务管理',\n 'tabJobInstance': '任务实例',\n 'tabWorkflowManage': '工作流管理',\n 'tabWfInstance': '工作流实例',\n 'tabContainerOps': '容器',\n 'tabTemplate': '模版生成',\n 'tabContainerManager': '容器运维',\n // 系统首页\n 'omsServerTime': '调度服务器时间',\n 'omsServerTimezone': '调度服务器时区',\n 'localBrowserTime': '本地时间',\n 'localBrowserTimezone': '本地时区',\n 'githubURL': '项目地址',\n 'docURL': '文档地址',\n 'totalJobNum': '任务总数',\n 'runningInstanceNum': '当前运行实例数',\n 'recentFailedInstanceNum': '近期失败任务数',\n 'workerNum': '集群机器数',\n 'workerAddress': '机器地址',\n 'cpuLoad': 'CPU 占用',\n 'memoryLoad': '内存占用',\n 'diskLoad': '磁盘占用',\n // 任务管理\n 'jobId': '任务ID',\n 'instanceId': '任务实例ID',\n 'jobName': '任务名称',\n 'scheduleInfo': '定时信息',\n 'executeType': '执行类型',\n 'processorType': '处理器类型',\n 'status': '状态',\n 'operation': '操作',\n 'newJob': '新建任务',\n 'jobDescription': '任务描述',\n 'jobParams': '任务参数',\n 'timeExpressionType': '时间表达式类型',\n 'timeExpressionPlaceHolder': 'CRON填写CRON表达式,秒级任务填写整数,API无需填写',\n 'executeConfig': '执行配置',\n 'javaProcessorInfoPLH': '全限定类名,eg:com.github.kfcfans.DemoProcessor',\n 'containerProcessorInfoPLH': '容器ID#全限定类名,eg:1#com.github.kfcfans.DemoProcessor',\n 'shellProcessorInfoPLH': 'SHELL脚本文件内容',\n 'pythonProcessorInfoPLH': 'Python脚本文件内容',\n 'runtimeConfig': '运行时配置',\n 'maxInstanceNum': '最大实例数',\n 'threadConcurrency': '单机线程并发度',\n 'timeout': '运行时间限制(毫秒)',\n 'retryConfig': '重试配置',\n 'taskRetryTimes': 'Instance重试次数',\n 'subTaskRetryTimes': \"Task重试次数\",\n 'workerConfig': '机器配置',\n 'minCPU': '最低CPU核心数',\n 'minMemory': '最低内存(GB)',\n 'minDisk': '最低磁盘空间(GB)',\n 'clusterConfig': '集群配置',\n 'designatedWorkerAddress': '执行机器地址',\n 'designatedWorkerAddressPLH': '执行机器地址(可选,不指定代表全部;多值英文逗号分割)',\n 'maxWorkerNum': '最大执行机器数量',\n 'maxWorkerNumPLH': '最大执行机器数量(0代表不限)',\n 'alarmConfig': '报警配置',\n 'alarmSelectorPLH': '选择报警通知人员',\n 'standalone': '单机执行',\n 'broadcast': '广播执行',\n 'map': 'Map执行',\n 'mapReduce': 'MapReduce执行',\n 'fixRate': '固定频率(毫秒)',\n 'fixDelay': '固定延迟(毫秒)',\n 'workflow': '工作流',\n 'validateTimeExpression': '校验定时参数',\n 'javaContainer': 'Java(容器)',\n 'runHistory': '运行记录',\n 'reRun': '重跑',\n // 任务实例管理\n 'wfInstanceId': '工作流实例ID',\n 'normalInstance': '普通任务实例',\n 'wfInstance': '工作流任务实例',\n 'triggerTime': '触发时间',\n 'finishedTime': '结束时间',\n 'log': '日志',\n 'runningTimes': '运行次数',\n 'taskTrackerAddress': 'TaskTracker 地址',\n 'startTime': '开始时间',\n 'expectedTriggerTime': '预计执行时间',\n 'result': '任务结果',\n 'subTaskInfo': 'Task 信息',\n 'secondlyJobHistory': '最近 10 条秒级任务历史记录(秒级任务专用)',\n 'subInstanceId': '子任务实例ID',\n 'instanceParams': '任务实例参数',\n // 工作流管理\n 'wfId': '工作流ID',\n 'wfName': '工作流名称',\n 'newWorkflow': '新建工作流',\n 'wfDescription': '工作流描述',\n 'importJob': '导入任务',\n 'deleteJob': '删除任务',\n 'newStartPoint': '新增起点',\n 'newEndPoint': '新增终点',\n 'deleteEdge': '删除边',\n 'importJobTitle': \"请选择需要导入工作流的任务\",\n 'wfTimeExpressionPLH': 'CRON填写CRON表达式,API无需填写',\n 'import': '导入',\n 'ntfClickNeedDeleteNode': '请点击需要删除的节点',\n 'ntfClickStartPoint': '请点击起始节点',\n 'ntfClickTargetPoint': '请点击目标节点',\n 'ntfClickDeleteEdge': '请点击需要删除的边',\n 'ntfAddStartPointFirst': '请先添加起点!',\n 'ntfInvalidEdge': '非法操作(起点终点相同)!',\n // 工作流实例\n 'wfTips': 'tips:点击节点可查看任务实例详情',\n 'ntfClickWaitingNode': '等待上游任务中...未生成任务实例,无法查看详情!',\n 'wfInitParams': '启动参数',\n // 容器\n 'newContainer': '新增容器',\n 'containerType': '容器类型',\n 'containerGitURL': 'Git仓库地址',\n 'branchName': '分支名称',\n 'username': '用户名',\n 'oldPassword': '旧密码',\n 'password': '密码',\n 'containerId': '容器ID',\n 'containerName': '容器名称',\n 'containerVersion': '容器版本',\n 'deployTime': '部署时间',\n 'deploy': '部署',\n 'deployedWorkerList': '机器列表',\n 'uploadTips': '拖拽或点击文件后会自动上传',\n // 任务实例状态\n 'waitingDispatch': '等待派发',\n 'waitingWorkerReceive': '等待Worker接收',\n 'running': '运行中',\n 'stopped': '手动停止',\n 'canceled': '手动取消',\n 'wfWaiting': '等待调度',\n 'waitingUpstream': '等待上游节点'\n }\n}, element_ui_lib_locale_lang_zh_CN__WEBPACK_IMPORTED_MODULE_1___default.a);\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (cn);\n\n//# sourceURL=webpack:///./src/i18n/langs/cn.js?"); /***/ }), @@ -688,7 +688,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Use /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/objectSpread2 */ \"./node_modules/@babel/runtime/helpers/esm/objectSpread2.js\");\n/* harmony import */ var element_ui_lib_locale_lang_en__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! element-ui/lib/locale/lang/en */ \"./node_modules/element-ui/lib/locale/lang/en.js\");\n/* harmony import */ var element_ui_lib_locale_lang_en__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(element_ui_lib_locale_lang_en__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\nvar en = Object(_Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({\n message: {\n 'save': 'save',\n 'cancel': 'cancel',\n 'refresh': 'refresh',\n 'query': 'query',\n 'reset': 'reset',\n 'keyword': 'keyword',\n 'run': 'run',\n 'edit': 'edit',\n 'delete': 'delete',\n 'success': 'success',\n 'failed': 'failed',\n 'detail': 'detail',\n 'download': 'download',\n 'stop': 'stop',\n 'back': 'back',\n 'all': 'ALL',\n 'more': '| more',\n // 欢迎界面\n 'appRegister': 'App Registration',\n 'userRegister': 'User Registration',\n 'appNameInputPLH': 'Enter The AppName',\n 'appName': 'AppName',\n 'appPassword': 'AppPassword',\n 'register': 'register',\n 'name': 'name',\n 'phone': 'phone',\n 'email': 'email',\n 'webhook': 'webhook',\n 'welcomeTitle': 'Welcome to use PowerJob!',\n 'login': 'Login',\n 'logout': 'Logout',\n 'changeAppInfo': 'Change AppInfo',\n 'newPassword': 'New Password',\n 'newPassword2': 'Check New Password',\n 'stayLogged': 'Keep me logged in',\n 'tabHome': 'Home',\n 'tabJobManage': 'JobManage',\n 'tabJobInstance': 'JobInstance',\n 'tabWorkflowManage': 'WorkflowManage',\n 'tabWfInstance': 'WorkflowInstance',\n 'tabContainerOps': 'ContainerOps',\n 'tabTemplate': 'TemplateGenerator',\n 'tabContainerManager': 'ContainerManager',\n 'omsServerTime': 'Server Time',\n 'omsServerTimezone': 'Server Timezone',\n 'localBrowserTime': 'Local Time',\n 'localBrowserTimezone': 'Local Timezone',\n 'githubURL': 'GitHub Repo',\n 'docURL': 'Document Address',\n 'totalJobNum': 'total job Num',\n 'runningInstanceNum': 'running instance num',\n 'recentFailedInstanceNum': 'recent failed instance Num',\n 'workerNum': 'worker cluster size',\n 'workerAddress': 'worker address',\n 'cpuLoad': 'CPU Load',\n 'memoryLoad': 'Memory Load',\n 'diskLoad': 'Disk Load',\n // JobManage\n 'jobId': 'JobID',\n 'instanceId': 'InstanceID',\n 'jobName': 'JobName',\n 'scheduleInfo': 'ScheduleInfo',\n 'executeType': 'ExecuteType',\n 'processorType': 'ProcessorType',\n 'status': 'status',\n 'operation': 'operation',\n 'newJob': 'New Job',\n 'jobDescription': 'JobDescription',\n 'jobParams': 'JobParams',\n 'timeExpressionType': 'TimeExpressionType',\n 'timeExpressionPlaceHolder': 'cron expression or number(millions) for fix_rate/fix_delay job',\n 'executeConfig': 'ExecuteConfig',\n 'javaProcessorInfoPLH': 'classname, eg: com.github.kfcfans.DemoProcessor',\n 'containerProcessorInfoPLH': 'containerID#classname, eg: 1#com.github.kfcfans.DemoProcessor',\n 'shellProcessorInfoPLH': 'shell script',\n 'pythonProcessorInfoPLH': 'python script',\n 'runtimeConfig': 'RuntimeConfig',\n 'maxInstanceNum': 'MaxInstanceNum',\n 'threadConcurrency': 'ThreadConcurrency',\n 'timeout': 'TimeLimit (ms)',\n 'retryConfig': 'RetryConfig',\n 'taskRetryTimes': 'InstanceRetryTimes',\n 'subTaskRetryTimes': \"TaskRetryTimes\",\n 'workerConfig': 'WorkerConfig',\n 'minCPU': 'MinAvailableCPUCores',\n 'minMemory': 'MinMemory(GB)',\n 'minDisk': 'MinDisk(GB)',\n 'clusterConfig': 'ClusterConfig',\n 'designatedWorkerAddress': 'DesignatedWorkerAddress',\n 'designatedWorkerAddressPLH': 'empty for all worker or IP:Port,IP:Port ...',\n 'maxWorkerNum': 'MaxWorkerNum',\n 'maxWorkerNumPLH': '0 means no limit',\n 'alarmConfig': 'AlarmConfig',\n 'alarmSelectorPLH': 'select alarm recipient ',\n 'standalone': 'Standalone',\n 'broadcast': 'Broadcast',\n 'map': 'MAP',\n 'mapReduce': 'MapReduce',\n 'fixRate': 'Fix Rate (ms)',\n 'fixDelay': 'Fix Delay (ms)',\n 'workflow': 'workflow',\n 'validateTimeExpression': 'validate',\n 'javaContainer': 'Java(Container)',\n 'runHistory': 'history',\n 'reRun': 'retry',\n // JobInstance\n 'wfInstanceId': 'WorkflowInstanceId',\n 'normalInstance': 'normal instance',\n 'wfInstance': 'workflow instance',\n 'triggerTime': 'trigger time',\n 'finishedTime': 'finished time',\n 'log': 'log',\n 'runningTimes': 'running times',\n 'taskTrackerAddress': 'taskTracker address',\n 'startTime': 'start time',\n 'expectedTriggerTime': 'expected trigger time',\n 'result': 'result',\n 'subTaskInfo': 'task info',\n 'secondlyJobHistory': 'secondlyJobHistory',\n 'subInstanceId': 'subInstanceId',\n 'instanceParams': 'instanceParams',\n // workflowManage\n 'wfId': 'WorkflowID',\n 'wfName': 'WorkflowName',\n 'newWorkflow': 'new workflow',\n 'wfDescription': 'description',\n 'importJob': 'import job',\n 'deleteJob': 'delete job',\n 'newStartPoint': 'new starting point',\n 'newEndPoint': 'new ending point',\n 'deleteEdge': 'delete edge',\n 'importJobTitle': \"select jobs\",\n 'wfTimeExpressionPLH': 'cron expression for CRON or empty for API',\n 'import': 'import',\n 'ntfClickNeedDeleteNode': 'Please click on the node you want to delete.',\n 'ntfClickStartPoint': 'Please click on the start node',\n 'ntfClickTargetPoint': 'Please click on the end node',\n 'ntfClickDeleteEdge': 'Please click on the edge you want to remove.',\n 'ntfAddStartPointFirst': 'Please add the starting point first!',\n 'ntfInvalidEdge': 'Illegal operation (same origin and destination)!',\n // workflowInstance\n 'wfTips': 'tips:Click on a node to view details of the job instance',\n 'ntfClickWaitingNode': 'Waiting for the upstream instances... No instances have been generated, and details cannot be viewed!',\n 'wfInitParams': 'initParams',\n // 容器\n 'newContainer': 'new container',\n 'containerType': 'type',\n 'containerGitURL': 'Git URL',\n 'branchName': 'branch',\n 'username': 'username',\n 'oldPassword': 'old password',\n 'password': 'password',\n 'containerId': 'ID',\n 'containerName': 'name',\n 'containerVersion': 'version',\n 'deployTime': 'deployed time',\n 'deploy': 'deploy',\n 'deployedWorkerList': 'worker list',\n 'uploadTips': 'Drag and drop or click on the file to upload it automatically',\n // 任务实例状态\n 'waitingDispatch': 'waiting dispatch',\n 'waitingWorkerReceive': 'waiting receive',\n 'running': 'running',\n 'stopped': 'stopped',\n 'canceled': 'canceled',\n 'wfWaiting': 'waiting',\n 'waitingUpstream': 'waiting upstream'\n }\n}, element_ui_lib_locale_lang_en__WEBPACK_IMPORTED_MODULE_1___default.a);\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (en);\n\n//# sourceURL=webpack:///./src/i18n/langs/en.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Users_salieri_Desktop_code_PowerJob_Console_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/objectSpread2 */ \"./node_modules/@babel/runtime/helpers/esm/objectSpread2.js\");\n/* harmony import */ var element_ui_lib_locale_lang_en__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! element-ui/lib/locale/lang/en */ \"./node_modules/element-ui/lib/locale/lang/en.js\");\n/* harmony import */ var element_ui_lib_locale_lang_en__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(element_ui_lib_locale_lang_en__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\nvar en = Object(_Users_salieri_Desktop_code_PowerJob_Console_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({\n message: {\n 'save': 'save',\n 'cancel': 'cancel',\n 'refresh': 'refresh',\n 'query': 'query',\n 'reset': 'reset',\n 'keyword': 'keyword',\n 'run': 'run',\n 'edit': 'edit',\n 'delete': 'delete',\n 'success': 'success',\n 'failed': 'failed',\n 'detail': 'detail',\n 'download': 'download',\n 'stop': 'stop',\n 'back': 'back',\n 'all': 'ALL',\n 'more': '| more',\n // 欢迎界面\n 'appRegister': 'App Registration',\n 'userRegister': 'User Registration',\n 'appNameInputPLH': 'Enter The AppName',\n 'appName': 'AppName',\n 'appPassword': 'AppPassword',\n 'register': 'register',\n 'name': 'name',\n 'phone': 'phone',\n 'email': 'email',\n 'webhook': 'webhook',\n 'welcomeTitle': 'Welcome to use PowerJob!',\n 'login': 'Login',\n 'logout': 'Logout',\n 'changeAppInfo': 'Change AppInfo',\n 'newPassword': 'New Password',\n 'newPassword2': 'Check New Password',\n 'stayLogged': 'Keep me logged in',\n 'tabHome': 'Home',\n 'tabJobManage': 'JobManage',\n 'tabJobInstance': 'JobInstance',\n 'tabWorkflowManage': 'WorkflowManage',\n 'tabWfInstance': 'WorkflowInstance',\n 'tabContainerOps': 'ContainerOps',\n 'tabTemplate': 'TemplateGenerator',\n 'tabContainerManager': 'ContainerManager',\n 'omsServerTime': 'Server Time',\n 'omsServerTimezone': 'Server Timezone',\n 'localBrowserTime': 'Local Time',\n 'localBrowserTimezone': 'Local Timezone',\n 'githubURL': 'GitHub Repo',\n 'docURL': 'Document Address',\n 'totalJobNum': 'total job Num',\n 'runningInstanceNum': 'running instance num',\n 'recentFailedInstanceNum': 'recent failed instance Num',\n 'workerNum': 'worker cluster size',\n 'workerAddress': 'worker address',\n 'cpuLoad': 'CPU Load',\n 'memoryLoad': 'Memory Load',\n 'diskLoad': 'Disk Load',\n // JobManage\n 'jobId': 'JobID',\n 'instanceId': 'InstanceID',\n 'jobName': 'JobName',\n 'scheduleInfo': 'ScheduleInfo',\n 'executeType': 'ExecuteType',\n 'processorType': 'ProcessorType',\n 'status': 'status',\n 'operation': 'operation',\n 'newJob': 'New Job',\n 'jobDescription': 'JobDescription',\n 'jobParams': 'JobParams',\n 'timeExpressionType': 'TimeExpressionType',\n 'timeExpressionPlaceHolder': 'cron expression or number(millions) for fix_rate/fix_delay job',\n 'executeConfig': 'ExecuteConfig',\n 'javaProcessorInfoPLH': 'classname, eg: com.github.kfcfans.DemoProcessor',\n 'containerProcessorInfoPLH': 'containerID#classname, eg: 1#com.github.kfcfans.DemoProcessor',\n 'shellProcessorInfoPLH': 'shell script',\n 'pythonProcessorInfoPLH': 'python script',\n 'runtimeConfig': 'RuntimeConfig',\n 'maxInstanceNum': 'MaxInstanceNum',\n 'threadConcurrency': 'ThreadConcurrency',\n 'timeout': 'TimeLimit (ms)',\n 'retryConfig': 'RetryConfig',\n 'taskRetryTimes': 'InstanceRetryTimes',\n 'subTaskRetryTimes': \"TaskRetryTimes\",\n 'workerConfig': 'WorkerConfig',\n 'minCPU': 'MinAvailableCPUCores',\n 'minMemory': 'MinMemory(GB)',\n 'minDisk': 'MinDisk(GB)',\n 'clusterConfig': 'ClusterConfig',\n 'designatedWorkerAddress': 'DesignatedWorkerAddress',\n 'designatedWorkerAddressPLH': 'empty for all worker or IP:Port,IP:Port ...',\n 'maxWorkerNum': 'MaxWorkerNum',\n 'maxWorkerNumPLH': '0 means no limit',\n 'alarmConfig': 'AlarmConfig',\n 'alarmSelectorPLH': 'select alarm recipient ',\n 'standalone': 'Standalone',\n 'broadcast': 'Broadcast',\n 'map': 'MAP',\n 'mapReduce': 'MapReduce',\n 'fixRate': 'Fix Rate (ms)',\n 'fixDelay': 'Fix Delay (ms)',\n 'workflow': 'workflow',\n 'validateTimeExpression': 'validate',\n 'javaContainer': 'Java(Container)',\n 'runHistory': 'history',\n 'reRun': 'retry',\n // JobInstance\n 'wfInstanceId': 'WorkflowInstanceId',\n 'normalInstance': 'normal instance',\n 'wfInstance': 'workflow instance',\n 'triggerTime': 'trigger time',\n 'finishedTime': 'finished time',\n 'log': 'log',\n 'runningTimes': 'running times',\n 'taskTrackerAddress': 'taskTracker address',\n 'startTime': 'start time',\n 'expectedTriggerTime': 'expected trigger time',\n 'result': 'result',\n 'subTaskInfo': 'task info',\n 'secondlyJobHistory': 'secondlyJobHistory',\n 'subInstanceId': 'subInstanceId',\n 'instanceParams': 'instanceParams',\n // workflowManage\n 'wfId': 'WorkflowID',\n 'wfName': 'WorkflowName',\n 'newWorkflow': 'new workflow',\n 'wfDescription': 'description',\n 'importJob': 'import job',\n 'deleteJob': 'delete job',\n 'newStartPoint': 'new starting point',\n 'newEndPoint': 'new ending point',\n 'deleteEdge': 'delete edge',\n 'importJobTitle': \"select jobs\",\n 'wfTimeExpressionPLH': 'cron expression for CRON or empty for API',\n 'import': 'import',\n 'ntfClickNeedDeleteNode': 'Please click on the node you want to delete.',\n 'ntfClickStartPoint': 'Please click on the start node',\n 'ntfClickTargetPoint': 'Please click on the end node',\n 'ntfClickDeleteEdge': 'Please click on the edge you want to remove.',\n 'ntfAddStartPointFirst': 'Please add the starting point first!',\n 'ntfInvalidEdge': 'Illegal operation (same origin and destination)!',\n // workflowInstance\n 'wfTips': 'tips:Click on a node to view details of the job instance',\n 'ntfClickWaitingNode': 'Waiting for the upstream instances... No instances have been generated, and details cannot be viewed!',\n 'wfInitParams': 'initParams',\n // 容器\n 'newContainer': 'new container',\n 'containerType': 'type',\n 'containerGitURL': 'Git URL',\n 'branchName': 'branch',\n 'username': 'username',\n 'oldPassword': 'old password',\n 'password': 'password',\n 'containerId': 'ID',\n 'containerName': 'name',\n 'containerVersion': 'version',\n 'deployTime': 'deployed time',\n 'deploy': 'deploy',\n 'deployedWorkerList': 'worker list',\n 'uploadTips': 'Drag and drop or click on the file to upload it automatically',\n // 任务实例状态\n 'waitingDispatch': 'waiting dispatch',\n 'waitingWorkerReceive': 'waiting receive',\n 'running': 'running',\n 'stopped': 'stopped',\n 'canceled': 'canceled',\n 'wfWaiting': 'waiting',\n 'waitingUpstream': 'waiting upstream'\n }\n}, element_ui_lib_locale_lang_en__WEBPACK_IMPORTED_MODULE_1___default.a);\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (en);\n\n//# sourceURL=webpack:///./src/i18n/langs/en.js?"); /***/ }), @@ -712,7 +712,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _en_ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_object_to_string__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.object.to-string */ \"./node_modules/core-js/modules/es.object.to-string.js\");\n/* harmony import */ var core_js_modules_es_object_to_string__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_object_to_string__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_regexp_exec__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.regexp.exec */ \"./node_modules/core-js/modules/es.regexp.exec.js\");\n/* harmony import */ var core_js_modules_es_regexp_exec__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_regexp_exec__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_regexp_to_string__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.regexp.to-string */ \"./node_modules/core-js/modules/es.regexp.to-string.js\");\n/* harmony import */ var core_js_modules_es_regexp_to_string__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_regexp_to_string__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_string_search__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.string.search */ \"./node_modules/core-js/modules/es.string.search.js\");\n/* harmony import */ var core_js_modules_es_string_search__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_string_search__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_core_js_modules_es_array_iterator_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./node_modules/core-js/modules/es.array.iterator.js */ \"./node_modules/core-js/modules/es.array.iterator.js\");\n/* harmony import */ var _Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_core_js_modules_es_array_iterator_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_core_js_modules_es_array_iterator_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_core_js_modules_es_promise_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./node_modules/core-js/modules/es.promise.js */ \"./node_modules/core-js/modules/es.promise.js\");\n/* harmony import */ var _Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_core_js_modules_es_promise_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_core_js_modules_es_promise_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_core_js_modules_es_object_assign_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./node_modules/core-js/modules/es.object.assign.js */ \"./node_modules/core-js/modules/es.object.assign.js\");\n/* harmony import */ var _Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_core_js_modules_es_object_assign_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_core_js_modules_es_object_assign_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var _Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_core_js_modules_es_promise_finally_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./node_modules/core-js/modules/es.promise.finally.js */ \"./node_modules/core-js/modules/es.promise.finally.js\");\n/* harmony import */ var _Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_core_js_modules_es_promise_finally_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_Users_tjq_Desktop_DistributeCompute_PowerJob_Console_node_modules_core_js_modules_es_promise_finally_js__WEBPACK_IMPORTED_MODULE_7__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm.js\");\n/* harmony import */ var _App_vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./App.vue */ \"./src/App.vue\");\n/* harmony import */ var element_ui__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! element-ui */ \"./node_modules/element-ui/lib/element-ui.common.js\");\n/* harmony import */ var element_ui__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(element_ui__WEBPACK_IMPORTED_MODULE_10__);\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./styles.scss */ \"./src/styles.scss\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(_styles_scss__WEBPACK_IMPORTED_MODULE_11__);\n/* harmony import */ var _plugins_element_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./plugins/element.js */ \"./src/plugins/element.js\");\n/* harmony import */ var _i18n_i18n__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./i18n/i18n */ \"./src/i18n/i18n.js\");\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! axios */ \"./node_modules/axios/index.js\");\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(axios__WEBPACK_IMPORTED_MODULE_14__);\n/* harmony import */ var flyio__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! flyio */ \"./node_modules/flyio/index.js\");\n/* harmony import */ var flyio__WEBPACK_IMPORTED_MODULE_15___default = /*#__PURE__*/__webpack_require__.n(flyio__WEBPACK_IMPORTED_MODULE_15__);\n/* harmony import */ var _router__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./router */ \"./src/router.js\");\n/* harmony import */ var _store__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./store */ \"./src/store.js\");\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./common */ \"./src/common.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n // axios 负责统一拦截处理 ResultDTO,fly 负责处理不需要拦截的请求\n\n\n\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_8__[\"default\"].use(element_ui__WEBPACK_IMPORTED_MODULE_10___default.a); // let baseURL = \"http://139.224.83.134:7700\";\n\nvar baseURL = \"/\";\nvar timeout = 10000;\nvue__WEBPACK_IMPORTED_MODULE_8__[\"default\"].prototype.common = _common__WEBPACK_IMPORTED_MODULE_18__[\"default\"];\n/* ******* axios config ******* */\n\nvue__WEBPACK_IMPORTED_MODULE_8__[\"default\"].prototype.axios = axios__WEBPACK_IMPORTED_MODULE_14___default.a;\naxios__WEBPACK_IMPORTED_MODULE_14___default.a.defaults.baseURL = baseURL;\naxios__WEBPACK_IMPORTED_MODULE_14___default.a.defaults.timeout = timeout;\n/* ******* fly.io config ******* */\n\nvue__WEBPACK_IMPORTED_MODULE_8__[\"default\"].prototype.flyio = flyio__WEBPACK_IMPORTED_MODULE_15___default.a;\nflyio__WEBPACK_IMPORTED_MODULE_15___default.a.config.baseURL = baseURL;\nflyio__WEBPACK_IMPORTED_MODULE_15___default.a.config.timeout = timeout;\nvue__WEBPACK_IMPORTED_MODULE_8__[\"default\"].config.productionTip = false;\nnew vue__WEBPACK_IMPORTED_MODULE_8__[\"default\"]({\n router: _router__WEBPACK_IMPORTED_MODULE_16__[\"default\"],\n store: _store__WEBPACK_IMPORTED_MODULE_17__[\"default\"],\n i18n: _i18n_i18n__WEBPACK_IMPORTED_MODULE_13__[\"default\"],\n render: function render(h) {\n return h(_App_vue__WEBPACK_IMPORTED_MODULE_9__[\"default\"]);\n }\n}).$mount('#app'); //请求发送拦截,没有 appId 要求重新 \"登录\"\n\naxios__WEBPACK_IMPORTED_MODULE_14___default.a.interceptors.request.use(function (request) {\n var url = request.url;\n var isListAppInfo = url.search(\"/appInfo/list\") !== -1;\n var isAppRegister = url.search(\"/appInfo/save\") !== -1;\n var isUserRegister = url.search(\"/user/save\") !== -1;\n var isAssertAppInfo = url.search(\"/appInfo/assert\") !== -1;\n\n if (isListAppInfo || isAppRegister || isUserRegister || isAssertAppInfo) {\n return request;\n }\n\n var appId = _store__WEBPACK_IMPORTED_MODULE_17__[\"default\"].state.appInfo.id;\n\n if (appId === undefined || appId === null) {\n _router__WEBPACK_IMPORTED_MODULE_16__[\"default\"].push(\"/\"); // remove no appId warn due to too much user report this is a bug...\n\n return Promise.reject();\n }\n\n return request;\n}, function (error) {\n // Do something with request error\n return Promise.reject(error);\n}); // 请求返回拦截,封装公共处理逻辑\n\naxios__WEBPACK_IMPORTED_MODULE_14___default.a.interceptors.response.use(function (response) {\n if (response.data.success === true) {\n return response.data.data;\n }\n\n element_ui__WEBPACK_IMPORTED_MODULE_10__[\"Message\"].warning(\"ERROR:\" + response.data.message);\n return Promise.reject(response.data.msg);\n}, function (error) {\n element_ui__WEBPACK_IMPORTED_MODULE_10__[\"Message\"].error(error.toString());\n return Promise.reject(error);\n});\n/* harmony default export */ __webpack_exports__[\"default\"] = (baseURL);\n\n//# sourceURL=webpack:///./src/main.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_object_to_string__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.object.to-string */ \"./node_modules/core-js/modules/es.object.to-string.js\");\n/* harmony import */ var core_js_modules_es_object_to_string__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_object_to_string__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_regexp_exec__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.regexp.exec */ \"./node_modules/core-js/modules/es.regexp.exec.js\");\n/* harmony import */ var core_js_modules_es_regexp_exec__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_regexp_exec__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_regexp_to_string__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.regexp.to-string */ \"./node_modules/core-js/modules/es.regexp.to-string.js\");\n/* harmony import */ var core_js_modules_es_regexp_to_string__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_regexp_to_string__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_string_search__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.string.search */ \"./node_modules/core-js/modules/es.string.search.js\");\n/* harmony import */ var core_js_modules_es_string_search__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_string_search__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _Users_salieri_Desktop_code_PowerJob_Console_node_modules_core_js_modules_es_array_iterator_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./node_modules/core-js/modules/es.array.iterator.js */ \"./node_modules/core-js/modules/es.array.iterator.js\");\n/* harmony import */ var _Users_salieri_Desktop_code_PowerJob_Console_node_modules_core_js_modules_es_array_iterator_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_Users_salieri_Desktop_code_PowerJob_Console_node_modules_core_js_modules_es_array_iterator_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _Users_salieri_Desktop_code_PowerJob_Console_node_modules_core_js_modules_es_promise_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./node_modules/core-js/modules/es.promise.js */ \"./node_modules/core-js/modules/es.promise.js\");\n/* harmony import */ var _Users_salieri_Desktop_code_PowerJob_Console_node_modules_core_js_modules_es_promise_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_Users_salieri_Desktop_code_PowerJob_Console_node_modules_core_js_modules_es_promise_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _Users_salieri_Desktop_code_PowerJob_Console_node_modules_core_js_modules_es_object_assign_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./node_modules/core-js/modules/es.object.assign.js */ \"./node_modules/core-js/modules/es.object.assign.js\");\n/* harmony import */ var _Users_salieri_Desktop_code_PowerJob_Console_node_modules_core_js_modules_es_object_assign_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_Users_salieri_Desktop_code_PowerJob_Console_node_modules_core_js_modules_es_object_assign_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var _Users_salieri_Desktop_code_PowerJob_Console_node_modules_core_js_modules_es_promise_finally_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./node_modules/core-js/modules/es.promise.finally.js */ \"./node_modules/core-js/modules/es.promise.finally.js\");\n/* harmony import */ var _Users_salieri_Desktop_code_PowerJob_Console_node_modules_core_js_modules_es_promise_finally_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_Users_salieri_Desktop_code_PowerJob_Console_node_modules_core_js_modules_es_promise_finally_js__WEBPACK_IMPORTED_MODULE_7__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm.js\");\n/* harmony import */ var _App_vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./App.vue */ \"./src/App.vue\");\n/* harmony import */ var element_ui__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! element-ui */ \"./node_modules/element-ui/lib/element-ui.common.js\");\n/* harmony import */ var element_ui__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(element_ui__WEBPACK_IMPORTED_MODULE_10__);\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./styles.scss */ \"./src/styles.scss\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(_styles_scss__WEBPACK_IMPORTED_MODULE_11__);\n/* harmony import */ var _plugins_element_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./plugins/element.js */ \"./src/plugins/element.js\");\n/* harmony import */ var _i18n_i18n__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./i18n/i18n */ \"./src/i18n/i18n.js\");\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! axios */ \"./node_modules/axios/index.js\");\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(axios__WEBPACK_IMPORTED_MODULE_14__);\n/* harmony import */ var flyio__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! flyio */ \"./node_modules/flyio/index.js\");\n/* harmony import */ var flyio__WEBPACK_IMPORTED_MODULE_15___default = /*#__PURE__*/__webpack_require__.n(flyio__WEBPACK_IMPORTED_MODULE_15__);\n/* harmony import */ var _router__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./router */ \"./src/router.js\");\n/* harmony import */ var _store__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./store */ \"./src/store.js\");\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./common */ \"./src/common.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n // axios 负责统一拦截处理 ResultDTO,fly 负责处理不需要拦截的请求\n\n\n\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_8__[\"default\"].use(element_ui__WEBPACK_IMPORTED_MODULE_10___default.a); // let baseURL = \"http://139.224.83.134:7700\";\n\nvar baseURL = \"/\";\nvar timeout = 10000;\nvue__WEBPACK_IMPORTED_MODULE_8__[\"default\"].prototype.common = _common__WEBPACK_IMPORTED_MODULE_18__[\"default\"];\n/* ******* axios config ******* */\n\nvue__WEBPACK_IMPORTED_MODULE_8__[\"default\"].prototype.axios = axios__WEBPACK_IMPORTED_MODULE_14___default.a;\naxios__WEBPACK_IMPORTED_MODULE_14___default.a.defaults.baseURL = baseURL;\naxios__WEBPACK_IMPORTED_MODULE_14___default.a.defaults.timeout = timeout;\n/* ******* fly.io config ******* */\n\nvue__WEBPACK_IMPORTED_MODULE_8__[\"default\"].prototype.flyio = flyio__WEBPACK_IMPORTED_MODULE_15___default.a;\nflyio__WEBPACK_IMPORTED_MODULE_15___default.a.config.baseURL = baseURL;\nflyio__WEBPACK_IMPORTED_MODULE_15___default.a.config.timeout = timeout;\nvue__WEBPACK_IMPORTED_MODULE_8__[\"default\"].config.productionTip = false;\nnew vue__WEBPACK_IMPORTED_MODULE_8__[\"default\"]({\n router: _router__WEBPACK_IMPORTED_MODULE_16__[\"default\"],\n store: _store__WEBPACK_IMPORTED_MODULE_17__[\"default\"],\n i18n: _i18n_i18n__WEBPACK_IMPORTED_MODULE_13__[\"default\"],\n render: function render(h) {\n return h(_App_vue__WEBPACK_IMPORTED_MODULE_9__[\"default\"]);\n }\n}).$mount('#app'); //请求发送拦截,没有 appId 要求重新 \"登录\"\n\naxios__WEBPACK_IMPORTED_MODULE_14___default.a.interceptors.request.use(function (request) {\n var url = request.url;\n var isListAppInfo = url.search(\"/appInfo/list\") !== -1;\n var isAppRegister = url.search(\"/appInfo/save\") !== -1;\n var isUserRegister = url.search(\"/user/save\") !== -1;\n var isAssertAppInfo = url.search(\"/appInfo/assert\") !== -1;\n\n if (isListAppInfo || isAppRegister || isUserRegister || isAssertAppInfo) {\n return request;\n }\n\n var appId = _store__WEBPACK_IMPORTED_MODULE_17__[\"default\"].state.appInfo.id;\n\n if (appId === undefined || appId === null) {\n _router__WEBPACK_IMPORTED_MODULE_16__[\"default\"].push(\"/\"); // remove no appId warn due to too much user report this is a bug...\n\n return Promise.reject();\n }\n\n return request;\n}, function (error) {\n // Do something with request error\n return Promise.reject(error);\n}); // 请求返回拦截,封装公共处理逻辑\n\naxios__WEBPACK_IMPORTED_MODULE_14___default.a.interceptors.response.use(function (response) {\n if (response.data.success === true) {\n return response.data.data;\n }\n\n element_ui__WEBPACK_IMPORTED_MODULE_10__[\"Message\"].warning(\"ERROR:\" + response.data.message);\n return Promise.reject(response.data.msg);\n}, function (error) {\n element_ui__WEBPACK_IMPORTED_MODULE_10__[\"Message\"].error(error.toString());\n return Promise.reject(error);\n});\n/* harmony default export */ __webpack_exports__[\"default\"] = (baseURL);\n\n//# sourceURL=webpack:///./src/main.js?"); /***/ }), From ee80ae76a81abab44e43a52f06ed22043c32443e Mon Sep 17 00:00:00 2001 From: jjnnzb Date: Sun, 13 Dec 2020 20:50:29 +0800 Subject: [PATCH 08/19] Optimize statement. --- README_enUS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README_enUS.md b/README_enUS.md index 24a29d0d..3cbcad04 100644 --- a/README_enUS.md +++ b/README_enUS.md @@ -25,7 +25,7 @@ Well, PowerJob is there for you, it is the choice of a new generation. It is a p - Complete workflow support. PowerJob supports DAG(Directed acyclic graph) based online task configuration. Developers could arrange tasks on the console, while data could be transferred among tasks on the flow. - Extensive executor support: PowerJob supports multiple processors, including Spring Beans, ordinary Java objects, Shell, Python and so on. - Simple in dependency: PowerJob aims to be simple in dependency. The only dependency is merely database (MySQL / Oracle / MS SQLServer ...), with MongoDB being the extra dependency for storing large log files online. -- High availability and performance: Unlike traditional job-scheduling frameworks which rely on database locks, PowerJob server is lock-free. PowerJob supports unlimited horizontal expansion. It's easy to achieve high availability and performance by deploying as many PowerJob server instances as you need. +- High availability and performance: Unlike traditional job-scheduling frameworks that rely on database locks, PowerJob server is lock-free. PowerJob supports unlimited horizontal expansion. It's easy to achieve high availability and performance by deploying as many PowerJob server instances as you need. - Quick failover and recovery support: Whenever any task failed, PowerJob server would retry according to the configured strategy. As long as there were enough nodes in the cluster, the failed tasks could execute successfully finally. - Convenient to run and maintain: PowerJob supports online logging. Logs generated by the worker would be transferred and displayed on the console instantly, therefore reducing the cost of debugging and improving the efficiency significantly. @@ -38,7 +38,7 @@ Well, PowerJob is there for you, it is the choice of a new generation. It is a p ### Design goals -PowerJob aims to be an enterprise-level scheduling middleware. By deploying PowerJob-server as the scheduling center, +PowerJob aims to be an enterprise scheduling middleware. By deploying PowerJob-server as the scheduling center, all the applications could gain scheduling and distributed computing ability relying on PowerJob-worker. ### Online trial @@ -77,7 +77,7 @@ Application password: 123 # Others - PowerJob is permanently open source software(Apache License, Version 2.0), please feel free to try, deploy and put into production! -- Owner of PowerJob (@KFCFans) has abundant time for maintenance, and is willing to provide technical support if you have needs! +- Author of PowerJob (@KFCFans) has abundant time for maintenance, and is willing to provide technical support if you have needs! - Welcome to contribute to PowerJob, both Pull Requests and Issues are precious. - Please STAR PowerJob if it is valuable. ~ =  ̄ω ̄ = - Do you need any help or want to propose suggestions? Please raise Github issues or contact the Author @KFCFans-> `tengjiqi@gmail.com` directly. \ No newline at end of file From 9822e8a10fe4203e1a05fb79dd4e9391d2c0f501 Mon Sep 17 00:00:00 2001 From: tanwenhai Date: Tue, 15 Dec 2020 15:27:57 +0800 Subject: [PATCH 09/19] postgresql --- .../server/persistence/core/model/InstanceInfoDO.java | 3 +++ .../powerjob/server/persistence/core/model/JobInfoDO.java | 2 ++ .../server/persistence/core/model/WorkflowInfoDO.java | 2 ++ .../server/persistence/core/model/WorkflowInstanceInfoDO.java | 4 ++++ 4 files changed, 11 insertions(+) diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/InstanceInfoDO.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/InstanceInfoDO.java index 5af69945..b0d7599d 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/InstanceInfoDO.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/InstanceInfoDO.java @@ -5,6 +5,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; import javax.persistence.*; import java.util.Date; @@ -36,6 +37,7 @@ public class InstanceInfoDO { // 任务实例参数 @Lob @Column + @Type(type ="org.hibernate.type.StringType") private String instanceParams; // 该任务实例的类型,普通/工作流(InstanceType) @@ -49,6 +51,7 @@ public class InstanceInfoDO { // 执行结果(允许存储稍大的结果) @Lob @Column + @Type(type ="org.hibernate.type.StringType") private String result; // 预计触发时间 private Long expectedTriggerTime; diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/JobInfoDO.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/JobInfoDO.java index b5d2b171..5bfe66b7 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/JobInfoDO.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/JobInfoDO.java @@ -5,6 +5,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; import javax.persistence.*; import java.util.Date; @@ -52,6 +53,7 @@ public class JobInfoDO { // 执行器信息(可能需要存储整个脚本文件) @Lob @Column + @Type(type ="org.hibernate.type.StringType") private String processorInfo; /* ************************** 运行时配置 ************************** */ diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInfoDO.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInfoDO.java index f3c5d560..3bcb6ac1 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInfoDO.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInfoDO.java @@ -4,6 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; import javax.persistence.*; import java.util.Date; @@ -35,6 +36,7 @@ public class WorkflowInfoDO { // 工作流的DAG图信息(点线式DAG的json) @Lob @Column + @Type(type ="org.hibernate.type.StringType") private String peDAG; /* ************************** 定时参数 ************************** */ diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInstanceInfoDO.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInstanceInfoDO.java index e6f483c4..2dcb9a1c 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInstanceInfoDO.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInstanceInfoDO.java @@ -4,6 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; import javax.persistence.*; import java.util.Date; @@ -39,13 +40,16 @@ public class WorkflowInstanceInfoDO { // 工作流启动参数 @Lob @Column + @Type(type ="org.hibernate.type.StringType") private String wfInitParams; @Lob @Column + @Type(type ="org.hibernate.type.StringType") private String dag; @Lob @Column + @Type(type ="org.hibernate.type.StringType") private String result; // 预计触发时间 From be43839d730d8ba945614179ba175a1f430c826b Mon Sep 17 00:00:00 2001 From: tanwenhai Date: Tue, 15 Dec 2020 15:29:06 +0800 Subject: [PATCH 10/19] actuator endpoint --- powerjob-server/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/powerjob-server/pom.xml b/powerjob-server/pom.xml index 68036a10..080e85d1 100644 --- a/powerjob-server/pom.xml +++ b/powerjob-server/pom.xml @@ -119,6 +119,11 @@ spring-boot-starter-data-mongodb ${springboot.version} + + org.springframework.boot + spring-boot-starter-actuator + ${springboot.version} + org.springframework.boot spring-boot-starter-mail From e311e7c50062115c390c16966c5a8d294eb964b6 Mon Sep 17 00:00:00 2001 From: tanwenhai Date: Tue, 15 Dec 2020 16:11:02 +0800 Subject: [PATCH 11/19] id generate --- .../core/repository/ServerInfoRepository.java | 9 ++++ .../server/service/id/IdGenerateService.java | 52 ++++++++++++++----- .../resources/application-daily.properties | 17 ++---- 3 files changed, 51 insertions(+), 27 deletions(-) diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/repository/ServerInfoRepository.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/repository/ServerInfoRepository.java index 615933f2..7f0b70ba 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/repository/ServerInfoRepository.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/repository/ServerInfoRepository.java @@ -2,6 +2,11 @@ package com.github.kfcfans.powerjob.server.persistence.core.repository; import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Lock; +import org.springframework.data.jpa.repository.Query; + +import javax.persistence.LockModeType; +import java.util.List; /** * 服务器信息 数据操作层 @@ -11,4 +16,8 @@ import org.springframework.data.jpa.repository.JpaRepository; */ public interface ServerInfoRepository extends JpaRepository { ServerInfoDO findByIp(String ip); + + @Query("select t from ServerInfoDO as t order by t.id asc") + @Lock(LockModeType.PESSIMISTIC_WRITE) + List findAllAndLockTable(); } diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java index e56462fa..bf3f0ee7 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java @@ -3,9 +3,23 @@ package com.github.kfcfans.powerjob.server.service.id; import com.github.kfcfans.powerjob.common.utils.NetUtils; import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.repository.ServerInfoRepository; +import com.google.common.base.Throwables; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.support.JdbcUtils; import org.springframework.stereotype.Service; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionTemplate; +import org.springframework.util.Assert; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; /** * 唯一ID生成服务,使用 Twitter snowflake 算法 @@ -24,20 +38,32 @@ public class IdGenerateService { private static final int DATA_CENTER_ID = 0; @Autowired - public IdGenerateService(ServerInfoRepository serverInfoRepository) { + public IdGenerateService(ServerInfoRepository serverInfoRepository, + @Qualifier("coreTransactionManager") PlatformTransactionManager platformTransactionManager) { + TransactionTemplate transactionTemplate = new TransactionTemplate(platformTransactionManager); + // 服务频繁重启,数据库id自增值过大,使用表锁获取机器id + snowFlakeIdGenerator = transactionTemplate.execute(action -> { + List serverInfos = serverInfoRepository.findAllAndLockTable(); + String ip = NetUtils.getLocalHost(); + ServerInfoDO server = serverInfoRepository.findByIp(ip); + Long id = null; + if (server == null) { + ServerInfoDO newServerInfo = new ServerInfoDO(ip); + serverInfoRepository.saveAndFlush(newServerInfo); + id = serverInfos.size() + 1L; + } else { + for (int i = 0, len = serverInfos.size(); i < len; i++) { + if (Objects.equals(serverInfos.get(i).getId(), server.getId())) { + id = i + 1L; + break; + } + } + } + Assert.notNull(id, "[IdGenerateService] init snowflake error, id is null"); + log.info("[IdGenerateService] init snowflake for server(address={}) by machineId({}).", ip, id); - String ip = NetUtils.getLocalHost(); - ServerInfoDO server = serverInfoRepository.findByIp(ip); - - if (server == null) { - ServerInfoDO newServerInfo = new ServerInfoDO(ip); - server = serverInfoRepository.saveAndFlush(newServerInfo); - } - - Long id = server.getId(); - snowFlakeIdGenerator = new SnowFlakeIdGenerator(DATA_CENTER_ID, id); - - log.info("[IdGenerateService] init snowflake for server(address={}) by machineId({}).", ip, id); + return new SnowFlakeIdGenerator(DATA_CENTER_ID, id); + }); } /** diff --git a/powerjob-server/src/main/resources/application-daily.properties b/powerjob-server/src/main/resources/application-daily.properties index 18bb67ef..32d7da66 100644 --- a/powerjob-server/src/main/resources/application-daily.properties +++ b/powerjob-server/src/main/resources/application-daily.properties @@ -3,28 +3,17 @@ logging.config=classpath:logback-dev.xml ####### 外部数据库配置(需要用户更改为自己的数据库配置) ####### spring.datasource.core.driver-class-name=com.mysql.cj.jdbc.Driver -spring.datasource.core.jdbc-url=jdbc:mysql://localhost:3306/powerjob-daily?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai +spring.datasource.core.jdbc-url=jdbc:mysql://localhost:3306/powerjob?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai spring.datasource.core.username=root -spring.datasource.core.password=No1Bug2Please3! +spring.datasource.core.password=123456 spring.datasource.core.hikari.maximum-pool-size=20 spring.datasource.core.hikari.minimum-idle=5 ####### mongoDB配置,非核心依赖,通过配置 oms.mongodb.enable=false 来关闭 ####### -oms.mongodb.enable=true +oms.mongodb.enable=false spring.data.mongodb.uri=mongodb+srv://zqq:No1Bug2Please3!@cluster0.wie54.gcp.mongodb.net/powerjob_daily?retryWrites=true&w=majority -####### 邮件配置(不需要邮件报警可以删除以下配置来避免报错) ####### -spring.mail.host=smtp.163.com -spring.mail.username=zqq@163.com -spring.mail.password=GOFZPNARMVKCGONV -spring.mail.properties.mail.smtp.auth=true -spring.mail.properties.mail.smtp.starttls.enable=true -spring.mail.properties.mail.smtp.starttls.required=true -####### 钉钉报警配置(不需要钉钉报警可以删除以下配置来避免报错) ####### -oms.alarm.ding.app-key=dingauqwkvxxnqskknfv -oms.alarm.ding.app-secret=XWrEPdAZMPgJeFtHuL0LH73LRj-74umF2_0BFcoXMfvnX0pCQvt0rpb1JOJU_HLl -oms.alarm.ding.agent-id=847044348 ####### 资源清理配置 ####### oms.instanceinfo.retention=1 From ca6b02d19f9b6bdba892a2560288e858e1da3fcd Mon Sep 17 00:00:00 2001 From: tanwenhai Date: Tue, 15 Dec 2020 16:14:18 +0800 Subject: [PATCH 12/19] reset --- .../resources/application-daily.properties | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/powerjob-server/src/main/resources/application-daily.properties b/powerjob-server/src/main/resources/application-daily.properties index 32d7da66..9b1e2b7a 100644 --- a/powerjob-server/src/main/resources/application-daily.properties +++ b/powerjob-server/src/main/resources/application-daily.properties @@ -3,17 +3,28 @@ logging.config=classpath:logback-dev.xml ####### 外部数据库配置(需要用户更改为自己的数据库配置) ####### spring.datasource.core.driver-class-name=com.mysql.cj.jdbc.Driver -spring.datasource.core.jdbc-url=jdbc:mysql://localhost:3306/powerjob?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai +spring.datasource.core.jdbc-url=jdbc:mysql://localhost:3306/powerjob-daily?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai spring.datasource.core.username=root -spring.datasource.core.password=123456 +spring.datasource.core.password=No1Bug2Please3! spring.datasource.core.hikari.maximum-pool-size=20 spring.datasource.core.hikari.minimum-idle=5 ####### mongoDB配置,非核心依赖,通过配置 oms.mongodb.enable=false 来关闭 ####### -oms.mongodb.enable=false +oms.mongodb.enable=true spring.data.mongodb.uri=mongodb+srv://zqq:No1Bug2Please3!@cluster0.wie54.gcp.mongodb.net/powerjob_daily?retryWrites=true&w=majority +####### 邮件配置(不需要邮件报警可以删除以下配置来避免报错) ####### +spring.mail.host=smtp.163.com +spring.mail.username=zqq@163.com +spring.mail.password=GOFZPNARMVKCGONV +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.smtp.starttls.enable=true +spring.mail.properties.mail.smtp.starttls.required=true +####### 钉钉报警配置(不需要钉钉报警可以删除以下配置来避免报错) ####### +oms.alarm.ding.app-key=dingauqwkvxxnqskknfv +oms.alarm.ding.app-secret=XWrEPdAZMPgJeFtHuL0LH73LRj-74umF2_0BFcoXMfvnX0pCQvt0rpb1JOJU_HLl +oms.alarm.ding.agent-id=847044348 ####### 资源清理配置 ####### oms.instanceinfo.retention=1 @@ -21,7 +32,4 @@ oms.container.retention.local=1 oms.container.retention.remote=-1 ####### 缓存配置 ####### -oms.instance.metadata.cache.size=1024 - -####### 精确获取 server 的百分比,0~100,100代表每次 worker 获取 server 都会进行完整的探活流程,不存在脑裂问题,但有性能开销 ####### -oms.accurate.select.server.percentage = 50 \ No newline at end of file +oms.instance.metadata.cache.size=1024 \ No newline at end of file From 4eb53990f404bf957c003f6ccc9f065e5c8f0c24 Mon Sep 17 00:00:00 2001 From: tanwenhai Date: Wed, 16 Dec 2020 17:05:29 +0800 Subject: [PATCH 13/19] daily config --- .../src/main/resources/application-daily.properties | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/powerjob-server/src/main/resources/application-daily.properties b/powerjob-server/src/main/resources/application-daily.properties index 9b1e2b7a..18bb67ef 100644 --- a/powerjob-server/src/main/resources/application-daily.properties +++ b/powerjob-server/src/main/resources/application-daily.properties @@ -32,4 +32,7 @@ oms.container.retention.local=1 oms.container.retention.remote=-1 ####### 缓存配置 ####### -oms.instance.metadata.cache.size=1024 \ No newline at end of file +oms.instance.metadata.cache.size=1024 + +####### 精确获取 server 的百分比,0~100,100代表每次 worker 获取 server 都会进行完整的探活流程,不存在脑裂问题,但有性能开销 ####### +oms.accurate.select.server.percentage = 50 \ No newline at end of file From 35f0991f031ee047c80e097e81c452e4d125222d Mon Sep 17 00:00:00 2001 From: tanwenhai Date: Wed, 16 Dec 2020 18:35:56 +0800 Subject: [PATCH 14/19] TypeDef --- .../server/persistence/core/model/InstanceInfoDO.java | 4 ++-- .../server/persistence/core/model/JobInfoDO.java | 2 +- .../server/persistence/core/model/TypeDefConstant.java | 9 +++++++++ .../server/persistence/core/model/WorkflowInfoDO.java | 2 +- .../persistence/core/model/WorkflowInstanceInfoDO.java | 6 +++--- .../server/persistence/core/model/package-info.java | 7 +++++++ 6 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/TypeDefConstant.java create mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/package-info.java diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/InstanceInfoDO.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/InstanceInfoDO.java index b0d7599d..a956830c 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/InstanceInfoDO.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/InstanceInfoDO.java @@ -37,7 +37,7 @@ public class InstanceInfoDO { // 任务实例参数 @Lob @Column - @Type(type ="org.hibernate.type.StringType") + @Type(type = TypeDefConstant.STRING_TYPE) private String instanceParams; // 该任务实例的类型,普通/工作流(InstanceType) @@ -51,7 +51,7 @@ public class InstanceInfoDO { // 执行结果(允许存储稍大的结果) @Lob @Column - @Type(type ="org.hibernate.type.StringType") + @Type(type = TypeDefConstant.STRING_TYPE) private String result; // 预计触发时间 private Long expectedTriggerTime; diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/JobInfoDO.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/JobInfoDO.java index 5bfe66b7..ddccbf7a 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/JobInfoDO.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/JobInfoDO.java @@ -53,7 +53,7 @@ public class JobInfoDO { // 执行器信息(可能需要存储整个脚本文件) @Lob @Column - @Type(type ="org.hibernate.type.StringType") + @Type(type = TypeDefConstant.STRING_TYPE) private String processorInfo; /* ************************** 运行时配置 ************************** */ diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/TypeDefConstant.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/TypeDefConstant.java new file mode 100644 index 00000000..fbe4b199 --- /dev/null +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/TypeDefConstant.java @@ -0,0 +1,9 @@ +package com.github.kfcfans.powerjob.server.persistence.core.model; + +/** + * @see package-info.java + * @author user + */ +public final class TypeDefConstant { + public static final String STRING_TYPE = "string-type"; +} diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInfoDO.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInfoDO.java index 3bcb6ac1..ee8c53a8 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInfoDO.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInfoDO.java @@ -36,7 +36,7 @@ public class WorkflowInfoDO { // 工作流的DAG图信息(点线式DAG的json) @Lob @Column - @Type(type ="org.hibernate.type.StringType") + @Type(type = TypeDefConstant.STRING_TYPE) private String peDAG; /* ************************** 定时参数 ************************** */ diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInstanceInfoDO.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInstanceInfoDO.java index 2dcb9a1c..d6290205 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInstanceInfoDO.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInstanceInfoDO.java @@ -40,16 +40,16 @@ public class WorkflowInstanceInfoDO { // 工作流启动参数 @Lob @Column - @Type(type ="org.hibernate.type.StringType") + @Type(type = TypeDefConstant.STRING_TYPE) private String wfInitParams; @Lob @Column - @Type(type ="org.hibernate.type.StringType") + @Type(type = TypeDefConstant.STRING_TYPE) private String dag; @Lob @Column - @Type(type ="org.hibernate.type.StringType") + @Type(type = TypeDefConstant.STRING_TYPE) private String result; // 预计触发时间 diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/package-info.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/package-info.java new file mode 100644 index 00000000..543fd8a0 --- /dev/null +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/package-info.java @@ -0,0 +1,7 @@ +@TypeDefs({ + @TypeDef(name = TypeDefConstant.STRING_TYPE, typeClass = org.hibernate.type.StringType.class) +}) +package com.github.kfcfans.powerjob.server.persistence.core.model; + +import org.hibernate.annotations.TypeDef; +import org.hibernate.annotations.TypeDefs; \ No newline at end of file From 76e5a41881c1f401c65fc5c0df68980d5d539a16 Mon Sep 17 00:00:00 2001 From: tanwenhai Date: Thu, 17 Dec 2020 11:12:54 +0800 Subject: [PATCH 15/19] serverIdProvider interface and implements --- .../service/id/DefaultServerIdProvider.java | 39 +++++++++++++++++ .../server/service/id/IdGenerateService.java | 43 +++---------------- .../server/service/id/ServerIdProvider.java | 12 ++++++ .../id/ServerIdProviderConfiguration.java | 25 +++++++++++ .../id/StatefulSetServerIdProvider.java | 30 +++++++++++++ 5 files changed, 111 insertions(+), 38 deletions(-) create mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/DefaultServerIdProvider.java create mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProvider.java create mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProviderConfiguration.java create mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/StatefulSetServerIdProvider.java diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/DefaultServerIdProvider.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/DefaultServerIdProvider.java new file mode 100644 index 00000000..1c018370 --- /dev/null +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/DefaultServerIdProvider.java @@ -0,0 +1,39 @@ +package com.github.kfcfans.powerjob.server.service.id; + +import com.github.kfcfans.powerjob.common.utils.NetUtils; +import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO; +import com.github.kfcfans.powerjob.server.persistence.core.repository.ServerInfoRepository; + +/** + * @author user + */ +public class DefaultServerIdProvider implements ServerIdProvider { + private final ServerInfoRepository serverInfoRepository; + + private volatile Long id; + + public DefaultServerIdProvider(ServerInfoRepository serverInfoRepository) { + this.serverInfoRepository = serverInfoRepository; + } + + @Override + public long serverId() { + if (id == null) { + synchronized (this) { + if (id == null) { + String ip = NetUtils.getLocalHost(); + ServerInfoDO server = serverInfoRepository.findByIp(ip); + + if (server == null) { + ServerInfoDO newServerInfo = new ServerInfoDO(ip); + server = serverInfoRepository.saveAndFlush(newServerInfo); + } + + id = server.getId(); + } + } + } + + return id; + } +} diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java index bf3f0ee7..c334d01b 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java @@ -3,23 +3,10 @@ package com.github.kfcfans.powerjob.server.service.id; import com.github.kfcfans.powerjob.common.utils.NetUtils; import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.repository.ServerInfoRepository; -import com.google.common.base.Throwables; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.jdbc.support.JdbcUtils; import org.springframework.stereotype.Service; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.transaction.support.TransactionTemplate; -import org.springframework.util.Assert; - -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; /** * 唯一ID生成服务,使用 Twitter snowflake 算法 @@ -38,32 +25,12 @@ public class IdGenerateService { private static final int DATA_CENTER_ID = 0; @Autowired - public IdGenerateService(ServerInfoRepository serverInfoRepository, - @Qualifier("coreTransactionManager") PlatformTransactionManager platformTransactionManager) { - TransactionTemplate transactionTemplate = new TransactionTemplate(platformTransactionManager); - // 服务频繁重启,数据库id自增值过大,使用表锁获取机器id - snowFlakeIdGenerator = transactionTemplate.execute(action -> { - List serverInfos = serverInfoRepository.findAllAndLockTable(); - String ip = NetUtils.getLocalHost(); - ServerInfoDO server = serverInfoRepository.findByIp(ip); - Long id = null; - if (server == null) { - ServerInfoDO newServerInfo = new ServerInfoDO(ip); - serverInfoRepository.saveAndFlush(newServerInfo); - id = serverInfos.size() + 1L; - } else { - for (int i = 0, len = serverInfos.size(); i < len; i++) { - if (Objects.equals(serverInfos.get(i).getId(), server.getId())) { - id = i + 1L; - break; - } - } - } - Assert.notNull(id, "[IdGenerateService] init snowflake error, id is null"); - log.info("[IdGenerateService] init snowflake for server(address={}) by machineId({}).", ip, id); + public IdGenerateService(@Qualifier("serverIdProvider") ServerIdProvider serverIdProvider) { + long id = serverIdProvider.serverId(); + snowFlakeIdGenerator = new SnowFlakeIdGenerator(DATA_CENTER_ID, id); + String ip = NetUtils.getLocalHost(); - return new SnowFlakeIdGenerator(DATA_CENTER_ID, id); - }); + log.info("[IdGenerateService] init snowflake for server(address={}) by machineId({}).", ip, id); } /** diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProvider.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProvider.java new file mode 100644 index 00000000..f7fcbd2e --- /dev/null +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProvider.java @@ -0,0 +1,12 @@ +package com.github.kfcfans.powerjob.server.service.id; + +/** + * @author user + */ +public interface ServerIdProvider { + /** + * get number for IdGenerateService + * @return serverId + */ + long serverId(); +} diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProviderConfiguration.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProviderConfiguration.java new file mode 100644 index 00000000..e2e6f5c4 --- /dev/null +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProviderConfiguration.java @@ -0,0 +1,25 @@ +package com.github.kfcfans.powerjob.server.service.id; + +import com.github.kfcfans.powerjob.server.persistence.core.repository.ServerInfoRepository; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author user + */ +@Configuration +public class ServerIdProviderConfiguration { + @ConditionalOnProperty(prefix = "oms.server-id", name = "provider", havingValue = "hostname") + @Bean(name = "serverIdProvider") + public ServerIdProvider statefulSetServerIdProvider() { + return new StatefulSetServerIdProvider(); + } + + @ConditionalOnMissingBean(ServerIdProvider.class) + @Bean(name = "serverIdProvider") + public ServerIdProvider defaultServerIdProvider(ServerInfoRepository serverInfoRepository) { + return new DefaultServerIdProvider(serverInfoRepository); + } +} diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/StatefulSetServerIdProvider.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/StatefulSetServerIdProvider.java new file mode 100644 index 00000000..9e796e36 --- /dev/null +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/StatefulSetServerIdProvider.java @@ -0,0 +1,30 @@ +package com.github.kfcfans.powerjob.server.service.id; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author user + */ +public class StatefulSetServerIdProvider implements ServerIdProvider { + /** + * xxx-1,aa-bb-2 + */ + private static final Pattern HOSTNAME_PATTERN = Pattern.compile("^.*-([0-9]+)$"); + + @Override + public long serverId() { + try { + String hostname = InetAddress.getLocalHost().getHostName(); + Matcher matcher = HOSTNAME_PATTERN.matcher(hostname); + if (matcher.matches()) { + return Long.parseLong(matcher.group(1)); + } + throw new RuntimeException(String.format("hostname=%s not match %s", hostname, HOSTNAME_PATTERN.toString())); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + } +} From 977b8bfd4b21d65f4bd6c18fecae63948f2d4bcf Mon Sep 17 00:00:00 2001 From: tjq Date: Sat, 19 Dec 2020 21:49:41 +0800 Subject: [PATCH 16/19] fix: fetch instance log failed when server use different http port --- .../powerjob/common/InstanceStatus.java | 4 +-- .../server/service/DispatchService.java | 1 + .../server/service/InstanceLogService.java | 25 +++++++++++++-- .../web/controller/InstanceController.java | 32 +++---------------- .../src/main/resources/static/js/9.js | 2 +- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/powerjob-common/src/main/java/com/github/kfcfans/powerjob/common/InstanceStatus.java b/powerjob-common/src/main/java/com/github/kfcfans/powerjob/common/InstanceStatus.java index 536ef621..996ce997 100644 --- a/powerjob-common/src/main/java/com/github/kfcfans/powerjob/common/InstanceStatus.java +++ b/powerjob-common/src/main/java/com/github/kfcfans/powerjob/common/InstanceStatus.java @@ -24,8 +24,8 @@ public enum InstanceStatus { CANCELED(9, "取消"), STOPPED(10, "手动停止"); - private int v; - private String des; + private final int v; + private final String des; // 广义的运行状态 public static final List generalizedRunningStatus = Lists.newArrayList(WAITING_DISPATCH.v, WAITING_WORKER_RECEIVE.v, RUNNING.v); diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/DispatchService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/DispatchService.java index 8f98c7a0..3e5c41f4 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/DispatchService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/DispatchService.java @@ -81,6 +81,7 @@ public class DispatchService { if (maxInstanceNum > 0) { // 这个 runningInstanceCount 已经包含了本 instance + // 不统计 WAITING_DISPATCH 的状态:使用 OpenAPI 触发的延迟任务显然不应该统计进去(比如 delay 是 1 天) long runningInstanceCount = instanceInfoRepository.countByJobIdAndStatusIn(jobId, Lists.newArrayList(WAITING_WORKER_RECEIVE.getV(), RUNNING.getV())); // 超出最大同时运行限制,不执行调度 if (runningInstanceCount > maxInstanceNum) { diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/InstanceLogService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/InstanceLogService.java index 90a9fd8c..b197d31e 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/InstanceLogService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/InstanceLogService.java @@ -4,7 +4,9 @@ import com.github.kfcfans.powerjob.common.OmsConstant; import com.github.kfcfans.powerjob.common.TimeExpressionType; import com.github.kfcfans.powerjob.common.model.InstanceLogContent; import com.github.kfcfans.powerjob.common.utils.CommonUtils; +import com.github.kfcfans.powerjob.common.utils.NetUtils; import com.github.kfcfans.powerjob.common.utils.SegmentLock; +import com.github.kfcfans.powerjob.server.common.redirect.DesignateServer; import com.github.kfcfans.powerjob.server.common.utils.OmsFileUtils; import com.github.kfcfans.powerjob.server.persistence.StringPage; import com.github.kfcfans.powerjob.server.persistence.core.model.JobInfoDO; @@ -21,6 +23,7 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.time.FastDateFormat; import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -45,6 +48,9 @@ import java.util.stream.Stream; @Service public class InstanceLogService { + @Value("${server.port}") + private int port; + @Resource private InstanceMetadataService instanceMetadataService; @Resource @@ -99,11 +105,13 @@ public class InstanceLogService { /** * 获取任务实例运行日志(默认存在本地数据,需要由生成完成请求的路由与转发) + * @param appId appId,AOP 专用 * @param instanceId 任务实例ID * @param index 页码,从0开始 * @return 文本字符串 */ - public StringPage fetchInstanceLog(Long instanceId, long index) { + @DesignateServer(appIdParameterName = "appId") + public StringPage fetchInstanceLog(Long appId, Long instanceId, Long index) { try { Future fileFuture = prepareLogFile(instanceId); // 超时并不会打断正在执行的任务 @@ -125,7 +133,7 @@ public class InstanceLogService { ++lines; } }catch (Exception e) { - log.warn("[InstanceLog-{}] read logFile from disk failed.", instanceId, e); + log.warn("[InstanceLog-{}] read logFile from disk failed for app: {}.", instanceId, appId, e); return StringPage.simple("oms-server execution exception, caused by " + ExceptionUtils.getRootCauseMessage(e)); } @@ -140,6 +148,19 @@ public class InstanceLogService { } } + /** + * 获取日志的下载链接 + * @param appId AOP 专用 + * @param instanceId 任务实例 ID + * @return 下载链接 + */ + @DesignateServer(appIdParameterName = "appId") + public String fetchDownloadUrl(Long appId, Long instanceId) { + String url = "http://" + NetUtils.getLocalHost() + ":" + port + "/instance/downloadLog?instanceId=" + instanceId; + log.info("[InstanceLog-{}] downloadURL for appId[{}]: {}", instanceId, appId, url); + return url; + } + /** * 下载全部的任务日志文件 * @param instanceId 任务实例ID diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/InstanceController.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/InstanceController.java index d3495717..ae36a78a 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/InstanceController.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/web/controller/InstanceController.java @@ -3,7 +3,6 @@ package com.github.kfcfans.powerjob.server.web.controller; import com.github.kfcfans.powerjob.common.InstanceStatus; import com.github.kfcfans.powerjob.common.PowerJobException; import com.github.kfcfans.powerjob.common.response.ResultDTO; -import com.github.kfcfans.powerjob.server.akka.OhMyServer; import com.github.kfcfans.powerjob.server.common.utils.OmsFileUtils; import com.github.kfcfans.powerjob.server.persistence.PageResult; import com.github.kfcfans.powerjob.server.persistence.StringPage; @@ -19,7 +18,6 @@ import com.github.kfcfans.powerjob.server.web.response.InstanceDetailVO; import com.github.kfcfans.powerjob.server.web.response.InstanceInfoVO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Example; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -46,8 +44,7 @@ import java.util.stream.Collectors; @RequestMapping("/instance") public class InstanceController { - @Value("${server.port}") - private int port; + @Resource private InstanceService instanceService; @@ -79,32 +76,13 @@ public class InstanceController { } @GetMapping("/log") - public ResultDTO getInstanceLog(Long instanceId, Long index, HttpServletResponse response) { - - String targetServer = getTargetServer(instanceId); - - // 转发HTTP请求(如果使用Akka,则需要传输两次,而转发HTTP请求只需要传输一次"大"数据包) - if (!OhMyServer.getActorSystemAddress().equals(targetServer)) { - String ip = targetServer.split(":")[0]; - String url = String.format("http://%s:%s/instance/log?instanceId=%d&index=%d", ip, port, instanceId, index); - try { - response.sendRedirect(url); - return ResultDTO.success(StringPage.simple("redirecting...")); - }catch (Exception e) { - log.warn("[Instance-{}] redirect request to url[{}] failed, please ensure all server has the same http port!", instanceId, url, e); - return ResultDTO.failed(e); - } - } - - return ResultDTO.success(instanceLogService.fetchInstanceLog(instanceId, index)); + public ResultDTO getInstanceLog(Long appId, Long instanceId, Long index) { + return ResultDTO.success(instanceLogService.fetchInstanceLog(appId, instanceId, index)); } @GetMapping("/downloadLogUrl") - public ResultDTO getDownloadUrl(Long instanceId) { - String targetServer = getTargetServer(instanceId); - String ip = targetServer.split(":")[0]; - String url = "http://" + ip + ":" + port + "/instance/downloadLog?instanceId=" + instanceId; - return ResultDTO.success(url); + public ResultDTO getDownloadUrl(Long appId, Long instanceId) { + return ResultDTO.success(instanceLogService.fetchDownloadUrl(appId, instanceId)); } @GetMapping("/downloadLog") diff --git a/powerjob-server/src/main/resources/static/js/9.js b/powerjob-server/src/main/resources/static/js/9.js index 34cb3277..9955e5b3 100644 --- a/powerjob-server/src/main/resources/static/js/9.js +++ b/powerjob-server/src/main/resources/static/js/9.js @@ -8,7 +8,7 @@ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _common_InstanceDetail__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common/InstanceDetail */ \"./src/components/common/InstanceDetail.vue\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n name: \"InstanceManager\",\n components: {\n InstanceDetail: _common_InstanceDetail__WEBPACK_IMPORTED_MODULE_0__[\"default\"]\n },\n data: function data() {\n return {\n // 实例查询对象\n instanceQueryContent: {\n appId: this.$store.state.appInfo.id,\n index: 0,\n pageSize: 10,\n instanceId: undefined,\n wfInstanceId: undefined,\n status: \"\",\n jobId: undefined,\n type: \"NORMAL\"\n },\n // 实例查询结果\n instancePageResult: {\n pageSize: 10,\n totalItems: 0,\n data: []\n },\n // 详细信息弹出框是否可见\n instanceDetailVisible: false,\n // 日志查询对象\n logQueryContent: {\n instanceId: undefined,\n index: 0\n },\n // 日志对象\n paginableInstanceLog: {\n index: 0,\n totalPages: 0,\n data: \"\"\n },\n // 日志弹出框是否可见\n instanceLogVisible: false,\n currentInstanceId: undefined,\n // 任务实例状态选择\n instanceStatusOptions: [{\n key: \"\",\n label: this.$t('message.all')\n }, {\n key: \"WAITING_DISPATCH\",\n label: this.$t('message.waitingDispatch')\n }, {\n key: \"WAITING_WORKER_RECEIVE\",\n label: this.$t('message.waitingWorkerReceive')\n }, {\n key: \"RUNNING\",\n label: this.$t('message.running')\n }, {\n key: \"FAILED\",\n label: this.$t('message.failed')\n }, {\n key: \"SUCCEED\",\n label: this.$t('message.success')\n }, {\n key: \"CANCELED\",\n label: this.$t('message.canceled')\n }, {\n key: \"STOPPED\",\n label: this.$t('message.stopped')\n }]\n };\n },\n methods: {\n // 查询任务实例信息\n listInstanceInfos: function listInstanceInfos() {\n var that = this;\n that.axios.post(\"/instance/list\", that.instanceQueryContent).then(function (res) {\n that.instancePageResult = res;\n });\n },\n // 点击重置按钮\n onClickRest: function onClickRest() {\n this.instanceQueryContent.jobId = undefined;\n this.instanceQueryContent.instanceId = undefined;\n this.instanceQueryContent.wfInstanceId = undefined;\n this.instanceQueryContent.status = \"\";\n this.listInstanceInfos();\n },\n // 点击查询详情\n onClickShowDetail: function onClickShowDetail(data) {\n this.instanceDetailVisible = true;\n this.currentInstanceId = data.instanceId;\n },\n // 点击重跑\n onClickRetryJob: function onClickRetryJob(data) {\n var _this = this;\n\n var that = this;\n var url = \"/instance/retry?instanceId=\" + data.instanceId + \"&appId=\" + that.$store.state.appInfo.id;\n this.axios.get(url).then(function () {\n that.$message.success(_this.$t('message.success'));\n that.listInstanceInfos();\n });\n },\n // 点击停止实例\n onClickStop: function onClickStop(data) {\n var _this2 = this;\n\n var that = this;\n var url = \"/instance/stop?instanceId=\" + data.instanceId;\n this.axios.get(url).then(function () {\n that.$message.success(_this2.$t('message.success')); // 重新加载列表\n\n that.listInstanceInfos();\n });\n },\n // 换页\n onClickChangeInstancePage: function onClickChangeInstancePage(index) {\n // 后端从0开始,前端从1开始\n this.instanceQueryContent.index = index - 1;\n this.listInstanceInfos();\n },\n instanceTableRowClassName: function instanceTableRowClassName(_ref) {\n var row = _ref.row;\n\n switch (row.status) {\n // 失败\n case 4:\n return 'error-row';\n // 成功\n\n case 5:\n return 'success-row';\n\n case 9:\n case 10:\n return 'warning-row';\n }\n },\n // 查看日志\n queryLog: function queryLog() {\n var that = this;\n var url = \"/instance/log?instanceId=\" + this.logQueryContent.instanceId + \"&index=\" + this.logQueryContent.index;\n this.axios.get(url).then(function (res) {\n that.paginableInstanceLog = res;\n that.instanceLogVisible = true;\n });\n },\n // 查看在线日志\n onClickShowLog: function onClickShowLog(data) {\n this.logQueryContent.instanceId = data.instanceId;\n this.logQueryContent.index = 0;\n this.queryLog();\n },\n // 查看其它页的在线日志\n onClickChangeLogPage: function onClickChangeLogPage(index) {\n this.logQueryContent.index = index - 1;\n this.queryLog();\n },\n // 下载日志\n onclickDownloadLog: function onclickDownloadLog() {\n var url = \"/instance/downloadLogUrl?instanceId=\" + this.logQueryContent.instanceId;\n this.axios.get(url).then(function (res) {\n return window.open(res);\n });\n },\n // 获取状态\n fetchStatus: function fetchStatus(s) {\n return this.common.translateInstanceStatus(s);\n }\n },\n mounted: function mounted() {\n // 读取传递的参数\n var jobId = this.$route.params.jobId;\n\n if (jobId !== undefined) {\n this.instanceQueryContent.jobId = jobId;\n }\n\n this.listInstanceInfos();\n }\n});\n\n//# sourceURL=webpack:///./src/components/views/InstanceManager.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _common_InstanceDetail__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common/InstanceDetail */ \"./src/components/common/InstanceDetail.vue\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n name: \"InstanceManager\",\n components: {\n InstanceDetail: _common_InstanceDetail__WEBPACK_IMPORTED_MODULE_0__[\"default\"]\n },\n data: function data() {\n return {\n // 实例查询对象\n instanceQueryContent: {\n appId: this.$store.state.appInfo.id,\n index: 0,\n pageSize: 10,\n instanceId: undefined,\n wfInstanceId: undefined,\n status: \"\",\n jobId: undefined,\n type: \"NORMAL\"\n },\n // 实例查询结果\n instancePageResult: {\n pageSize: 10,\n totalItems: 0,\n data: []\n },\n // 详细信息弹出框是否可见\n instanceDetailVisible: false,\n // 日志查询对象\n logQueryContent: {\n instanceId: undefined,\n index: 0\n },\n // 日志对象\n paginableInstanceLog: {\n index: 0,\n totalPages: 0,\n data: \"\"\n },\n // 日志弹出框是否可见\n instanceLogVisible: false,\n currentInstanceId: undefined,\n // 任务实例状态选择\n instanceStatusOptions: [{\n key: \"\",\n label: this.$t('message.all')\n }, {\n key: \"WAITING_DISPATCH\",\n label: this.$t('message.waitingDispatch')\n }, {\n key: \"WAITING_WORKER_RECEIVE\",\n label: this.$t('message.waitingWorkerReceive')\n }, {\n key: \"RUNNING\",\n label: this.$t('message.running')\n }, {\n key: \"FAILED\",\n label: this.$t('message.failed')\n }, {\n key: \"SUCCEED\",\n label: this.$t('message.success')\n }, {\n key: \"CANCELED\",\n label: this.$t('message.canceled')\n }, {\n key: \"STOPPED\",\n label: this.$t('message.stopped')\n }]\n };\n },\n methods: {\n // 查询任务实例信息\n listInstanceInfos: function listInstanceInfos() {\n var that = this;\n that.axios.post(\"/instance/list\", that.instanceQueryContent).then(function (res) {\n that.instancePageResult = res;\n });\n },\n // 点击重置按钮\n onClickRest: function onClickRest() {\n this.instanceQueryContent.jobId = undefined;\n this.instanceQueryContent.instanceId = undefined;\n this.instanceQueryContent.wfInstanceId = undefined;\n this.instanceQueryContent.status = \"\";\n this.listInstanceInfos();\n },\n // 点击查询详情\n onClickShowDetail: function onClickShowDetail(data) {\n this.instanceDetailVisible = true;\n this.currentInstanceId = data.instanceId;\n },\n // 点击重跑\n onClickRetryJob: function onClickRetryJob(data) {\n var _this = this;\n\n var that = this;\n var url = \"/instance/retry?instanceId=\" + data.instanceId + \"&appId=\" + that.$store.state.appInfo.id;\n this.axios.get(url).then(function () {\n that.$message.success(_this.$t('message.success'));\n that.listInstanceInfos();\n });\n },\n // 点击停止实例\n onClickStop: function onClickStop(data) {\n var _this2 = this;\n\n var that = this;\n var url = \"/instance/stop?instanceId=\" + data.instanceId;\n this.axios.get(url).then(function () {\n that.$message.success(_this2.$t('message.success')); // 重新加载列表\n\n that.listInstanceInfos();\n });\n },\n // 换页\n onClickChangeInstancePage: function onClickChangeInstancePage(index) {\n // 后端从0开始,前端从1开始\n this.instanceQueryContent.index = index - 1;\n this.listInstanceInfos();\n },\n instanceTableRowClassName: function instanceTableRowClassName(_ref) {\n var row = _ref.row;\n\n switch (row.status) {\n // 失败\n case 4:\n return 'error-row';\n // 成功\n\n case 5:\n return 'success-row';\n\n case 9:\n case 10:\n return 'warning-row';\n }\n },\n // 查看日志\n queryLog: function queryLog() {\n var that = this;\n var url = \"/instance/log?instanceId=\" + this.logQueryContent.instanceId + \"&index=\" + this.logQueryContent.index + \"&appId=\" + that.$store.state.appInfo.id;\n this.axios.get(url).then(function (res) {\n that.paginableInstanceLog = res;\n that.instanceLogVisible = true;\n });\n },\n // 查看在线日志\n onClickShowLog: function onClickShowLog(data) {\n this.logQueryContent.instanceId = data.instanceId;\n this.logQueryContent.index = 0;\n this.queryLog();\n },\n // 查看其它页的在线日志\n onClickChangeLogPage: function onClickChangeLogPage(index) {\n this.logQueryContent.index = index - 1;\n this.queryLog();\n },\n // 下载日志\n onclickDownloadLog: function onclickDownloadLog() {\n var url = \"/instance/downloadLogUrl?instanceId=\" + this.logQueryContent.instanceId + \"&appId=\" + this.$store.state.appInfo.id;\n this.axios.get(url).then(function (res) {\n return window.open(res);\n });\n },\n // 获取状态\n fetchStatus: function fetchStatus(s) {\n return this.common.translateInstanceStatus(s);\n }\n },\n mounted: function mounted() {\n // 读取传递的参数\n var jobId = this.$route.params.jobId;\n\n if (jobId !== undefined) {\n this.instanceQueryContent.jobId = jobId;\n }\n\n this.listInstanceInfos();\n }\n});\n\n//# sourceURL=webpack:///./src/components/views/InstanceManager.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), From c40774d5780c551f3481b14449270d83ef5fc2e1 Mon Sep 17 00:00:00 2001 From: tjq Date: Sun, 20 Dec 2020 00:04:07 +0800 Subject: [PATCH 17/19] refactor: add extension module --- .../alarm => extension}/Alarmable.java | 4 +- .../server/extension/ServerIdProvider.java | 14 ++++++ .../core/repository/ServerInfoRepository.java | 9 ---- .../server/service/alarm/AlarmCenter.java | 1 + .../alarm/impl/DingTalkAlarmService.java | 2 +- .../service/alarm/impl/MailAlarmService.java | 2 +- .../alarm/impl/WebHookAlarmService.java | 2 +- .../service/id/DefaultServerIdProvider.java | 38 ++++++++-------- .../server/service/id/IdGenerateService.java | 45 ++++++++++++++----- .../server/service/id/ServerIdProvider.java | 12 ----- .../id/ServerIdProviderConfiguration.java | 25 ----------- .../service/id/SnowFlakeIdGenerator.java | 4 +- .../id/StatefulSetServerIdProvider.java | 30 ------------- 13 files changed, 75 insertions(+), 113 deletions(-) rename powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/{service/alarm => extension}/Alarmable.java (71%) create mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/extension/ServerIdProvider.java delete mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProvider.java delete mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProviderConfiguration.java delete mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/StatefulSetServerIdProvider.java diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/Alarmable.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/extension/Alarmable.java similarity index 71% rename from powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/Alarmable.java rename to powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/extension/Alarmable.java index 715bfd7f..abab5b00 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/Alarmable.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/extension/Alarmable.java @@ -1,6 +1,8 @@ -package com.github.kfcfans.powerjob.server.service.alarm; +package com.github.kfcfans.powerjob.server.extension; import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO; +import com.github.kfcfans.powerjob.server.service.alarm.Alarm; +import com.github.kfcfans.powerjob.server.service.alarm.AlarmCenter; import org.springframework.beans.factory.InitializingBean; import java.util.List; diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/extension/ServerIdProvider.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/extension/ServerIdProvider.java new file mode 100644 index 00000000..62751040 --- /dev/null +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/extension/ServerIdProvider.java @@ -0,0 +1,14 @@ +package com.github.kfcfans.powerjob.server.extension; + +/** + * provide unique server ip in the cluster for IdGenerateService + * @author user + */ +public interface ServerIdProvider { + + /** + * get number for IdGenerateService + * @return serverId, must in range [0, 16384) + */ + long getServerId(); +} diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/repository/ServerInfoRepository.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/repository/ServerInfoRepository.java index 7f0b70ba..615933f2 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/repository/ServerInfoRepository.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/repository/ServerInfoRepository.java @@ -2,11 +2,6 @@ package com.github.kfcfans.powerjob.server.persistence.core.repository; import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Lock; -import org.springframework.data.jpa.repository.Query; - -import javax.persistence.LockModeType; -import java.util.List; /** * 服务器信息 数据操作层 @@ -16,8 +11,4 @@ import java.util.List; */ public interface ServerInfoRepository extends JpaRepository { ServerInfoDO findByIp(String ip); - - @Query("select t from ServerInfoDO as t order by t.id asc") - @Lock(LockModeType.PESSIMISTIC_WRITE) - List findAllAndLockTable(); } diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/AlarmCenter.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/AlarmCenter.java index 06bd79b3..356931c6 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/AlarmCenter.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/AlarmCenter.java @@ -1,5 +1,6 @@ package com.github.kfcfans.powerjob.server.service.alarm; +import com.github.kfcfans.powerjob.server.extension.Alarmable; import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO; import com.google.common.collect.Lists; import com.google.common.collect.Queues; diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/impl/DingTalkAlarmService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/impl/DingTalkAlarmService.java index f1e4ee48..2bcde0ed 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/impl/DingTalkAlarmService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/impl/DingTalkAlarmService.java @@ -8,7 +8,7 @@ import com.github.kfcfans.powerjob.server.common.SJ; import com.github.kfcfans.powerjob.server.common.utils.DingTalkUtils; import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO; import com.github.kfcfans.powerjob.server.service.alarm.Alarm; -import com.github.kfcfans.powerjob.server.service.alarm.Alarmable; +import com.github.kfcfans.powerjob.server.extension.Alarmable; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.Lists; diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/impl/MailAlarmService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/impl/MailAlarmService.java index 516d1814..60010e1d 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/impl/MailAlarmService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/impl/MailAlarmService.java @@ -2,7 +2,7 @@ package com.github.kfcfans.powerjob.server.service.alarm.impl; import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO; import com.github.kfcfans.powerjob.server.service.alarm.Alarm; -import com.github.kfcfans.powerjob.server.service.alarm.Alarmable; +import com.github.kfcfans.powerjob.server.extension.Alarmable; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/impl/WebHookAlarmService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/impl/WebHookAlarmService.java index dc6662c7..9de33c67 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/impl/WebHookAlarmService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/alarm/impl/WebHookAlarmService.java @@ -5,7 +5,7 @@ import com.github.kfcfans.powerjob.common.OmsConstant; import com.github.kfcfans.powerjob.common.utils.HttpUtils; import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO; import com.github.kfcfans.powerjob.server.service.alarm.Alarm; -import com.github.kfcfans.powerjob.server.service.alarm.Alarmable; +import com.github.kfcfans.powerjob.server.extension.Alarmable; import lombok.extern.slf4j.Slf4j; import okhttp3.MediaType; import okhttp3.RequestBody; diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/DefaultServerIdProvider.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/DefaultServerIdProvider.java index 1c018370..41ba4ac9 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/DefaultServerIdProvider.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/DefaultServerIdProvider.java @@ -1,39 +1,37 @@ package com.github.kfcfans.powerjob.server.service.id; import com.github.kfcfans.powerjob.common.utils.NetUtils; +import com.github.kfcfans.powerjob.server.extension.ServerIdProvider; import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.repository.ServerInfoRepository; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; /** + * 默认服务器 ID 生成策略,不适用于 Server 频繁重启且变化 IP 的场景 * @author user */ +@Slf4j +@Service public class DefaultServerIdProvider implements ServerIdProvider { - private final ServerInfoRepository serverInfoRepository; - private volatile Long id; + private final Long id; - public DefaultServerIdProvider(ServerInfoRepository serverInfoRepository) { - this.serverInfoRepository = serverInfoRepository; - } + public DefaultServerIdProvider(ServerInfoRepository serverInfoRepository) { + String ip = NetUtils.getLocalHost(); + ServerInfoDO server = serverInfoRepository.findByIp(ip); - @Override - public long serverId() { - if (id == null) { - synchronized (this) { - if (id == null) { - String ip = NetUtils.getLocalHost(); - ServerInfoDO server = serverInfoRepository.findByIp(ip); - - if (server == null) { + if (server == null) { ServerInfoDO newServerInfo = new ServerInfoDO(ip); server = serverInfoRepository.saveAndFlush(newServerInfo); - } - - id = server.getId(); } - } + this.id = server.getId(); + + log.info("[DefaultServerIdProvider] address:{},id:{}", ip, id); } - return id; - } + @Override + public long getServerId() { + return id; + } } diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java index c334d01b..73565360 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/IdGenerateService.java @@ -1,17 +1,19 @@ package com.github.kfcfans.powerjob.server.service.id; -import com.github.kfcfans.powerjob.common.utils.NetUtils; -import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO; -import com.github.kfcfans.powerjob.server.persistence.core.repository.ServerInfoRepository; +import com.github.kfcfans.powerjob.common.PowerJobException; +import com.github.kfcfans.powerjob.server.extension.ServerIdProvider; +import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.List; /** * 唯一ID生成服务,使用 Twitter snowflake 算法 * 机房ID:固定为0,占用2位 - * 机器ID:数据库自增,占用14位(如果频繁部署需要删除数据库重置id) + * 机器ID:由 ServerIdProvider 提供 * * @author tjq * @since 2020/4/6 @@ -21,16 +23,37 @@ import org.springframework.stereotype.Service; public class IdGenerateService { private final SnowFlakeIdGenerator snowFlakeIdGenerator; - private static final int DATA_CENTER_ID = 0; @Autowired - public IdGenerateService(@Qualifier("serverIdProvider") ServerIdProvider serverIdProvider) { - long id = serverIdProvider.serverId(); - snowFlakeIdGenerator = new SnowFlakeIdGenerator(DATA_CENTER_ID, id); - String ip = NetUtils.getLocalHost(); + public IdGenerateService(List serverIdProviders) { - log.info("[IdGenerateService] init snowflake for server(address={}) by machineId({}).", ip, id); + if (CollectionUtils.isEmpty(serverIdProviders)) { + throw new PowerJobException("can't find any ServerIdProvider!"); + } + + ServerIdProvider serverIdProvider; + int severIpProviderNums = serverIdProviders.size(); + if (severIpProviderNums == 1) { + serverIdProvider = serverIdProviders.get(0); + } else { + List extendServerIpProviders = Lists.newArrayList(); + for (ServerIdProvider sp : serverIdProviders) { + if (sp instanceof DefaultServerIdProvider) { + continue; + } + extendServerIpProviders.add(sp); + } + int extNum = extendServerIpProviders.size(); + if (extNum != 1) { + throw new PowerJobException(String.format("find %d ServerIdProvider but just need one, please delete the useless ServerIdProvider!", extNum)); + } + serverIdProvider = extendServerIpProviders.get(0); + } + + long id = serverIdProvider.getServerId(); + snowFlakeIdGenerator = new SnowFlakeIdGenerator(DATA_CENTER_ID, id); + log.info("[IdGenerateService] initialize IdGenerateService successfully, ServerIdProvider:{},ID:{}", serverIdProvider.getClass().getSimpleName(), id); } /** diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProvider.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProvider.java deleted file mode 100644 index f7fcbd2e..00000000 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProvider.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.github.kfcfans.powerjob.server.service.id; - -/** - * @author user - */ -public interface ServerIdProvider { - /** - * get number for IdGenerateService - * @return serverId - */ - long serverId(); -} diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProviderConfiguration.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProviderConfiguration.java deleted file mode 100644 index e2e6f5c4..00000000 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/ServerIdProviderConfiguration.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.github.kfcfans.powerjob.server.service.id; - -import com.github.kfcfans.powerjob.server.persistence.core.repository.ServerInfoRepository; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @author user - */ -@Configuration -public class ServerIdProviderConfiguration { - @ConditionalOnProperty(prefix = "oms.server-id", name = "provider", havingValue = "hostname") - @Bean(name = "serverIdProvider") - public ServerIdProvider statefulSetServerIdProvider() { - return new StatefulSetServerIdProvider(); - } - - @ConditionalOnMissingBean(ServerIdProvider.class) - @Bean(name = "serverIdProvider") - public ServerIdProvider defaultServerIdProvider(ServerInfoRepository serverInfoRepository) { - return new DefaultServerIdProvider(serverInfoRepository); - } -} diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/SnowFlakeIdGenerator.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/SnowFlakeIdGenerator.java index 637fef6d..2eb5888d 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/SnowFlakeIdGenerator.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/SnowFlakeIdGenerator.java @@ -34,8 +34,8 @@ class SnowFlakeIdGenerator { private final static long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; private final static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT; - private long dataCenterId; //数据中心 - private long machineId; //机器标识 + private final long dataCenterId; //数据中心 + private final long machineId; //机器标识 private long sequence = 0L; //序列号 private long lastTimestamp = -1L;//上一次时间戳 diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/StatefulSetServerIdProvider.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/StatefulSetServerIdProvider.java deleted file mode 100644 index 9e796e36..00000000 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/id/StatefulSetServerIdProvider.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.github.kfcfans.powerjob.server.service.id; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * @author user - */ -public class StatefulSetServerIdProvider implements ServerIdProvider { - /** - * xxx-1,aa-bb-2 - */ - private static final Pattern HOSTNAME_PATTERN = Pattern.compile("^.*-([0-9]+)$"); - - @Override - public long serverId() { - try { - String hostname = InetAddress.getLocalHost().getHostName(); - Matcher matcher = HOSTNAME_PATTERN.matcher(hostname); - if (matcher.matches()) { - return Long.parseLong(matcher.group(1)); - } - throw new RuntimeException(String.format("hostname=%s not match %s", hostname, HOSTNAME_PATTERN.toString())); - } catch (UnknownHostException e) { - throw new RuntimeException(e); - } - } -} From 12162f29554655298c3f91e280fcee721c5c0598 Mon Sep 17 00:00:00 2001 From: tjq Date: Sun, 20 Dec 2020 20:40:36 +0800 Subject: [PATCH 18/19] feat: log full stack info when can't fetch processor #134 --- .../powerjob/worker/common/utils/SpringUtils.java | 8 +++++--- .../powerjob/worker/core/ProcessorBeanFactory.java | 4 +++- .../worker/core/tracker/processor/ProcessorTracker.java | 9 +++++---- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/powerjob-worker/src/main/java/com/github/kfcfans/powerjob/worker/common/utils/SpringUtils.java b/powerjob-worker/src/main/java/com/github/kfcfans/powerjob/worker/common/utils/SpringUtils.java index b8cafad3..c495dbda 100644 --- a/powerjob-worker/src/main/java/com/github/kfcfans/powerjob/worker/common/utils/SpringUtils.java +++ b/powerjob-worker/src/main/java/com/github/kfcfans/powerjob/worker/common/utils/SpringUtils.java @@ -1,15 +1,15 @@ package com.github.kfcfans.powerjob.worker.common.utils; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationContext; -import java.util.Objects; - /** * Spring ApplicationContext 工具类 * * @author tjq * @since 2020/3/16 */ +@Slf4j public class SpringUtils { private static boolean supportSpringBean = false; @@ -43,7 +43,9 @@ public class SpringUtils { // 小写转大写 char[] cs = beanName.toCharArray(); cs[0] += 32; - return (T) context.getBean(String.valueOf(cs)); + String beanName0 = String.valueOf(cs); + log.warn("[SpringUtils] can't get ClassLoader from context[{}], try to load by beanName:{}", context, beanName0); + return (T) context.getBean(beanName0); } } diff --git a/powerjob-worker/src/main/java/com/github/kfcfans/powerjob/worker/core/ProcessorBeanFactory.java b/powerjob-worker/src/main/java/com/github/kfcfans/powerjob/worker/core/ProcessorBeanFactory.java index 2b890d90..27dfbf32 100644 --- a/powerjob-worker/src/main/java/com/github/kfcfans/powerjob/worker/core/ProcessorBeanFactory.java +++ b/powerjob-worker/src/main/java/com/github/kfcfans/powerjob/worker/core/ProcessorBeanFactory.java @@ -3,6 +3,7 @@ package com.github.kfcfans.powerjob.worker.core; import com.github.kfcfans.powerjob.worker.core.processor.sdk.BasicProcessor; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; import java.util.Map; @@ -37,7 +38,8 @@ public class ProcessorBeanFactory { return (BasicProcessor) clz.getDeclaredConstructor().newInstance(); }catch (Exception e) { - log.warn("[ProcessorBeanFactory] load local Processor(className = {}) failed, reason is {}", className, e.getMessage()); + log.warn("[ProcessorBeanFactory] load local Processor(className = {}) failed.", className, e); + ExceptionUtils.rethrow(e); } return null; }); diff --git a/powerjob-worker/src/main/java/com/github/kfcfans/powerjob/worker/core/tracker/processor/ProcessorTracker.java b/powerjob-worker/src/main/java/com/github/kfcfans/powerjob/worker/core/tracker/processor/ProcessorTracker.java index 4c7e42e2..e12f48cc 100644 --- a/powerjob-worker/src/main/java/com/github/kfcfans/powerjob/worker/core/tracker/processor/ProcessorTracker.java +++ b/powerjob-worker/src/main/java/com/github/kfcfans/powerjob/worker/core/tracker/processor/ProcessorTracker.java @@ -24,6 +24,7 @@ import com.github.kfcfans.powerjob.worker.core.processor.sdk.BasicProcessor; import com.google.common.collect.Queues; import com.google.common.util.concurrent.ThreadFactoryBuilder; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.util.CollectionUtils; import java.util.List; @@ -96,10 +97,10 @@ public class ProcessorTracker { initProcessor(); log.info("[ProcessorTracker-{}] ProcessorTracker was successfully created!", instanceId); - }catch (Throwable e) { - log.warn("[ProcessorTracker-{}] create ProcessorTracker failed, all tasks submitted here will fail.", instanceId, e); + } catch (Throwable t) { + log.warn("[ProcessorTracker-{}] create ProcessorTracker failed, all tasks submitted here will fail.", instanceId, t); lethal = true; - lethalReason = e.toString(); + lethalReason = ExceptionUtils.getMessage(t); } } @@ -291,7 +292,7 @@ public class ProcessorTracker { try { processor = SpringUtils.getBean(processorInfo); }catch (Exception e) { - log.warn("[ProcessorTracker-{}] no spring bean of processor(className={}), reason is {}.", instanceId, processorInfo, e.toString()); + log.warn("[ProcessorTracker-{}] no spring bean of processor(className={}), reason is {}.", instanceId, processorInfo, ExceptionUtils.getMessage(e)); } } // 反射加载 From 2d989d2b0be42f33de5155e34dee939360f7c778 Mon Sep 17 00:00:00 2001 From: tjq Date: Sun, 20 Dec 2020 21:28:37 +0800 Subject: [PATCH 19/19] revert: temporary remove @Type(StringType) due to it will change the db colum type to varchar --- .../powerjob/server/common/redirect/DesignateServer.java | 2 +- .../server/common/redirect/DesignateServerAspect.java | 2 +- .../server/persistence/core/model/InstanceInfoDO.java | 3 --- .../server/persistence/core/model/JobInfoDO.java | 2 -- .../server/persistence/core/model/TypeDefConstant.java | 9 --------- .../server/persistence/core/model/WorkflowInfoDO.java | 2 -- .../persistence/core/model/WorkflowInstanceInfoDO.java | 4 ---- .../server/persistence/core/model/package-info.java | 7 ------- .../kfcfans/powerjob/server/service/DispatchService.java | 2 +- 9 files changed, 3 insertions(+), 30 deletions(-) delete mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/TypeDefConstant.java delete mode 100644 powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/package-info.java diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServer.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServer.java index bc31aafd..7954b7e6 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServer.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServer.java @@ -6,7 +6,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * 执行服务器运行 + * 需要在指定的服务器运行 * 注意:该注解所在方法的参数必须为对象,不可以是 long 等基本类型 * * @author tjq diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServerAspect.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServerAspect.java index 87a47448..9d8684b3 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServerAspect.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/common/redirect/DesignateServerAspect.java @@ -62,7 +62,7 @@ public class DesignateServerAspect { } if (appId == null) { - throw new PowerJobException("can't find appId in params!"); + throw new PowerJobException("can't find appId in params for:" + signature.toString()); } // 获取执行机器 diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/InstanceInfoDO.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/InstanceInfoDO.java index a956830c..5af69945 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/InstanceInfoDO.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/InstanceInfoDO.java @@ -5,7 +5,6 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.Type; import javax.persistence.*; import java.util.Date; @@ -37,7 +36,6 @@ public class InstanceInfoDO { // 任务实例参数 @Lob @Column - @Type(type = TypeDefConstant.STRING_TYPE) private String instanceParams; // 该任务实例的类型,普通/工作流(InstanceType) @@ -51,7 +49,6 @@ public class InstanceInfoDO { // 执行结果(允许存储稍大的结果) @Lob @Column - @Type(type = TypeDefConstant.STRING_TYPE) private String result; // 预计触发时间 private Long expectedTriggerTime; diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/JobInfoDO.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/JobInfoDO.java index ddccbf7a..b5d2b171 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/JobInfoDO.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/JobInfoDO.java @@ -5,7 +5,6 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.Type; import javax.persistence.*; import java.util.Date; @@ -53,7 +52,6 @@ public class JobInfoDO { // 执行器信息(可能需要存储整个脚本文件) @Lob @Column - @Type(type = TypeDefConstant.STRING_TYPE) private String processorInfo; /* ************************** 运行时配置 ************************** */ diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/TypeDefConstant.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/TypeDefConstant.java deleted file mode 100644 index fbe4b199..00000000 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/TypeDefConstant.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.github.kfcfans.powerjob.server.persistence.core.model; - -/** - * @see package-info.java - * @author user - */ -public final class TypeDefConstant { - public static final String STRING_TYPE = "string-type"; -} diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInfoDO.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInfoDO.java index ee8c53a8..f3c5d560 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInfoDO.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInfoDO.java @@ -4,7 +4,6 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.Type; import javax.persistence.*; import java.util.Date; @@ -36,7 +35,6 @@ public class WorkflowInfoDO { // 工作流的DAG图信息(点线式DAG的json) @Lob @Column - @Type(type = TypeDefConstant.STRING_TYPE) private String peDAG; /* ************************** 定时参数 ************************** */ diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInstanceInfoDO.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInstanceInfoDO.java index d6290205..e6f483c4 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInstanceInfoDO.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/WorkflowInstanceInfoDO.java @@ -4,7 +4,6 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.Type; import javax.persistence.*; import java.util.Date; @@ -40,16 +39,13 @@ public class WorkflowInstanceInfoDO { // 工作流启动参数 @Lob @Column - @Type(type = TypeDefConstant.STRING_TYPE) private String wfInitParams; @Lob @Column - @Type(type = TypeDefConstant.STRING_TYPE) private String dag; @Lob @Column - @Type(type = TypeDefConstant.STRING_TYPE) private String result; // 预计触发时间 diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/package-info.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/package-info.java deleted file mode 100644 index 543fd8a0..00000000 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/persistence/core/model/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -@TypeDefs({ - @TypeDef(name = TypeDefConstant.STRING_TYPE, typeClass = org.hibernate.type.StringType.class) -}) -package com.github.kfcfans.powerjob.server.persistence.core.model; - -import org.hibernate.annotations.TypeDef; -import org.hibernate.annotations.TypeDefs; \ No newline at end of file diff --git a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/DispatchService.java b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/DispatchService.java index 3e5c41f4..6399a72f 100644 --- a/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/DispatchService.java +++ b/powerjob-server/src/main/java/com/github/kfcfans/powerjob/server/service/DispatchService.java @@ -81,7 +81,7 @@ public class DispatchService { if (maxInstanceNum > 0) { // 这个 runningInstanceCount 已经包含了本 instance - // 不统计 WAITING_DISPATCH 的状态:使用 OpenAPI 触发的延迟任务显然不应该统计进去(比如 delay 是 1 天) + // 不统计 WAITING_DISPATCH 的状态:使用 OpenAPI 触发的延迟任务不应该统计进去(比如 delay 是 1 天) long runningInstanceCount = instanceInfoRepository.countByJobIdAndStatusIn(jobId, Lists.newArrayList(WAITING_WORKER_RECEIVE.getV(), RUNNING.getV())); // 超出最大同时运行限制,不执行调度 if (runningInstanceCount > maxInstanceNum) {