Skip to content

Commit

Permalink
Support phase-based job shutdown (graceful shutdown, aggressive grace…
Browse files Browse the repository at this point in the history
…ful shutdown, forced shutdown) to shut down gracefully and promptly
  • Loading branch information
JamesChenX committed Aug 10, 2024
1 parent 0870aab commit b61b89c
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ public class TurmsApplicationContext {
private final String activeEnvProfile;
private final BuildProperties buildProperties;

private long shutdownJobTimeoutMillis;
private long shutdownJobGracefulTimeoutMillis;
private long shutdownJobForcedTimeoutMillis;
private final TreeMap<JobShutdownOrder, ShutdownHook> shutdownHooks = new TreeMap<>();

public TurmsApplicationContext(Environment environment) {
Expand Down Expand Up @@ -175,7 +176,9 @@ public void handleContextRefreshedEvent(ContextRefreshedEvent event) {
.getBean(TurmsPropertiesManager.class);
ShutdownProperties properties = propertiesManager.getLocalProperties()
.getShutdown();
shutdownJobTimeoutMillis = properties.getJobTimeoutMillis();
shutdownJobGracefulTimeoutMillis = properties.getJobGracefulTimeoutMillis();
shutdownJobForcedTimeoutMillis =
Math.max(properties.getJobForcedTimeoutMillis(), shutdownJobGracefulTimeoutMillis);
}

@EventListener(classes = ContextClosedEvent.class)
Expand All @@ -188,18 +191,18 @@ public void handleContextClosedEvent() {
String jobName = key.name();
boolean isClosingLogProcessor = key == JobShutdownOrder.CLOSE_LOG_PROCESSOR;
Future<Mono<Void>> shutdownFuture = executor.submit(() -> orderAndJob.getValue()
.run(shutdownJobTimeoutMillis));
.run(shutdownJobGracefulTimeoutMillis));
try {
long time = System.currentTimeMillis();
Mono<Void> mono =
shutdownFuture.get(shutdownJobTimeoutMillis, TimeUnit.MILLISECONDS);
shutdownFuture.get(shutdownJobForcedTimeoutMillis, TimeUnit.MILLISECONDS);
if (mono == null) {
throw new IllegalArgumentException(
"The result of the job \""
+ jobName
+ "\" must not be null");
}
time = shutdownJobTimeoutMillis - (System.currentTimeMillis() - time);
time = shutdownJobForcedTimeoutMillis - (System.currentTimeMillis() - time);
if (time <= 0) {
throw new TimeoutException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,15 @@
@NoArgsConstructor
public class ShutdownProperties {

@Description("Wait for a job 2 minutes at most for extreme cases by default. "
+ "Though it is a long time, graceful shutdown is usually better than force shutdown.")
@Description("The graceful shutdown timeout in milliseconds. After the timeout, the job will try to shut down gracefully in a more aggressive way "
+ "before being forced to be shutdown when reaching \"jobForcedTimeoutMillis\"")
@Min(0)
private long jobTimeoutMillis = 120 * 1000;
private long jobGracefulTimeoutMillis = 60 * 1000;

@Description("The forced shutdown timeout in milliseconds. After the timeout, the job will be forced to be shutdown immediately no matter "
+ "whether it is running or not. If this value is equal to or less than \"jobGracefulTimeoutMillis\", the job will be forced to be shutdown when "
+ "reaching \"jobGracefulTimeoutMillis\"")
@Min(0)
private long jobForcedTimeoutMillis = 90 * 1000;

}
Original file line number Diff line number Diff line change
Expand Up @@ -2474,10 +2474,14 @@ turms:
# mutable property: true
ignore-unknown-settings-on-upsert: false
shutdown:
# Wait for a job 2 minutes at most for extreme cases by default. Though it is a long time, graceful shutdown is usually better than force shutdown.
# The forced shutdown timeout in milliseconds. After the timeout, the job will be forced to be shutdown immediately no matter whether it is running or not. If this value is equal to or less than "jobGracefulTimeoutMillis", the job will be forced to be shutdown when reaching "jobGracefulTimeoutMillis".
# global property: false
# mutable property: false
job-timeout-millis: 120000
job-forced-timeout-millis: 90000
# The graceful shutdown timeout in milliseconds. After the timeout, the job will try to shut down gracefully in a more aggressive way before being forced to be shutdown when reaching "jobForcedTimeoutMillis".
# global property: false
# mutable property: false
job-graceful-timeout-millis: 60000
user-status:
# Whether to cache the user sessions status.
# global property: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4528,7 +4528,7 @@
"type": "boolean",
"value": false
},
"roleId": {
"roleIds": {
"deprecated": false,
"global": false,
"mutable": false,
Expand Down Expand Up @@ -6189,14 +6189,23 @@
}
},
"shutdown": {
"jobTimeoutMillis": {
"jobForcedTimeoutMillis": {
"deprecated": false,
"description": "Wait for a job 2 minutes at most for extreme cases by default. Though it is a long time, graceful shutdown is usually better than force shutdown.",
"description": "The forced shutdown timeout in milliseconds. After the timeout, the job will be forced to be shutdown immediately no matter whether it is running or not. If this value is equal to or less than \"jobGracefulTimeoutMillis\", the job will be forced to be shutdown when reaching \"jobGracefulTimeoutMillis\"",
"global": false,
"mutable": false,
"sensitive": false,
"type": "long",
"value": 120000
"value": 90000
},
"jobGracefulTimeoutMillis": {
"deprecated": false,
"description": "The graceful shutdown timeout in milliseconds. After the timeout, the job will try to shut down gracefully in a more aggressive way before being forced to be shutdown when reaching \"jobForcedTimeoutMillis\"",
"global": false,
"mutable": false,
"sensitive": false,
"type": "long",
"value": 60000
}
},
"userStatus": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3972,7 +3972,7 @@
"sensitive": false,
"type": "boolean"
},
"roleId": {
"roleIds": {
"deprecated": false,
"global": false,
"mutable": false,
Expand Down Expand Up @@ -5435,9 +5435,17 @@
}
},
"shutdown": {
"jobTimeoutMillis": {
"jobForcedTimeoutMillis": {
"deprecated": false,
"description": "Wait for a job 2 minutes at most for extreme cases by default. Though it is a long time, graceful shutdown is usually better than force shutdown.",
"description": "The forced shutdown timeout in milliseconds. After the timeout, the job will be forced to be shutdown immediately no matter whether it is running or not. If this value is equal to or less than \"jobGracefulTimeoutMillis\", the job will be forced to be shutdown when reaching \"jobGracefulTimeoutMillis\"",
"global": false,
"mutable": false,
"sensitive": false,
"type": "long"
},
"jobGracefulTimeoutMillis": {
"deprecated": false,
"description": "The graceful shutdown timeout in milliseconds. After the timeout, the job will try to shut down gracefully in a more aggressive way before being forced to be shutdown when reaching \"jobForcedTimeoutMillis\"",
"global": false,
"mutable": false,
"sensitive": false,
Expand Down

0 comments on commit b61b89c

Please sign in to comment.