-
-
Notifications
You must be signed in to change notification settings - Fork 229
Allow for configurable timeout of the Scheduler. #92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Modify Scheduler to take responsibility for the lifecycle of the job ExecutorService only if it's not externally supplied. - Make the shutdown timeout be externally configurable by the user. - Additional logging for when the Scheduler does not shut down cleanly. - Add bits to the POM that allow for building under Java 9+ - Have the tests use logback instead of slf4-simple for log output
|
Thanks for the contribution! Will try and have a look in the coming days :) |
|
Bit of a busy week, haven't had the time to check this yet |
kagkarlsson
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for contributing to db-scheduler! Looks good, but left a few comments :)
| <configuration> | ||
|
|
||
| <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | ||
| <encoder> | ||
| <pattern>%d{HH:mm:ss.SSS} %highlight(%-5level) %cyan(%logger{50}) - %msg%n%rootException</pattern> | ||
| </encoder> | ||
| </appender> | ||
|
|
||
| <logger level="INFO" name="com.github.kagkarlsson"/> | ||
|
|
||
| <root level="WARN"> | ||
| <appender-ref ref="STDOUT"/> | ||
| </root> | ||
|
|
||
| </configuration> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Was not aware of those options (highlight, cyan), better looking output 👍
| import java.util.*; | ||
| import java.util.concurrent.ExecutorService; | ||
| import java.util.concurrent.Executors; | ||
| import java.util.concurrent.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I see I have a bit of a whitespace issue in the project. I will fix that afterwards, in another PR, to make it more consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(the placement of this comment was probably better before I disabled whitespace changes... )
| // this.dueExecutor = Executors.newSingleThreadExecutor(defaultThreadFactoryWithPrefix(THREAD_PREFIX + "-execute-due-")); | ||
| // this.detectDeadExecutor = Executors.newSingleThreadExecutor(defaultThreadFactoryWithPrefix(THREAD_PREFIX + "-detect-dead-")); | ||
| // this.updateHeartbeatExecutor = Executors.newSingleThreadExecutor(defaultThreadFactoryWithPrefix(THREAD_PREFIX + "-update-heartbeat-")); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be removed
| if(managedExecutorService) { | ||
| LOG.info("Letting running executions finish. Will wait up to {}.", executorShutdownWait); | ||
| if (ExecutorUtils.shutdownAndAwaitTermination(executorService, executorShutdownWait)) { | ||
| LOG.info("Scheduler stopped."); | ||
| } else { | ||
| if(!currentlyProcessing.isEmpty()) { | ||
| String runningJobs = currentlyProcessing.keySet().stream().map(Execution::toString).collect(Collectors.joining("\n")); | ||
| LOG.warn("Scheduler did not shut down within the timeout. Interrupting the following jobs:\n{}", runningJobs); | ||
| } else { | ||
| LOG.warn("Scheduler did not shut down cleanly within the timeout. Terminating the executor."); | ||
| } | ||
| if(!ExecutorUtils.shutdownNowAndAwaitTermination(executorService, Duration.ofSeconds(5))) { | ||
| LOG.warn("Scheduler did not terminate within the timeout. The Scheduler pool may be orphaned and have live threads."); | ||
| } | ||
| if(!currentlyProcessing.isEmpty()) { | ||
| String staleJobs = currentlyProcessing.keySet().stream().map(Execution::toString).collect(Collectors.joining("\n")); | ||
| LOG.warn("Scheduler stopped, but the following jobs were orphaned:\n{}", staleJobs); | ||
| } | ||
| } | ||
| } else { | ||
| LOG.info("Not shutting down externally managed job executor."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indent is a bit messed up. I will probably do a reformat to 4 spaces after this PR is merged.
| return this; | ||
| } | ||
|
|
||
| public SchedulerBuilder executorServiceShutdownTimeout(Duration shutdownTimeout) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about the name. Especially since it is not applicable for the builder-method executorService where you send in the externally managed one.
What about shutdownTimeout?
| new LinkedBlockingQueue<>(), | ||
| defaultThreadFactoryWithPrefix(prefix) | ||
| ); | ||
| executor.allowCoreThreadTimeOut(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, I don't think that the pool will ever be scaled to less than 3 threads? (Since currently all util-threads run until shutdown with their own sleep)
| ThreadPoolExecutor housekeepingExecutor = newThreadPool(THREAD_PREFIX + "-housekeeper-", 3, THREAD_POOL_TIMEOUT); | ||
| this.dueExecutor = housekeepingExecutor; | ||
| this.detectDeadExecutor = housekeepingExecutor; | ||
| this.updateHeartbeatExecutor = housekeepingExecutor; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about this. The util-threads currently run "forever" (internal sleep). The only difference now will be that the thread-names will be a bit less describing. What do you feel is the benefit here?
Maybe they should be made into a ScheduledExecutorService, but I suspect that generates a bigger change..
| public static ThreadFactory defaultThreadFactoryWithPrefix(String prefix, boolean useDaemonThreads) { | ||
| return new PrefixingDefaultThreadFactory(prefix, useDaemonThreads); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't seem to find any references to this method (where daemon=true)? Was there meant to be?
|
Much of these changes have reached master via other PRs. Closing. |
the job ExecutorService only if it's not externally supplied.
This addresses #88