-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1246 from amergey/main
prevent mssqlserver deadlock
- Loading branch information
Showing
5 changed files
with
278 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
quartz/src/test/java/org/quartz/impl/jdbcjobstore/JdbcQuartzMSSQLUtilities.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* Copyright Super iPaaS Integration LLC, an IBM Company 2024 | ||
* | ||
* Licensed 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.quartz.impl.jdbcjobstore; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.InputStreamReader; | ||
import java.sql.Connection; | ||
import java.sql.SQLException; | ||
import java.sql.Statement; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import org.testcontainers.containers.MSSQLServerContainer; | ||
|
||
/** | ||
* A utility class to create a database for Quartz MSSQL test. | ||
* | ||
* @author Arnaud Mergey | ||
*/ | ||
|
||
public final class JdbcQuartzMSSQLUtilities { | ||
private static final List<String> DATABASE_SETUP_STATEMENTS; | ||
static { | ||
List<String> setup = new ArrayList<String>(); | ||
String setupScript; | ||
try { | ||
InputStream setupStream = MSSQLDelegate.class.getClassLoader() | ||
.getResourceAsStream("org/quartz/impl/jdbcjobstore/tables_sqlServer.sql"); | ||
try { | ||
BufferedReader r = new BufferedReader(new InputStreamReader(setupStream, "US-ASCII")); | ||
StringBuilder sb = new StringBuilder(); | ||
while (true) { | ||
String line = r.readLine(); | ||
if (line == null) { | ||
break; | ||
} else if (!line.startsWith("--")) { | ||
sb.append(line.replace("GO", ";").replace("[enter_db_name_here]", "[master]")).append("\n"); | ||
} | ||
} | ||
setupScript = sb.toString(); | ||
} finally { | ||
setupStream.close(); | ||
} | ||
} catch (IOException e) { | ||
throw new AssertionError(e); | ||
} | ||
for (String command : setupScript.split(";")) { | ||
if (!command.matches("\\s*")) { | ||
setup.add(command); | ||
} | ||
} | ||
DATABASE_SETUP_STATEMENTS = setup; | ||
} | ||
|
||
public static void createDatabase(MSSQLServerContainer<?> container) throws SQLException { | ||
Connection conn = container.createConnection(""); | ||
try { | ||
Statement statement = conn.createStatement(); | ||
for (String command : DATABASE_SETUP_STATEMENTS) { | ||
statement.addBatch(command); | ||
} | ||
statement.executeBatch(); | ||
} finally { | ||
conn.close(); | ||
} | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
quartz/src/test/java/org/quartz/integrations/tests/QuartzMSSQLDatabaseCronTriggerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* Copyright Super iPaaS Integration LLC, an IBM Company 2024 | ||
* | ||
* Licensed 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.quartz.integrations.tests; | ||
import java.util.Collections; | ||
|
||
import java.util.LinkedList; | ||
import java.util.List; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
import org.junit.jupiter.api.Test; | ||
import org.quartz.*; | ||
|
||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.hamcrest.collection.IsCollectionWithSize.hasSize; | ||
import static org.hamcrest.core.Is.is; | ||
import static org.hamcrest.number.OrderingComparison.greaterThanOrEqualTo; | ||
import static org.quartz.integrations.tests.TrackingJob.SCHEDULED_TIMES_KEY; | ||
/** | ||
* A integration test for Quartz MSSQL Database Scheduler with Cron Trigger. | ||
* | ||
* @author Arnaud Mergey | ||
*/ | ||
public class QuartzMSSQLDatabaseCronTriggerTest extends QuartzMSSQLTestSupport { | ||
@Test | ||
void testCronRepeatCount() throws Exception { | ||
CronTrigger trigger = TriggerBuilder.newTrigger() | ||
.withIdentity("test") | ||
.withSchedule(CronScheduleBuilder.cronSchedule("* * * * * ?")) | ||
.build(); | ||
List<Long> scheduledTimes = Collections.synchronizedList(new LinkedList<Long>()); | ||
scheduler.getContext().put(SCHEDULED_TIMES_KEY, scheduledTimes); | ||
JobDetail jobDetail = JobBuilder.newJob(TrackingJob.class).withIdentity("test").build(); | ||
scheduler.scheduleJob(jobDetail, trigger); | ||
|
||
for (int i = 0; i < 20 && scheduledTimes.size() < 3; i++) { | ||
Thread.sleep(500); | ||
} | ||
assertThat(scheduledTimes, hasSize(greaterThanOrEqualTo(3))); | ||
|
||
Long[] times = scheduledTimes.toArray(new Long[scheduledTimes.size()]); | ||
long baseline = times[0]; | ||
assertThat(baseline % 1000, is(0L)); | ||
for (int i = 1; i < times.length; i++) { | ||
assertThat(times[i], is(baseline + TimeUnit.SECONDS.toMillis(i))); | ||
} | ||
} | ||
} |
86 changes: 86 additions & 0 deletions
86
quartz/src/test/java/org/quartz/integrations/tests/QuartzMSSQLTestSupport.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/* | ||
* Copyright Super iPaaS Integration LLC, an IBM Company 2024 | ||
* | ||
* Licensed 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.quartz.integrations.tests; | ||
|
||
import java.sql.SQLException; | ||
import java.util.Properties; | ||
import org.junit.jupiter.api.AfterAll; | ||
import org.junit.jupiter.api.BeforeAll; | ||
import org.quartz.impl.jdbcjobstore.JdbcQuartzMSSQLUtilities; | ||
import org.quartz.impl.jdbcjobstore.MSSQLDelegate; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.testcontainers.containers.MSSQLServerContainer; | ||
import org.testcontainers.utility.DockerImageName; | ||
|
||
/** | ||
* A base class to support database (MSSQL) scheduler integration testing. Each | ||
* test will have a fresh scheduler created and started, and it will auto | ||
* shutdown upon each test run. The database will be created with schema before | ||
* class and destroy after class test. | ||
* | ||
* @author Arnaud Mergey | ||
*/ | ||
public class QuartzMSSQLTestSupport extends QuartzMemoryTestSupport { | ||
protected static final Logger LOG = LoggerFactory.getLogger(QuartzMSSQLTestSupport.class); | ||
static MSSQLServerContainer<?> mssqlserver = new MSSQLServerContainer( | ||
DockerImageName.parse(MSSQLServerContainer.IMAGE).withTag("latest")).acceptLicense(); | ||
|
||
@BeforeAll | ||
public static void initialize() throws Exception { | ||
LOG.info("Starting MSSQL database."); | ||
mssqlserver.start(); | ||
LOG.info("Database started."); | ||
try { | ||
LOG.info("Creating Database tables for Quartz."); | ||
JdbcQuartzMSSQLUtilities.createDatabase(mssqlserver); | ||
LOG.info("Database tables created."); | ||
} catch (SQLException e) { | ||
throw new Exception("Failed to create Quartz tables.", e); | ||
} | ||
} | ||
|
||
@AfterAll | ||
public static void shutdownDb() throws Exception { | ||
mssqlserver.stop(); | ||
LOG.info("Database shutdown."); | ||
} | ||
|
||
protected Properties createSchedulerProperties() { | ||
Properties properties = new Properties(); | ||
properties.put("org.quartz.scheduler.instanceName", "TestScheduler"); | ||
properties.put("org.quartz.scheduler.instanceId", "AUTO"); | ||
properties.put("org.quartz.scheduler.skipUpdateCheck", "true"); | ||
properties.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); | ||
properties.put("org.quartz.threadPool.threadCount", "12"); | ||
properties.put("org.quartz.threadPool.threadPriority", "5"); | ||
properties.put("org.quartz.jobStore.misfireThreshold", "10000"); | ||
properties.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX"); | ||
properties.put("org.quartz.jobStore.driverDelegateClass", MSSQLDelegate.class.getName()); | ||
properties.put("org.quartz.jobStore.useProperties", "true"); | ||
properties.put("org.quartz.jobStore.dataSource", "myDS"); | ||
properties.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); | ||
properties.put("org.quartz.jobStore.isClustered", "false"); | ||
properties.put("org.quartz.dataSource.myDS.driver", mssqlserver.getDriverClassName()); | ||
properties.put("org.quartz.dataSource.myDS.URL", mssqlserver.getJdbcUrl()); | ||
properties.put("org.quartz.dataSource.myDS.user", mssqlserver.getUsername()); | ||
properties.put("org.quartz.dataSource.myDS.password", mssqlserver.getPassword()); | ||
properties.put("org.quartz.dataSource.myDS.maxConnections", "5"); | ||
properties.put("org.quartz.dataSource.myDS.provider", "hikaricp"); | ||
return properties; | ||
} | ||
} |