diff --git a/.github/workflows/graalvm.yml b/.github/workflows/graalvm.yml new file mode 100644 index 0000000000..fcff1f14e3 --- /dev/null +++ b/.github/workflows/graalvm.yml @@ -0,0 +1,47 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: NativeTest CI - GraalVM Native Image + +on: + pull_request: + branches: [ master ] + paths: + - '.github/workflows/graalvm.yml' + - 'reachability-metadata/src/**' + - 'test/native/native-image-filter/**' + - 'test/native/src/**' + +jobs: + build: + strategy: + matrix: + java: [ '22.0.2' ] + os: [ 'ubuntu-latest' ] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - name: Set up GraalVM CE ${{ matrix.java }} + uses: graalvm/setup-graalvm@v1 + with: + java-version: ${{ matrix.java }} + distribution: 'graalvm-community' + github-token: ${{ secrets.GITHUB_TOKEN }} + cache: 'maven' + - name: Run nativeTest with GraalVM CE for ${{ matrix.java-version }} + continue-on-error: true + run: ./mvnw -PnativeTestInElasticJob -T1C -B -e clean test diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml index 75ae790343..4606a518dd 100644 --- a/bootstrap/pom.xml +++ b/bootstrap/pom.xml @@ -62,6 +62,11 @@ elasticjob-tracing-rdb ${project.parent.version} + + org.apache.shardingsphere.elasticjob + elasticjob-reachability-metadata + ${project.version} + org.apache.shardingsphere.elasticjob diff --git a/docs/content/user-manual/configuration/graalvm-native-image.cn.md b/docs/content/user-manual/configuration/graalvm-native-image.cn.md new file mode 100644 index 0000000000..09f85ca46c --- /dev/null +++ b/docs/content/user-manual/configuration/graalvm-native-image.cn.md @@ -0,0 +1,166 @@ ++++ +title = "GraalVM Native Image 支持" +weight = 6 +chapter = true ++++ + +## 背景信息 + +ElasticJob 已在 GraalVM Native Image 下完成可用性验证。 + +构建包含 `org.apache.shardingsphere.elasticjob:elasticjob-bootstrap:${elasticjob.version}` 的 Maven 依赖的 GraalVM Native Image, +你需要借助于 GraalVM Native Build Tools。 +GraalVM Native Build Tools 提供了 Maven Plugin 和 Gradle Plugin 来简化 GraalVM CE 的 `native-image` 命令行工具的长篇大论的 shell 命令。 + +ElasticJob 要求在如下或更高版本的 `GraalVM CE` 完成构建 GraalVM Native Image。使用者可通过 SDKMAN! 快速切换 JDK。这同理 +适用于 https://sdkman.io/jdks#graal , https://sdkman.io/jdks#nik 和 https://sdkman.io/jdks#mandrel 等 `GraalVM CE` 的下游发行版。 + +- GraalVM CE For JDK 22.0.2,对应于 SDKMAN! 的 `22.0.2-graalce` + +用户依然可以使用 SDKMAN! 上的 `21.0.2-graalce` 等旧版本的 GraalVM CE 来构建 ShardingSphere 的 GraalVM Native Image 产物。 +ElasticJob 不为已停止维护的 GraalVM CE 版本设置 CI。 + +## 使用 ElasticJob 的 Java API + +### Maven 生态 + +使用者需要主动使用 GraalVM Reachability Metadata 中央仓库。 +如下配置可供参考,以配置项目额外的 Maven Profiles,以 GraalVM Native Build Tools 的文档为准。 + +```xml + + + + org.apache.shardingsphere.elasticjob + elasticjob-bootstrap + ${elasticjob.version} + test + + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + build-native + + compile-no-fork + + package + + + test-native + + test + + test + + + + + + +``` + +### Gradle 生态 + +使用者需要主动使用 GraalVM Reachability Metadata 中央仓库。 +如下配置可供参考,以配置项目额外的 Gradle Tasks,以 GraalVM Native Build Tools 的文档为准。 +由于 https://github.com/gradle/gradle/issues/17559 的限制,用户需要通过 Maven 依赖的形式引入 Metadata Repository 的 JSON 文件。 +参考 https://github.com/graalvm/native-build-tools/issues/572 。 + +```groovy +plugins { + id 'org.graalvm.buildtools.native' version '0.10.2' +} + +dependencies { + implementation 'org.apache.shardingsphere.elasticjob:elasticjob-bootstrap:${elasticjob.version}' + implementation(group: 'org.graalvm.buildtools', name: 'graalvm-reachability-metadata', version: '0.10.2', classifier: 'repository', ext: 'zip') +} + +graalvmNative { + metadataRepository { + enabled.set(false) + } +} +``` + +## 对于 sbt 等不被 GraalVM Native Build Tools 支持的构建工具 + +此类需求需要在 https://github.com/graalvm/native-build-tools 打开额外的 issue 并提供对应构建工具的 Plugin 实现。 + +## 使用限制 + +1. 用户无法在 GraalVM Native Image 使用 elasticJobType 为 SCRIPT 的 Job。参考 https://github.com/oracle/graal/issues/7390 。 + +2. 使用者依然需要在 `src/main/resources/META-INF/native-image` 文件夹或 `src/test/resources/META-INF/native-image` 文件夹配置独立文件的 GraalVM Reachability Metadata。 +使用者可通过 GraalVM Native Build Tools 的 GraalVM Tracing Agent 来快速采集 GraalVM Reachability Metadata。 + +3. ElasticJob 的 Spring 命名空间集成模块 `org.apache.shardingsphere.elasticjob:elasticjob-spring-namespace` 尚未在 GraalVM Native Image 下可用。 + +4. ElasticJob 的 Spring Boot Starter 集成模块 `org.apache.shardingsphere.elasticjob:elasticjob-spring-boot-starter` 尚未在 GraalVM Native Image 下可用。 + +## 贡献 GraalVM Reachability Metadata + +ElasticJob 对在 GraalVM Native Image 下的可用性的验证,是通过 GraalVM Native Build Tools 的 Maven Plugin 子项目来完成的。 +通过在 JVM 下运行单元测试,为单元测试打上 `junit-platform-unique-ids*` 标签,此后构建为 GraalVM Native Image 进行 nativeTest 来测试 +在 GraalVM Native Image 下的单元测试覆盖率。请贡献者不要使用 `io.kotest:kotest-runner-junit5-jvm:5.5.4` 等在 `test listener` mode 下 +failed to discover tests 的测试库。 + +ElasticJob 定义了 `elasticjob-test-native` 的 Maven Module 用于为 native Test 提供小型的单元测试子集, +此单元测试子集避免了使用 Mockito 等 native Test 下无法使用的第三方库。 + +ElasticJob 定义了 `nativeTestInElasticJob` 的 Maven Profile 用于为 `elasticjob-test-native` 模块执行 nativeTest 。 + +假设贡献者处于新的 Ubuntu 22.04.4 LTS 实例下,其可通过如下 bash 命令通过 SDKMAN! 管理 JDK 和工具链, +并为 `elasticjob-test-native` 子模块执行 nativeTest。 + +贡献者必须安装 Docker Engine 以执行 `testcontainers-java` 相关的单元测试。 + +```bash +sudo apt install unzip zip curl sed -y +curl -s "https://get.sdkman.io" | bash +source "$HOME/.sdkman/bin/sdkman-init.sh" +sdk install java 22.0.2-graalce +sdk use java 22.0.2-graalce +sudo apt-get install build-essential zlib1g-dev -y + +git clone git@github.com:apache/shardingsphere-elasticjob.git +cd ./shardingsphere-elasticjob/ +./mvnw -PnativeTestInElasticJob -T1C -e clean test +``` + +当贡献者发现缺少与 ElasticJob 无关的第三方库的 GraalVM Reachability Metadata 时,应当在 +https://github.com/oracle/graalvm-reachability-metadata 打开新的 issue, 并提交包含依赖的第三方库缺失的 GraalVM Reachability +Metadata 的 PR。ElasticJob 在 `elasticjob-reachability-metadata` 子模块主动托管了部分第三方库的 GraalVM Reachability Metadata。 + +如果 nativeTest 执行失败, 应为单元测试生成初步的 GraalVM Reachability Metadata, +并手动调整 `elasticjob-reachability-metadata` 子模块的 classpath 的 `META-INF/native-image/org.apache.shardingsphere.elasticjob/elasticjob-reachability-metadata/` 文件夹下的内容以修复 nativeTest。 +如有需要,请使用 `org.junit.jupiter.api.condition.DisabledInNativeImage` 注解或 `org.graalvm.nativeimage.imagecode` 的 +System Property 屏蔽部分单元测试在 GraalVM Native Image 下运行。 + +ElasticJob 定义了 `generateMetadata` 的 Maven Profile 用于在 GraalVM JIT Compiler 下携带 GraalVM Tracing Agent 执行单元测试, +并在 `elasticjob-reachability-metadata` 子模块的 classpath 的 `META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/` 文件夹下, +生成或覆盖已有的 GraalVM Reachability Metadata 文件。可通过如下 bash 命令简单处理此流程。 +贡献者仍可能需要手动调整具体的 JSON 条目,并适时调整 Maven Profile 和 GraalVM Tracing Agent 的 Filter 链。 +针对 `elasticjob-reachability-metadata` 子模块, +手动增删改动的 JSON 条目应位于 `META-INF/native-image/org.apache.shardingsphere.elasticjob/elasticjob-reachability-metadata/` 文件夹下, +而 `META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/` 中的条目仅应由 `generateMetadata` 的 Maven Profile 生成。 + +以下命令仅为 `elasticjob-test-native` 生成 Conditional 形态的 GraalVM Reachability Metadata 的一个举例。 +生成的 GraalVM Reachability Metadata 位于 `elasticjob-reachability-metadata` 子模块下。 + +对于测试类和测试文件独立使用的 GraalVM Reachability Metadata,贡献者应该放置到 `shardingsphere-test-native` 子模块的 classpath 的 +`META-INF/native-image/elasticjob-test-native-test-metadata/` 下。 + +```bash +git clone git@github.com:apache/shardingsphere.git +cd ./shardingsphere/ +./mvnw -PgenerateMetadata -DskipNativeTests -e -T1C clean test native:metadata-copy +``` diff --git a/docs/content/user-manual/configuration/graalvm-native-image.en.md b/docs/content/user-manual/configuration/graalvm-native-image.en.md new file mode 100644 index 0000000000..23eda33816 --- /dev/null +++ b/docs/content/user-manual/configuration/graalvm-native-image.en.md @@ -0,0 +1,9 @@ ++++ +title = "GraalVM Native Image Support" +weight = 6 +chapter = true ++++ + +## TODO + +Users can temporarily refer to the Chinese documentation corresponding to this page. diff --git a/pom.xml b/pom.xml index dee0a8d466..b6f8202b27 100644 --- a/pom.xml +++ b/pom.xml @@ -44,6 +44,7 @@ test distribution + reachability-metadata @@ -126,6 +127,8 @@ 1.0.0 3.4 1.10 + + 0.10.2 @@ -920,6 +923,100 @@ + + generateMetadata + + + + + maven-surefire-plugin + + + org.apache.shardingsphere.elasticjob.test.natived.** + + + + + org.graalvm.buildtools + native-maven-plugin + ${native-maven-plugin.version} + true + + + true + Conditional + + + ${user.dir}/test/native/native-image-filter/user-code-filter.json + ${user.dir}/test/native/native-image-filter/extra-filter.json + true + + + + + main + + false + ${user.dir}/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/ + + + + + + build-native + + compile-no-fork + + package + + + test-native + + test + + test + + + + + + + + + nativeTestInElasticJob + + + + + maven-surefire-plugin + + + org.apache.shardingsphere.elasticjob.test.natived.** + + + + + org.graalvm.buildtools + native-maven-plugin + ${native-maven-plugin.version} + true + + true + + + + test-native + + test + + test + + + + + + + diff --git a/reachability-metadata/pom.xml b/reachability-metadata/pom.xml new file mode 100644 index 0000000000..2d9cd037cf --- /dev/null +++ b/reachability-metadata/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + org.apache.shardingsphere.elasticjob + elasticjob + 3.1.0-SNAPSHOT + + elasticjob-reachability-metadata + ${project.artifactId} + + diff --git a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/elasticjob-reachability-metadata/reflect-config.json b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/elasticjob-reachability-metadata/reflect-config.json new file mode 100644 index 0000000000..cb28c8e584 --- /dev/null +++ b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/elasticjob-reachability-metadata/reflect-config.json @@ -0,0 +1,7 @@ +[ +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.yaml.YamlTracingConfiguration"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.tracing.yaml.YamlTracingConfiguration", + "allPublicMethods":true +} +] diff --git a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/jni-config.json b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/jni-config.json new file mode 100644 index 0000000000..32960f8ced --- /dev/null +++ b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/jni-config.json @@ -0,0 +1,2 @@ +[ +] \ No newline at end of file diff --git a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/predefined-classes-config.json b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/predefined-classes-config.json new file mode 100644 index 0000000000..847895071f --- /dev/null +++ b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/predefined-classes-config.json @@ -0,0 +1,7 @@ +[ + { + "type":"agent-extracted", + "classes":[ + ] + } +] diff --git a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/proxy-config.json b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/proxy-config.json new file mode 100644 index 0000000000..fd2d4325f4 --- /dev/null +++ b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/proxy-config.json @@ -0,0 +1,6 @@ +[ + { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.converter.RDBTracingStorageConfigurationConverter"}, + "interfaces":["java.sql.Connection"] + } +] \ No newline at end of file diff --git a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/reflect-config.json b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/reflect-config.json new file mode 100644 index 0000000000..decaa1ec62 --- /dev/null +++ b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/reflect-config.json @@ -0,0 +1,287 @@ +[ +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.converter.RDBTracingStorageConfigurationConverter"}, + "name":"[Lcom.zaxxer.hikari.util.ConcurrentBag$IConcurrentBagEntry;" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.event.JobTracingEventBus"}, + "name":"com.google.common.util.concurrent.AbstractFuture", + "fields":[{"name":"listeners"}, {"name":"value"}, {"name":"waiters"}] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.event.JobTracingEventBus"}, + "name":"com.google.common.util.concurrent.AbstractFuture$Waiter", + "fields":[{"name":"next"}, {"name":"thread"}] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "name":"java.util.Properties", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.ElasticJobExecutor"}, + "name":"java.util.Properties", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.failover.FailoverListenerManager"}, + "name":"java.util.Properties", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.reconcile.ReconcileService"}, + "name":"java.util.Properties", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.ShardingListenerManager$ShardingTotalCountChangedJobListener"}, + "name":"java.util.Properties", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.item.JobItemExecutorFactory"}, + "name":"org.apache.shardingsphere.elasticjob.dataflow.executor.DataflowJobExecutor" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.error.handler.JobErrorHandlerReloader"}, + "name":"org.apache.shardingsphere.elasticjob.error.handler.normal.IgnoreJobErrorHandler", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.error.handler.JobErrorHandlerReloader"}, + "name":"org.apache.shardingsphere.elasticjob.error.handler.normal.LogJobErrorHandler", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.error.handler.JobErrorHandlerReloader"}, + "name":"org.apache.shardingsphere.elasticjob.error.handler.normal.ThrowJobErrorHandler", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.ElasticJobExecutor"}, + "name":"org.apache.shardingsphere.elasticjob.http.executor.HttpJobExecutor" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.threadpool.ExecutorServiceReloader"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.executor.threadpool.type.CPUUsageJobExecutorThreadPoolSizeProvider" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.threadpool.ExecutorServiceReloader"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.executor.threadpool.type.SingleThreadJobExecutorThreadPoolSizeProvider" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.OneOffJobBootstrap"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", + "queryAllPublicMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", + "queryAllPublicMethods":true, + "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.ElasticJobExecutor"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", + "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.infra.yaml.YamlEngine"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", + "allDeclaredFields":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setDescription","parameterTypes":["java.lang.String"] }, {"name":"setDisabled","parameterTypes":["boolean"] }, {"name":"setFailover","parameterTypes":["boolean"] }, {"name":"setJobExtraConfigurations","parameterTypes":["java.util.Collection"] }, {"name":"setJobName","parameterTypes":["java.lang.String"] }, {"name":"setJobParameter","parameterTypes":["java.lang.String"] }, {"name":"setMaxTimeDiffSeconds","parameterTypes":["int"] }, {"name":"setMisfire","parameterTypes":["boolean"] }, {"name":"setMonitorExecution","parameterTypes":["boolean"] }, {"name":"setOverwrite","parameterTypes":["boolean"] }, {"name":"setReconcileIntervalMinutes","parameterTypes":["int"] }, {"name":"setShardingItemParameters","parameterTypes":["java.lang.String"] }, {"name":"setShardingTotalCount","parameterTypes":["int"] }, {"name":"setStaticSharding","parameterTypes":["boolean"] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.config.ConfigurationService"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", + "allDeclaredFields":true, + "methods":[{"name":"getCron","parameterTypes":[] }, {"name":"getDescription","parameterTypes":[] }, {"name":"getJobErrorHandlerType","parameterTypes":[] }, {"name":"getJobExecutorThreadPoolSizeProviderType","parameterTypes":[] }, {"name":"getJobExtraConfigurations","parameterTypes":[] }, {"name":"getJobListenerTypes","parameterTypes":[] }, {"name":"getJobName","parameterTypes":[] }, {"name":"getJobParameter","parameterTypes":[] }, {"name":"getJobShardingStrategyType","parameterTypes":[] }, {"name":"getLabel","parameterTypes":[] }, {"name":"getMaxTimeDiffSeconds","parameterTypes":[] }, {"name":"getProps","parameterTypes":[] }, {"name":"getReconcileIntervalMinutes","parameterTypes":[] }, {"name":"getShardingItemParameters","parameterTypes":[] }, {"name":"getShardingTotalCount","parameterTypes":[] }, {"name":"getTimeZone","parameterTypes":[] }, {"name":"isDisabled","parameterTypes":[] }, {"name":"isFailover","parameterTypes":[] }, {"name":"isMisfire","parameterTypes":[] }, {"name":"isMonitorExecution","parameterTypes":[] }, {"name":"isOverwrite","parameterTypes":[] }, {"name":"isStaticSharding","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.failover.FailoverListenerManager"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", + "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.reconcile.ReconcileService"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", + "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobScheduler"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", + "queryAllPublicMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.ShardingListenerManager$ShardingTotalCountChangedJobListener"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", + "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJOBeanInfo" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJOCustomizer" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.OneOffJobBootstrap"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobShutdownHookPlugin", + "queryAllPublicMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobShutdownHookPlugin", + "queryAllPublicMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobScheduler"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobShutdownHookPlugin", + "queryAllPublicMethods":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setCleanShutdown","parameterTypes":["boolean"] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobShutdownHookPluginBeanInfo" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobShutdownHookPluginCustomizer" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.OneOffJobBootstrap"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstance", + "queryAllPublicMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstance", + "queryAllPublicMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.instance.InstanceNode"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstance", + "allDeclaredFields":true, + "methods":[{"name":"getJobInstanceId","parameterTypes":[] }, {"name":"getLabels","parameterTypes":[] }, {"name":"getServerIp","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.instance.InstanceService"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstance" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobScheduler"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstance", + "queryAllPublicMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.setup.SetUpFacade"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstance" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstanceBeanInfo" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstanceCustomizer" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.infra.yaml.YamlEngine"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.tracing.yaml.YamlTracingConfiguration", + "allDeclaredFields":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setTracingStorageConfiguration","parameterTypes":["org.apache.shardingsphere.elasticjob.kernel.tracing.yaml.YamlTracingStorageConfiguration"] }, {"name":"setType","parameterTypes":["java.lang.String"] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.tracing.yaml.YamlTracingConfigurationConverter" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.reg.exception.RegExceptionHandler"}, + "name":"org.apache.shardingsphere.elasticjob.reg.zookeeper.exception.ZookeeperCuratorIgnoredExceptionProvider" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.ElasticJobExecutor"}, + "name":"org.apache.shardingsphere.elasticjob.script.executor.ScriptJobExecutor" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.item.JobItemExecutorFactory"}, + "name":"org.apache.shardingsphere.elasticjob.simple.executor.SimpleJobExecutor" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.event.JobTracingEventBus"}, + "name":"org.apache.shardingsphere.elasticjob.spi.tracing.listener.TracingListener", + "queryAllDeclaredMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.event.JobTracingEventBus"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.listener.RDBTracingListener", + "queryAllDeclaredMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.event.JobTracingEventBus"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.listener.RDBTracingListenerFactory" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.storage.TracingStorageConverterFactory"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.converter.RDBTracingStorageConfigurationConverter" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.repository.RDBJobEventRepository"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.type.impl.DB2TracingStorageDatabaseType" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.repository.RDBJobEventRepository"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.type.impl.H2TracingStorageDatabaseType" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.repository.RDBJobEventRepository"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.type.impl.MySQLTracingStorageDatabaseType" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.repository.RDBJobEventRepository"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.type.impl.OracleTracingStorageDatabaseType" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.repository.RDBJobEventRepository"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.type.impl.PostgreSQLTracingStorageDatabaseType" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.repository.RDBJobEventRepository"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.type.impl.SQLServerTracingStorageDatabaseType" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.infra.yaml.YamlEngine"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.yaml.YamlDataSourceConfiguration", + "allDeclaredFields":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setDataSourceClassName","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Map"] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.yaml.YamlDataSourceConfigurationConverter" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperRegistryCenter"}, + "name":"org.apache.zookeeper.AddWatchMode" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperRegistryCenter"}, + "name":"org.apache.zookeeper.ClientCnxnSocketNIO", + "methods":[{"name":"","parameterTypes":["org.apache.zookeeper.client.ZKClientConfig"] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperRegistryCenter"}, + "name":"org.apache.zookeeper.server.quorum.MultipleAddresses", + "methods":[{"name":"getReachableOrOne","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperRegistryCenter"}, + "name":"org.apache.zookeeper.server.quorum.QuorumPeer$QuorumServer", + "fields":[{"name":"addr"}] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.event.JobTracingEventBus"}, + "name":"sun.misc.Unsafe", + "allDeclaredFields":true +} +] \ No newline at end of file diff --git a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/resource-config.json b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/resource-config.json new file mode 100644 index 0000000000..101e57e2fc --- /dev/null +++ b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/resource-config.json @@ -0,0 +1,41 @@ +{ + "resources":{ + "includes":[{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.threadpool.ExecutorServiceReloader"}, + "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.kernel.executor.threadpool.JobExecutorThreadPoolSizeProvider\\E" + }, { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.setup.JobClassNameProviderFactory"}, + "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.kernel.internal.setup.JobClassNameProvider\\E" + }, { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.reg.exception.RegExceptionHandler"}, + "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.reg.exception.IgnoredExceptionProvider\\E" + }, { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.spi.executor.error.handler.JobErrorHandler\\E" + }, { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.item.JobItemExecutorFactory"}, + "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.spi.executor.item.type.ClassedJobItemExecutor\\E" + }, { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.ElasticJobExecutor"}, + "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.spi.executor.item.type.TypedJobItemExecutor\\E" + }, { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.event.JobTracingEventBus"}, + "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.spi.tracing.listener.TracingListenerFactory\\E" + }, { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.storage.TracingStorageConverterFactory"}, + "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.spi.tracing.storage.TracingStorageConfigurationConverter\\E" + }, { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO"}, + "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.spi.yaml.YamlConfigurationConverter\\E" + }, { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.repository.RDBJobEventRepository"}, + "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.tracing.rdb.storage.type.TracingStorageDatabaseType\\E" + }, { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.sql.SQLPropertiesFactory"}, + "pattern":"\\QMETA-INF/sql/H2.properties\\E" + }, { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "pattern":"\\Qorg/quartz/core/quartz-build.properties\\E" + }]}, + "bundles":[] +} \ No newline at end of file diff --git a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/serialization-config.json b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/serialization-config.json new file mode 100644 index 0000000000..d0304f2a1c --- /dev/null +++ b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/serialization-config.json @@ -0,0 +1,8 @@ +{ + "types":[ + ], + "lambdaCapturingTypes":[ + ], + "proxies":[ + ] +} \ No newline at end of file diff --git a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.zookeeper/zookeeper/3.9.2/reflect-config.json b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.zookeeper/zookeeper/3.9.2/reflect-config.json new file mode 100644 index 0000000000..a6e52201ca --- /dev/null +++ b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.zookeeper/zookeeper/3.9.2/reflect-config.json @@ -0,0 +1,56 @@ +[ +{ + "condition":{"typeReachable":"org.apache.zookeeper.ZooKeeper"}, + "name":"org.apache.zookeeper.ClientCnxnSocketNIO", + "methods":[{"name":"","parameterTypes":["org.apache.zookeeper.client.ZKClientConfig"] }] +}, +{ + "condition":{"typeReachable":"org.apache.zookeeper.metrics.impl.MetricsProviderBootstrap"}, + "name":"org.apache.zookeeper.metrics.impl.DefaultMetricsProvider", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.zookeeper.server.quorum.QuorumPeerConfig"}, + "name":"org.apache.zookeeper.metrics.impl.DefaultMetricsProvider" +}, +{ + "condition":{"typeReachable":"org.apache.zookeeper.server.ServerCnxnFactory"}, + "name":"org.apache.zookeeper.server.ConnectionBean", + "queryAllPublicConstructors":true +}, +{ + "condition":{"typeReachable":"org.apache.zookeeper.server.ServerCnxnFactory"}, + "name":"org.apache.zookeeper.server.ConnectionMXBean", + "queryAllPublicMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.zookeeper.server.ZooKeeperServer"}, + "name":"org.apache.zookeeper.server.DataTreeBean", + "queryAllPublicConstructors":true +}, +{ + "condition":{"typeReachable":"org.apache.zookeeper.server.ZooKeeperServer"}, + "name":"org.apache.zookeeper.server.DataTreeMXBean", + "queryAllPublicMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.zookeeper.server.ServerCnxnFactory"}, + "name":"org.apache.zookeeper.server.NIOServerCnxnFactory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.zookeeper.server.ZooKeeperServer"}, + "name":"org.apache.zookeeper.server.ZooKeeperServerBean", + "queryAllPublicConstructors":true +}, +{ + "condition":{"typeReachable":"org.apache.zookeeper.server.ZooKeeperServer"}, + "name":"org.apache.zookeeper.server.ZooKeeperServerMXBean", + "queryAllPublicMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.zookeeper.server.watch.WatchManagerFactory"}, + "name":"org.apache.zookeeper.server.watch.WatchManager", + "methods":[{"name":"","parameterTypes":[] }] +} +] diff --git a/spring/core/pom.xml b/spring/core/pom.xml index 1d59320696..dbc3b8c1b5 100644 --- a/spring/core/pom.xml +++ b/spring/core/pom.xml @@ -42,15 +42,18 @@ org.springframework spring-context + provided org.springframework spring-context-support + provided org.springframework spring-test + test diff --git a/spring/namespace/pom.xml b/spring/namespace/pom.xml index 62d842f237..83a3a8ae40 100644 --- a/spring/namespace/pom.xml +++ b/spring/namespace/pom.xml @@ -62,10 +62,12 @@ org.springframework spring-context + provided org.springframework spring-context-support + provided @@ -75,6 +77,7 @@ org.springframework spring-test + test com.h2database diff --git a/test/native/native-image-filter/extra-filter.json b/test/native/native-image-filter/extra-filter.json new file mode 100644 index 0000000000..62800a1b20 --- /dev/null +++ b/test/native/native-image-filter/extra-filter.json @@ -0,0 +1,14 @@ +{ + "rules": [ + {"includeClasses": "**"}, + + {"excludeClasses": "com.zaxxer.hikari.**"}, + {"excludeClasses": "java.**"}, + {"includeClasses": "java.util.Properties"}, + {"excludeClasses": "org.quartz.**"}, + + {"excludeClasses": "org.apache.shardingsphere.elasticjob.test.natived.**"} + ], + "regexRules": [ + ] +} diff --git a/test/native/native-image-filter/user-code-filter.json b/test/native/native-image-filter/user-code-filter.json new file mode 100644 index 0000000000..926a991968 --- /dev/null +++ b/test/native/native-image-filter/user-code-filter.json @@ -0,0 +1,7 @@ +{ + "rules": [ + {"excludeClasses": "**"}, + {"includeClasses": "org.apache.shardingsphere.elasticjob.**"}, + {"excludeClasses": "org.apache.shardingsphere.elasticjob.test.natived.**"} + ] +} diff --git a/test/native/pom.xml b/test/native/pom.xml new file mode 100644 index 0000000000..1becb88eef --- /dev/null +++ b/test/native/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + org.apache.shardingsphere.elasticjob + elasticjob-test + 3.1.0-SNAPSHOT + + elasticjob-test-native + ${project.artifactId} + + + true + + + + + org.apache.shardingsphere.elasticjob + elasticjob-bootstrap + ${project.version} + test + + + + org.awaitility + awaitility + test + + + com.h2database + h2 + test + + + org.apache.curator + curator-test + test + + + + + + + org.graalvm.buildtools + native-maven-plugin + ${native-maven-plugin.version} + + + + diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/JavaTest.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/JavaTest.java new file mode 100644 index 0000000000..42d6e34f99 --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/JavaTest.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.elasticjob.test.natived; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.apache.curator.CuratorZookeeperClient; +import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.curator.test.TestingServer; +import org.apache.shardingsphere.elasticjob.api.JobConfiguration; +import org.apache.shardingsphere.elasticjob.bootstrap.type.OneOffJobBootstrap; +import org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap; +import org.apache.shardingsphere.elasticjob.dataflow.props.DataflowJobProperties; +import org.apache.shardingsphere.elasticjob.http.props.HttpJobProperties; +import org.apache.shardingsphere.elasticjob.kernel.tracing.config.TracingConfiguration; +import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter; +import org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperConfiguration; +import org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperRegistryCenter; +import org.apache.shardingsphere.elasticjob.script.props.ScriptJobProperties; +import org.apache.shardingsphere.elasticjob.test.natived.commons.job.dataflow.JavaDataflowJob; +import org.apache.shardingsphere.elasticjob.test.natived.commons.job.simple.JavaSimpleJob; +import org.awaitility.Awaitility; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; + +import javax.sql.DataSource; +import java.io.IOException; +import java.nio.file.Paths; +import java.time.Duration; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class JavaTest { + + private static TestingServer testingServer; + + private static CoordinatorRegistryCenter regCenter; + + private static TracingConfiguration tracingConfig; + + @BeforeAll + static void beforeAll() throws Exception { + testingServer = new TestingServer(); + try ( + CuratorZookeeperClient client = new CuratorZookeeperClient(testingServer.getConnectString(), + 60 * 1000, 500, null, + new ExponentialBackoffRetry(500, 3, 500 * 3))) { + client.start(); + Awaitility.await().atMost(Duration.ofMillis(500 * 60)).until(client::isConnected); + } + regCenter = new ZookeeperRegistryCenter(new ZookeeperConfiguration(testingServer.getConnectString(), "elasticjob-test-native-java")); + regCenter.init(); + HikariConfig config = new HikariConfig(); + config.setDriverClassName("org.h2.Driver"); + config.setJdbcUrl("jdbc:h2:mem:job_event_storage"); + config.setUsername("sa"); + config.setPassword(""); + tracingConfig = new TracingConfiguration<>("RDB", new HikariDataSource(config)); + } + + @AfterAll + static void afterAll() throws IOException { + regCenter.close(); + testingServer.close(); + } + + @Test + void testHttpJob() { + ScheduleJobBootstrap jobBootstrap = new ScheduleJobBootstrap(regCenter, "HTTP", + JobConfiguration.newBuilder("testJavaHttpJob", 3) + .setProperty(HttpJobProperties.URI_KEY, "https://www.apache.org") + .setProperty(HttpJobProperties.METHOD_KEY, "GET") + .cron("0/5 * * * * ?") + .shardingItemParameters("0=Norddorf,1=Bordeaux,2=Somerset") + .addExtraConfigurations(tracingConfig) + .build()); + assertDoesNotThrow(() -> { + jobBootstrap.schedule(); + jobBootstrap.shutdown(); + }); + } + + @Test + void testSimpleJob() { + ScheduleJobBootstrap jobBootstrap = new ScheduleJobBootstrap(regCenter, new JavaSimpleJob(), + JobConfiguration.newBuilder("testJavaSimpleJob", 3) + .cron("0/5 * * * * ?") + .shardingItemParameters("0=Norddorf,1=Bordeaux,2=Somerset") + .addExtraConfigurations(tracingConfig) + .build()); + assertDoesNotThrow(() -> { + jobBootstrap.schedule(); + jobBootstrap.shutdown(); + }); + } + + @Test + void testDataflowJob() { + ScheduleJobBootstrap jobBootstrap = new ScheduleJobBootstrap(regCenter, new JavaDataflowJob(), + JobConfiguration.newBuilder("testJavaDataflowElasticJob", 3) + .cron("0/5 * * * * ?") + .shardingItemParameters("0=Norddorf,1=Bordeaux,2=Somerset") + .setProperty(DataflowJobProperties.STREAM_PROCESS_KEY, Boolean.TRUE.toString()) + .addExtraConfigurations(tracingConfig) + .build()); + assertDoesNotThrow(() -> { + jobBootstrap.schedule(); + jobBootstrap.shutdown(); + }); + } + + @Test + void testOneOffJob() { + OneOffJobBootstrap jobBootstrap = new OneOffJobBootstrap(regCenter, new JavaSimpleJob(), + JobConfiguration.newBuilder("testJavaOneOffSimpleJob", 3) + .shardingItemParameters("0=Norddorf,1=Bordeaux,2=Somerset") + .addExtraConfigurations(tracingConfig) + .build()); + assertDoesNotThrow(() -> { + jobBootstrap.execute(); + jobBootstrap.shutdown(); + }); + } + + @Test + @EnabledOnOs(OS.LINUX) + void testScriptJob() { + ScheduleJobBootstrap jobBootstrap = new ScheduleJobBootstrap(regCenter, "SCRIPT", + JobConfiguration.newBuilder("scriptElasticJob", 3) + .cron("0/5 * * * * ?") + .setProperty(ScriptJobProperties.SCRIPT_KEY, Paths.get("src/test/resources/script/demo.sh").toString()) + .addExtraConfigurations(tracingConfig) + .build()); + assertDoesNotThrow(() -> { + jobBootstrap.schedule(); + jobBootstrap.shutdown(); + }); + } +} diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/entity/Foo.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/entity/Foo.java new file mode 100644 index 0000000000..7fb818cd65 --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/entity/Foo.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.elasticjob.test.natived.commons.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; + +@Getter +@ToString +@AllArgsConstructor +public final class Foo implements Serializable { + + private static final long serialVersionUID = 2706842871078949451L; + + private final long id; + + private final String location; + + @Setter + private Status status; + + public enum Status { + TODO, + COMPLETED + } +} diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/dataflow/JavaDataflowJob.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/dataflow/JavaDataflowJob.java new file mode 100644 index 0000000000..7c87dffacc --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/dataflow/JavaDataflowJob.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.elasticjob.test.natived.commons.job.dataflow; + +import org.apache.shardingsphere.elasticjob.spi.executor.item.param.ShardingContext; +import org.apache.shardingsphere.elasticjob.dataflow.job.DataflowJob; +import org.apache.shardingsphere.elasticjob.test.natived.commons.entity.Foo; +import org.apache.shardingsphere.elasticjob.test.natived.commons.repository.FooRepository; +import org.apache.shardingsphere.elasticjob.test.natived.commons.repository.FooRepositoryFactory; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +public class JavaDataflowJob implements DataflowJob { + + private final FooRepository fooRepository = FooRepositoryFactory.getFOO_REPOSITORY(); + + @Override + public List fetchData(final ShardingContext shardingContext) { + System.out.printf( + "Item: %s | Time: %s | Thread: %s | %s%n", + shardingContext.getShardingItem(), + new SimpleDateFormat("HH:mm:ss").format(new Date()), + Thread.currentThread().getId(), + "DATAFLOW FETCH"); + return fooRepository.findTodoData(shardingContext.getShardingParameter(), 10); + } + + @Override + public void processData(final ShardingContext shardingContext, final List data) { + System.out.printf( + "Item: %s | Time: %s | Thread: %s | %s%n", + shardingContext.getShardingItem(), + new SimpleDateFormat("HH:mm:ss").format(new Date()), + Thread.currentThread().getId(), + "DATAFLOW PROCESS"); + data.stream().mapToLong(Foo::getId).forEach(fooRepository::setCompleted); + } +} diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/simple/JavaSimpleJob.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/simple/JavaSimpleJob.java new file mode 100644 index 0000000000..0932a700bc --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/simple/JavaSimpleJob.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.elasticjob.test.natived.commons.job.simple; + +import org.apache.shardingsphere.elasticjob.spi.executor.item.param.ShardingContext; +import org.apache.shardingsphere.elasticjob.simple.job.SimpleJob; +import org.apache.shardingsphere.elasticjob.test.natived.commons.entity.Foo; +import org.apache.shardingsphere.elasticjob.test.natived.commons.repository.FooRepository; +import org.apache.shardingsphere.elasticjob.test.natived.commons.repository.FooRepositoryFactory; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +public class JavaSimpleJob implements SimpleJob { + + private final FooRepository fooRepository = FooRepositoryFactory.getFOO_REPOSITORY(); + + @Override + public void execute(final ShardingContext shardingContext) { + System.out.printf( + "Item: %s | Time: %s | Thread: %s | %s%n", + shardingContext.getShardingItem(), + new SimpleDateFormat("HH:mm:ss").format(new Date()), + Thread.currentThread().getId(), + "SIMPLE"); + List data = fooRepository.findTodoData(shardingContext.getShardingParameter(), 10); + data.stream().mapToLong(Foo::getId).forEach(fooRepository::setCompleted); + } +} diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/repository/FooRepository.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/repository/FooRepository.java new file mode 100644 index 0000000000..e6abaf1b10 --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/repository/FooRepository.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.elasticjob.test.natived.commons.repository; + +import org.apache.shardingsphere.elasticjob.test.natived.commons.entity.Foo; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.LongStream; + +public class FooRepository { + + private final Map data = new ConcurrentHashMap<>(300, 1); + + public FooRepository() { + addData(0L, 100L, "Norddorf"); + addData(100L, 200L, "Bordeaux"); + addData(200L, 300L, "Somerset"); + } + + private void addData(final long idFrom, final long idTo, final String location) { + LongStream.range(idFrom, idTo) + .forEachOrdered(i -> data.put(i, new Foo(i, location, Foo.Status.TODO))); + } + + /** + * Find todoData. + * @param location location + * @param limit limit + * @return An ordered collection, where the user has precise control over where in the list each element is inserted. + */ + public List findTodoData(final String location, final int limit) { + List result = new ArrayList<>(limit); + int count = 0; + for (Map.Entry each : data.entrySet()) { + Foo foo = each.getValue(); + if (foo.getLocation().equals(location) && foo.getStatus() == Foo.Status.TODO) { + result.add(foo); + count++; + if (count == limit) { + break; + } + } + } + return result; + } + + /** + * Set completed. + * @param id id + */ + public void setCompleted(final long id) { + data.get(id).setStatus(Foo.Status.COMPLETED); + } +} diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/repository/FooRepositoryFactory.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/repository/FooRepositoryFactory.java new file mode 100644 index 0000000000..8ce70c48f6 --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/repository/FooRepositoryFactory.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.elasticjob.test.natived.commons.repository; + +import lombok.Getter; + +public final class FooRepositoryFactory { + + @Getter + private static final FooRepository FOO_REPOSITORY = new FooRepository(); + +} diff --git a/test/native/src/test/resources/script/demo.sh b/test/native/src/test/resources/script/demo.sh new file mode 100644 index 0000000000..a3f5b00278 --- /dev/null +++ b/test/native/src/test/resources/script/demo.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# shellcheck disable=SC2048 +# shellcheck disable=SC2086 +echo Sharding Context: $* diff --git a/test/pom.xml b/test/pom.xml index 5c11d880af..4d6d5e326f 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -30,5 +30,6 @@ e2e util + native