fix(DirectoryWatchSupport): isolate handler failures

This commit is contained in:
2026-04-19 17:31:36 +08:00
parent 137b1ee917
commit eea72c747c
2 changed files with 43 additions and 1 deletions

View File

@@ -157,7 +157,11 @@ public class DirectoryWatchSupport implements Closeable {
if (handler == null) {
continue;
}
handler.handle(thisDir, resolvedContext);
try {
handler.handle(thisDir, resolvedContext);
} catch (Exception e) {
log.error("监听事件处理失败: dir={}, kind={}, context={}", thisDir, kind.name(), resolvedContext, e);
}
}
} catch (InterruptedException e) {
log.info("监听线程被中断,准备退出...");

View File

@@ -11,8 +11,11 @@ import java.nio.file.Path;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BooleanSupplier;
class DirectoryWatchSupportTest {
@@ -115,6 +118,41 @@ class DirectoryWatchSupportTest {
}
}
@Test
void testHandlerExceptionDoesNotStopWatching(@TempDir Path tempDir) throws Exception {
AtomicBoolean shouldThrow = new AtomicBoolean(true);
CountDownLatch goodEventLatch = new CountDownLatch(1);
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
DirectoryWatchSupport watchSupport = new DirectoryWatchSupport(
new DirectoryWatchSupport.Context(tempDir),
executor,
0,
null
)) {
List<String> events = new CopyOnWriteArrayList<>();
watchSupport.onCreate((thisDir, context) -> {
if (context == null || Files.isDirectory(context)) {
return;
}
String relative = tempDir.relativize(context).toString().replace('\\', '/');
if (shouldThrow.getAndSet(false)) {
throw new IllegalStateException("boom");
}
events.add(relative);
goodEventLatch.countDown();
});
watchSupport.start();
Files.writeString(tempDir.resolve("first.txt"), "first");
Files.writeString(tempDir.resolve("second.txt"), "second");
Assertions.assertTrue(goodEventLatch.await(2, TimeUnit.SECONDS));
Assertions.assertEquals(List.of("second.txt"), events);
}
}
private WatchHarness createWatchSupport(Path root, ExecutorService executor, int watchDepth) throws IOException {
DirectoryWatchSupport watchSupport = new DirectoryWatchSupport(new DirectoryWatchSupport.Context(root), executor, watchDepth, null);
List<String> events = new CopyOnWriteArrayList<>();