Code cleanup
This commit is contained in:
parent
5c33456de5
commit
915c50bee6
@ -25,8 +25,11 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
public class ThingsBoardExecutors {
|
public class ThingsBoardExecutors {
|
||||||
|
|
||||||
|
/** Cannot instantiate. */
|
||||||
|
private ThingsBoardExecutors(){}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method forked from ExecutorService to provide thread poll name
|
* Method forked from ExecutorService to provide thread pool name
|
||||||
*
|
*
|
||||||
* Creates a thread pool that maintains enough threads to support
|
* Creates a thread pool that maintains enough threads to support
|
||||||
* the given parallelism level, and may use multiple queues to
|
* the given parallelism level, and may use multiple queues to
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright © 2016-2024 The Thingsboard Authors
|
* Copyright © 2016-2024 The Thingsboard Authors
|
||||||
*
|
* <p>
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
* <p>
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
* <p>
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -17,9 +17,6 @@ package org.thingsboard.common.util;
|
|||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import java.util.concurrent.CancellationException;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
@ -32,67 +29,35 @@ final class ThingsBoardScheduledThreadPoolExecutor extends ScheduledThreadPoolEx
|
|||||||
super(corePoolSize, threadFactory);
|
super(corePoolSize, threadFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void afterExecute(Runnable r, Throwable t) {
|
|
||||||
super.afterExecute(r, t);
|
|
||||||
logExceptionsAfterExecute(r, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void logExceptionsAfterExecute(Runnable r, Throwable directThrowable) {
|
|
||||||
Throwable wrappedThrowable = extractThrowableWrappedInFuture(r);
|
|
||||||
if (wrappedThrowable != null) {
|
|
||||||
if (wrappedThrowable instanceof CancellationException) {
|
|
||||||
log.debug("Task was cancelled.", wrappedThrowable);
|
|
||||||
} else {
|
|
||||||
log.error("Uncaught error occurred during task execution!", wrappedThrowable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (directThrowable != null) { // should never be true since ScheduledThreadPoolExecutor wraps tasks in Future's
|
|
||||||
log.error("Caught direct throwable from task submitted to the scheduled thread pool executor!", directThrowable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Throwable extractThrowableWrappedInFuture(Runnable runnable) {
|
|
||||||
if (runnable instanceof Future<?> future && future.isDone()) {
|
|
||||||
try {
|
|
||||||
future.get();
|
|
||||||
} catch (InterruptedException e) { // should not happen due to isDone() check
|
|
||||||
throw new AssertionError("InterruptedException caught after isDone() check on a future", e);
|
|
||||||
} catch (CancellationException e) {
|
|
||||||
return e;
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
return e.getCause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
|
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
|
||||||
if (command == null) { // preserve the original NPE behavior of ScheduledThreadPoolExecutor with a more helpful message
|
if (command == null) { // preserve the original NPE behavior of ScheduledThreadPoolExecutor with a more helpful message
|
||||||
throw new NullPointerException("command is null");
|
throw new NullPointerException("Command is null");
|
||||||
}
|
}
|
||||||
return super.scheduleAtFixedRate(new SafePeriodicRunnable(command), initialDelay, period, unit);
|
return super.scheduleAtFixedRate(new PeriodicRunnable(command), initialDelay, period, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
|
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
|
||||||
if (command == null) { // preserve the original NPE behavior of ScheduledThreadPoolExecutor with a more helpful message
|
if (command == null) { // preserve the original NPE behavior of ScheduledThreadPoolExecutor with a more helpful message
|
||||||
throw new NullPointerException("command is null");
|
throw new NullPointerException("Command is null");
|
||||||
}
|
}
|
||||||
return super.scheduleWithFixedDelay(new SafePeriodicRunnable(command), initialDelay, delay, unit);
|
return super.scheduleWithFixedDelay(new PeriodicRunnable(command), initialDelay, delay, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private record SafePeriodicRunnable(Runnable runnable) implements Runnable {
|
private record PeriodicRunnable(Runnable runnable) implements Runnable {
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
runnable.run();
|
runnable.run();
|
||||||
} catch (Exception ex) {
|
} catch (Exception e) {
|
||||||
log.error("Uncaught exception occurred during periodic task execution!", ex);
|
// Log exceptions but do not propagate it. This ensures that subsequent scheduled tasks will still run.
|
||||||
|
log.error("Uncaught exception occurred during periodic task execution!", e);
|
||||||
|
} catch (Throwable th) {
|
||||||
|
// Log and rethrow other serious issues that are not regular Exceptions.
|
||||||
|
log.error("Critical exception occurred during periodic task execution!", th);
|
||||||
|
throw th;
|
||||||
}
|
}
|
||||||
// Intentionally, no catch block for Throwable; uncaught Throwables will be handled in afterExecute()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user