Configure individual timeouts for specific shutdown phases
Closes gh-32985
This commit is contained in:
parent
b7e4fa06c3
commit
457bf9416c
|
@ -106,6 +106,8 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
||||||
|
|
||||||
private final Log logger = LogFactory.getLog(getClass());
|
private final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
|
private final Map<Integer, Long> timeoutsForShutdownPhases = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private volatile long timeoutPerShutdownPhase = 10000;
|
private volatile long timeoutPerShutdownPhase = 10000;
|
||||||
|
|
||||||
private volatile boolean running;
|
private volatile boolean running;
|
||||||
|
@ -132,6 +134,37 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the maximum time allotted for the shutdown of each given phase
|
||||||
|
* (group of {@link SmartLifecycle} beans with the same 'phase' value).
|
||||||
|
* <p>In case of no specific timeout configured, the default timeout per
|
||||||
|
* shutdown phase will apply: 10000 milliseconds (10 seconds) as of 6.2.
|
||||||
|
* @param timeoutsForShutdownPhases a map of phase values (matching
|
||||||
|
* {@link SmartLifecycle#getPhase()}) and corresponding timeout values
|
||||||
|
* (in milliseconds)
|
||||||
|
* @since 6.2
|
||||||
|
* @see SmartLifecycle#getPhase()
|
||||||
|
* @see #setTimeoutPerShutdownPhase
|
||||||
|
*/
|
||||||
|
public void setTimeoutsForShutdownPhases(Map<Integer, Long> timeoutsForShutdownPhases) {
|
||||||
|
this.timeoutsForShutdownPhases.putAll(timeoutsForShutdownPhases);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the maximum time allotted for the shutdown of a specific phase
|
||||||
|
* (group of {@link SmartLifecycle} beans with the same 'phase' value).
|
||||||
|
* <p>In case of no specific timeout configured, the default timeout per
|
||||||
|
* shutdown phase will apply: 10000 milliseconds (10 seconds) as of 6.2.
|
||||||
|
* @param phase the phase value (matching {@link SmartLifecycle#getPhase()})
|
||||||
|
* @param timeout the corresponding timeout value (in milliseconds)
|
||||||
|
* @since 6.2
|
||||||
|
* @see SmartLifecycle#getPhase()
|
||||||
|
* @see #setTimeoutPerShutdownPhase
|
||||||
|
*/
|
||||||
|
public void setTimeoutForShutdownPhase(int phase, long timeout) {
|
||||||
|
this.timeoutsForShutdownPhases.put(phase, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the maximum time allotted in milliseconds for the shutdown of any
|
* Specify the maximum time allotted in milliseconds for the shutdown of any
|
||||||
* phase (group of {@link SmartLifecycle} beans with the same 'phase' value).
|
* phase (group of {@link SmartLifecycle} beans with the same 'phase' value).
|
||||||
|
@ -142,6 +175,11 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
||||||
this.timeoutPerShutdownPhase = timeoutPerShutdownPhase;
|
this.timeoutPerShutdownPhase = timeoutPerShutdownPhase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long determineTimeout(int phase) {
|
||||||
|
Long timeout = this.timeoutsForShutdownPhases.get(phase);
|
||||||
|
return (timeout != null ? timeout : this.timeoutPerShutdownPhase);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBeanFactory(BeanFactory beanFactory) {
|
public void setBeanFactory(BeanFactory beanFactory) {
|
||||||
if (!(beanFactory instanceof ConfigurableListableBeanFactory clbf)) {
|
if (!(beanFactory instanceof ConfigurableListableBeanFactory clbf)) {
|
||||||
|
@ -250,13 +288,13 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
||||||
|
|
||||||
lifecycleBeans.forEach((beanName, bean) -> {
|
lifecycleBeans.forEach((beanName, bean) -> {
|
||||||
if (!autoStartupOnly || isAutoStartupCandidate(beanName, bean)) {
|
if (!autoStartupOnly || isAutoStartupCandidate(beanName, bean)) {
|
||||||
int phase = getPhase(bean);
|
int startupPhase = getPhase(bean);
|
||||||
phases.computeIfAbsent(
|
phases.computeIfAbsent(startupPhase,
|
||||||
phase,
|
phase -> new LifecycleGroup(phase, determineTimeout(phase), lifecycleBeans, autoStartupOnly)
|
||||||
p -> new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)
|
|
||||||
).add(beanName, bean);
|
).add(beanName, bean);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!phases.isEmpty()) {
|
if (!phases.isEmpty()) {
|
||||||
phases.values().forEach(LifecycleGroup::start);
|
phases.values().forEach(LifecycleGroup::start);
|
||||||
}
|
}
|
||||||
|
@ -307,13 +345,14 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
||||||
private void stopBeans() {
|
private void stopBeans() {
|
||||||
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
|
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
|
||||||
Map<Integer, LifecycleGroup> phases = new TreeMap<>(Comparator.reverseOrder());
|
Map<Integer, LifecycleGroup> phases = new TreeMap<>(Comparator.reverseOrder());
|
||||||
|
|
||||||
lifecycleBeans.forEach((beanName, bean) -> {
|
lifecycleBeans.forEach((beanName, bean) -> {
|
||||||
int shutdownPhase = getPhase(bean);
|
int shutdownPhase = getPhase(bean);
|
||||||
phases.computeIfAbsent(
|
phases.computeIfAbsent(shutdownPhase,
|
||||||
shutdownPhase,
|
phase -> new LifecycleGroup(phase, determineTimeout(phase), lifecycleBeans, false)
|
||||||
p -> new LifecycleGroup(shutdownPhase, this.timeoutPerShutdownPhase, lifecycleBeans, false)
|
|
||||||
).add(beanName, bean);
|
).add(beanName, bean);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!phases.isEmpty()) {
|
if (!phases.isEmpty()) {
|
||||||
phases.values().forEach(LifecycleGroup::stop);
|
phases.values().forEach(LifecycleGroup::stop);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue