Skip to content

Commit

Permalink
feat(quartz): add clustered jobs support
Browse files Browse the repository at this point in the history
  • Loading branch information
machi1990 committed Nov 22, 2019
1 parent 18ea1cc commit 25cbd16
Show file tree
Hide file tree
Showing 30 changed files with 1,105 additions and 179 deletions.
5 changes: 5 additions & 0 deletions bom/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@
<artifactId>quarkus-agroal-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-agroal-spi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-artemis-core</artifactId>
Expand Down
1 change: 1 addition & 0 deletions ci-templates/stages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ stages:
modules:
- kogito
- kubernetes-client
- quartz
name: misc_3

- template: native-build-steps.yaml
Expand Down
4 changes: 4 additions & 0 deletions extensions/agroal/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-agroal</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-agroal-spi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-narayana-jta-deployment</artifactId>
Expand Down
1 change: 1 addition & 0 deletions extensions/agroal/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<name>Quarkus - Agroal</name>
<packaging>pom</packaging>
<modules>
<module>spi</module>
<module>deployment</module>
<module>runtime</module>
</modules>
Expand Down
23 changes: 23 additions & 0 deletions extensions/agroal/spi/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-agroal-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-agroal-spi</artifactId>
<name>Quarkus - Agroal - SPI</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core-deployment</artifactId>
</dependency>
</dependencies>

</project>
104 changes: 54 additions & 50 deletions extensions/quartz/deployment/pom.xml
Original file line number Diff line number Diff line change
@@ -1,58 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-quartz-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-quartz-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>

<modelVersion>4.0.0</modelVersion>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-quartz-deployment</artifactId>
<name>Quarkus - Scheduler Quartz - Deployment</name>
<artifactId>quarkus-quartz-deployment</artifactId>
<name>Quarkus - Quartz - Deployment</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-scheduler-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-quartz</artifactId>
</dependency>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-scheduler-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-agroal-spi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-quartz</artifactId>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.quarkus.quartz.deployment;

import java.util.Optional;

import io.quarkus.builder.item.SimpleBuildItem;

/**
* Holds the SQL driver dialect {@link org.quartz.impl.jdbcjobstore.StdJDBCDelegate driver delegate} to use.
*/
final class QuartzJDBCDriverDialectBuildItem extends SimpleBuildItem {
private final Optional<String> driver;

public QuartzJDBCDriverDialectBuildItem(Optional<String> driver) {
this.driver = driver;
}

public Optional<String> getDriver() {
return driver;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,27 @@

import static io.quarkus.deployment.annotations.ExecutionTime.RUNTIME_INIT;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.quartz.core.QuartzSchedulerThread;
import org.quartz.core.SchedulerSignalerImpl;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.jdbcjobstore.AttributeRestoringConnectionInvocationHandler;
import org.quartz.impl.jdbcjobstore.HSQLDBDelegate;
import org.quartz.impl.jdbcjobstore.JobStoreSupport;
import org.quartz.impl.jdbcjobstore.MSSQLDelegate;
import org.quartz.impl.jdbcjobstore.PostgreSQLDelegate;
import org.quartz.impl.jdbcjobstore.StdJDBCDelegate;
import org.quartz.impl.triggers.AbstractTrigger;
import org.quartz.impl.triggers.SimpleTriggerImpl;
import org.quartz.simpl.CascadingClassLoadHelper;
import org.quartz.simpl.RAMJobStore;
import org.quartz.simpl.SimpleInstanceIdGenerator;
import org.quartz.simpl.SimpleThreadPool;

import io.quarkus.agroal.deployment.DataSourceDriverBuildItem;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.arc.deployment.BeanContainerBuildItem;
import io.quarkus.deployment.Capabilities;
Expand All @@ -17,18 +31,22 @@
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.CapabilityBuildItem;
import io.quarkus.deployment.builditem.ServiceStartBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageProxyDefinitionBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.configuration.ConfigurationError;
import io.quarkus.deployment.logging.LogCleanupFilterBuildItem;
import io.quarkus.quartz.runtime.QuarkusQuartzConnectionPoolProvider;
import io.quarkus.quartz.runtime.QuartzBuildTimeConfig;
import io.quarkus.quartz.runtime.QuartzRecorder;
import io.quarkus.quartz.runtime.QuartzRuntimeConfig;
import io.quarkus.quartz.runtime.QuartzRunTimeConfig;
import io.quarkus.quartz.runtime.QuartzScheduler;
import io.quarkus.quartz.runtime.QuartzSupport;
import io.quarkus.quartz.runtime.StoreType;

/**
* @author Martin Kouba
*/
public class QuartzProcessor {

@BuildStep
CapabilityBuildItem capability() {
return new CapabilityBuildItem(Capabilities.QUARTZ);
Expand All @@ -40,41 +58,118 @@ AdditionalBeanBuildItem beans() {
}

@BuildStep
List<ReflectiveClassBuildItem> reflectiveClasses() {
NativeImageProxyDefinitionBuildItem connectionProxy(QuartzBuildTimeConfig config) {
if (config.storeType.equals(StoreType.DB)) {
return new NativeImageProxyDefinitionBuildItem(Connection.class.getName());
}
return null;
}

@BuildStep
QuartzJDBCDriverDialectBuildItem driver(Optional<DataSourceDriverBuildItem> dataSourceDriver,
QuartzBuildTimeConfig config) {
if (config.storeType == StoreType.RAM) {
if (config.clustered) {
throw new ConfigurationError("Clustered jobs configured with unsupported job store option");
}

return new QuartzJDBCDriverDialectBuildItem(Optional.empty());
}

if (!dataSourceDriver.isPresent()) {
String message = String.format(
"JDBC Store configured but '%s' datasource is not configured properly. You can configure your datasource by following the guide available at: https://quarkus.io/guides/datasource-guide",
config.dataSourceName.isPresent() ? config.dataSourceName.get() : "default");
throw new ConfigurationError(message);
}

return new QuartzJDBCDriverDialectBuildItem(Optional.of(guessDriver(dataSourceDriver)));
}

private String guessDriver(Optional<DataSourceDriverBuildItem> dataSourceDriver) {
if (!dataSourceDriver.isPresent()) {
return StdJDBCDelegate.class.getName();
}

String resolvedDriver = dataSourceDriver.get().getDriver();
if (resolvedDriver.contains("postgresql")) {
return PostgreSQLDelegate.class.getName();
}
if (resolvedDriver.contains("org.h2.Driver")) {
return HSQLDBDelegate.class.getName();
}

if (resolvedDriver.contains("com.microsoft.sqlserver.jdbc.SQLServerResource")) {
return MSSQLDelegate.class.getName();
}

return StdJDBCDelegate.class.getName();

}

@BuildStep
List<ReflectiveClassBuildItem> reflectiveClasses(QuartzBuildTimeConfig config,
QuartzJDBCDriverDialectBuildItem driverDialect) {
List<ReflectiveClassBuildItem> reflectiveClasses = new ArrayList<>();
reflectiveClasses.add(new ReflectiveClassBuildItem(false, false, CascadingClassLoadHelper.class.getName()));
StoreType storeType = config.storeType;

reflectiveClasses.add(new ReflectiveClassBuildItem(true, false, SimpleThreadPool.class.getName()));
reflectiveClasses.add(new ReflectiveClassBuildItem(true, false, RAMJobStore.class.getName()));
reflectiveClasses.add(new ReflectiveClassBuildItem(true, false, SimpleInstanceIdGenerator.class.getName()));
reflectiveClasses.add(new ReflectiveClassBuildItem(false, false, CascadingClassLoadHelper.class.getName()));
reflectiveClasses.add(new ReflectiveClassBuildItem(true, true, storeType.clazz));

if (storeType.equals(StoreType.DB)) {
reflectiveClasses.add(new ReflectiveClassBuildItem(true, false, JobStoreSupport.class.getName()));
reflectiveClasses.add(new ReflectiveClassBuildItem(true, true, Connection.class.getName()));
reflectiveClasses.add(new ReflectiveClassBuildItem(true, false, AbstractTrigger.class.getName()));
reflectiveClasses.add(new ReflectiveClassBuildItem(true, false, SimpleTriggerImpl.class.getName()));
reflectiveClasses.add(new ReflectiveClassBuildItem(true, false, driverDialect.getDriver().get()));
reflectiveClasses
.add(new ReflectiveClassBuildItem(true, true, "io.quarkus.quartz.runtime.QuartzScheduler$InvokerJob"));
reflectiveClasses
.add(new ReflectiveClassBuildItem(true, false, QuarkusQuartzConnectionPoolProvider.class.getName()));
}

return reflectiveClasses;
}

@BuildStep
public void logCleanup(BuildProducer<LogCleanupFilterBuildItem> logCleanupFilter) {
logCleanupFilter.produce(new LogCleanupFilterBuildItem("org.quartz.impl.StdSchedulerFactory",
public List<LogCleanupFilterBuildItem> logCleanup(QuartzBuildTimeConfig config) {
StoreType storeType = config.storeType;
List<LogCleanupFilterBuildItem> logCleanUps = new ArrayList<>();
logCleanUps.add(new LogCleanupFilterBuildItem(StdSchedulerFactory.class.getName(),
"Quartz scheduler version:",
"Using default implementation for",
"Quartz scheduler 'QuarkusQuartzScheduler'"));

logCleanupFilter.produce(new LogCleanupFilterBuildItem("org.quartz.core.QuartzScheduler",
logCleanUps.add(new LogCleanupFilterBuildItem(org.quartz.core.QuartzScheduler.class.getName(),
"Quartz Scheduler v",
"JobFactory set to:",
"Scheduler meta-data:",
"Scheduler QuarkusQuartzScheduler"));

logCleanupFilter.produce(new LogCleanupFilterBuildItem("org.quartz.simpl.RAMJobStore",
"RAMJobStore initialized."));

logCleanupFilter.produce(new LogCleanupFilterBuildItem("org.quartz.core.SchedulerSignalerImpl",
logCleanUps.add(new LogCleanupFilterBuildItem(storeType.clazz, storeType.name + " initialized.", "Handling",
"Using db table-based data access locking", "JDBCJobStore threads will inherit ContextClassLoader of thread",
"Couldn't rollback jdbc connection", "Database connection shutdown unsuccessful"));
logCleanUps.add(new LogCleanupFilterBuildItem(SchedulerSignalerImpl.class.getName(),
"Initialized Scheduler Signaller of type"));
logCleanUps.add(new LogCleanupFilterBuildItem(QuartzSchedulerThread.class.getName(),
"QuartzSchedulerThread Inheriting ContextClassLoader"));
logCleanUps.add(new LogCleanupFilterBuildItem(SimpleThreadPool.class.getName(),
"Job execution threads will use class loader of thread"));

logCleanUps.add(new LogCleanupFilterBuildItem(AttributeRestoringConnectionInvocationHandler.class.getName(),
"Failed restore connection's original"));
return logCleanUps;
}

@BuildStep
@Record(RUNTIME_INIT)
public void build(QuartzRuntimeConfig runtimeConfig, QuartzRecorder recorder, BeanContainerBuildItem beanContainer,
BuildProducer<ServiceStartBuildItem> serviceStart) {
recorder.initialize(runtimeConfig, beanContainer.getValue());
public void build(QuartzRunTimeConfig runTimeConfig, QuartzBuildTimeConfig buildTimeConfig, QuartzRecorder recorder,
BeanContainerBuildItem beanContainer,
BuildProducer<ServiceStartBuildItem> serviceStart, QuartzJDBCDriverDialectBuildItem driverDialect) {
recorder.initialize(runTimeConfig, buildTimeConfig, beanContainer.getValue(), driverDialect.getDriver());
// Make sure that StartupEvent is fired after the init
serviceStart.produce(new ServiceStartBuildItem("quartz"));
}

}
Loading

0 comments on commit 25cbd16

Please sign in to comment.