Skip to content

Commit

Permalink
♻️ executor shutdown quickly #283
Browse files Browse the repository at this point in the history
  • Loading branch information
trydofor committed Aug 5, 2024
1 parent 9e63d82 commit 5777f09
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 19 deletions.
2 changes: 1 addition & 1 deletion observe/docs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ wings.tiny.mail.service.only-run=true
## TaskSchedulingProperties
wings.tiny.mail.service.scheduler.pool.size=2
wings.tiny.mail.service.scheduler.shutdown.await-termination=true
wings.tiny.mail.service.scheduler.shutdown.await-termination-period=60s
wings.tiny.mail.service.scheduler.shutdown.await-termination-period=15s
wings.tiny.mail.service.scheduler.thread-name-prefix=mail-
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jooq.Field;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.PeriodicTrigger;
Expand Down Expand Up @@ -72,7 +73,7 @@
@Service
@ConditionalWingsEnabled
@Slf4j
public class TinyTaskExecServiceImpl implements TinyTaskExecService, InitializingBean, DisposableBean {
public class TinyTaskExecServiceImpl implements TinyTaskExecService, InitializingBean {

protected static final ConcurrentHashMap<Long, ScheduledFuture<?>> Handle = new ConcurrentHashMap<>();
protected static final ConcurrentHashMap<Long, Boolean> Cancel = new ConcurrentHashMap<>();
Expand All @@ -99,16 +100,20 @@ public class TinyTaskExecServiceImpl implements TinyTaskExecService, Initializin
@Setter(onMethod_ = { @Autowired })
protected TinyTaskExecProp execProp;

protected volatile boolean isShutdown = false;
protected volatile boolean isShutdownFast = false;
protected volatile boolean isShutdownSlow = false;

@Override
public void afterPropertiesSet() {
isShutdown = false;
isShutdownFast = false;
isShutdownSlow = false;
}

@Override
@EventListener(ContextClosedEvent.class)
public void destroy() {
isShutdown = true;
log.info("tiny-task shutdown for ContextClosedEvent");
isShutdownFast = true;
isShutdownSlow = true;
for (var en : Handle.entrySet()) {
var task = en.getValue();
if (task.isDone()) continue;
Expand All @@ -126,19 +131,31 @@ public boolean launch(long id) {

@Override
public boolean force(long id) {
if (isShutdown) {
log.warn("skip tiny-task for shutdwon, force id={}", id);
if (isShutdownFast && isShutdownSlow) {
log.warn("cancel tiny-task for shutdown all on force, id={}", id);
return false;
}

final WinTaskDefine td = winTaskDefineDao.fetchOneById(id);
if (td == null) {
log.info("skip tiny-task for not found, id={}", id);
log.info("skip tiny-task for not found on force, id={}", id);
return false;
}

final boolean fast = BoxedCastUtil.orTrue(td.getTaskerFast());
if (fast && isShutdownFast || !fast && isShutdownSlow) {
log.warn("cancal tiny-task for shutdown on force, fast={}, id={}", fast, id);
return false;
}

final var scheduler = fast ? TaskSchedulerHelper.Fast() : TaskSchedulerHelper.Scheduled();
if (scheduler.getScheduledExecutor().isShutdown()) {
log.warn("cancal tiny-task for Executor shutdown on force, fast={}, id={}", fast, id);
if (fast) isShutdownFast = true;
else isShutdownSlow = true;
return false;
}

scheduler.schedule(() -> {
long execTms = ThreadNow.millis();
long doneTms = -1;
Expand Down Expand Up @@ -190,6 +207,7 @@ public boolean force(long id) {
}
}
}, Instant.ofEpochMilli(ThreadNow.millis()));

return true;
}

Expand Down Expand Up @@ -220,22 +238,22 @@ public Set<Long> running() {
}

private boolean relaunch(long id) {
if (isShutdown) {
log.warn("skip tiny-task for shutdwon, relaunch id={}", id);
if (isShutdownFast && isShutdownSlow) {
log.warn("cancel tiny-task for shutdown all on relaunch, id={}", id);
return false;
}

final Lock lock = JvmStaticGlobalLock.get(id);
try {
lock.lock();
if (Handle.containsKey(id)) {
log.info("skip tiny-task for launching, id={}", id);
log.info("skip tiny-task on launching, id={}", id);
return false;
}

final WinTaskDefine td = winTaskDefineDao.fetchOneById(id);
if (td == null) {
log.info("skip tiny-task for not found, relaunch id={}", id);
log.info("skip tiny-task for not found on relaunch id={}", id);
return false;
}

Expand All @@ -253,15 +271,21 @@ private boolean relaunch(long id) {
saveNextExec(next, td);

final boolean fast = BoxedCastUtil.orTrue(td.getTaskerFast());
final var taskScheduler = fast ? TaskSchedulerHelper.Fast() : TaskSchedulerHelper.Scheduled();
if (fast && isShutdownFast || !fast && isShutdownSlow) {
log.warn("cancal tiny-task for shutdown on relaunch, fast={}, id={}", fast, id);
return false;
}

if (taskScheduler.getScheduledExecutor().isShutdown()) {
log.error("TaskScheduler={} is shutdown, id={}, prop={}", fast, id, key);
final var scheduler = fast ? TaskSchedulerHelper.Fast() : TaskSchedulerHelper.Scheduled();
if (scheduler.getScheduledExecutor().isShutdown()) {
log.warn("cancal tiny-task for Executor shutdown on relaunch, fast={}, id={}, prop={}", fast, id, key);
if (fast) isShutdownFast = true;
else isShutdownSlow = true;
return false;
}

log.info("prepare tiny-task id={}, prop={}", id, key);
final ScheduledFuture<?> handle = taskScheduler.schedule(() -> {
final ScheduledFuture<?> handle = scheduler.schedule(() -> {
long execTms = ThreadNow.millis();
try {
if (notNextLock(td, execTms)) {
Expand Down

0 comments on commit 5777f09

Please sign in to comment.