refactor(LocalRunnerClient): co-locate watch service builder internals

Context:
Group WatchService build interfaces and registry implementation into a
single internal structure for better cohesion.
This commit is contained in:
2025-12-29 18:40:20 +08:00
parent e3294ec302
commit db3435fccf

View File

@@ -272,118 +272,118 @@ public class LocalRunnerClient extends RunnerClient {
})); }));
} }
private WatchServiceBuild registerWatchService(Path path) { private LocalWatchServiceBuild registerWatchService(Path path) {
return new LocalWatchServiceRegistry(path, watchService, executor); return new LocalWatchServiceBuild.BuildRegistry(path, watchService, executor);
} }
private interface WatchServiceBuild { private interface LocalWatchServiceBuild {
WatchServiceBuild registerCreate(WatchEventHandler handler); LocalWatchServiceBuild registerCreate(EventHandler handler);
WatchServiceBuild registerModify(WatchEventHandler handler); LocalWatchServiceBuild registerModify(EventHandler handler);
WatchServiceBuild registerDelete(WatchEventHandler handler); LocalWatchServiceBuild registerDelete(EventHandler handler);
WatchServiceBuild registerOverflow(WatchEventHandler handler); LocalWatchServiceBuild registerOverflow(EventHandler handler);
WatchServiceBuild initialLoad(WatchInitLoader loader); LocalWatchServiceBuild initialLoad(InitLoader loader);
void commit(); void commit();
}
private interface WatchEventHandler { interface EventHandler {
void handle(Path thisDir, Path context); void handle(Path thisDir, Path context);
}
private interface WatchInitLoader {
void load(Path path);
}
private static class LocalWatchServiceRegistry implements WatchServiceBuild {
private final Map<WatchEvent.Kind<?>, WatchEventHandler> handlers = new HashMap<>();
private final Path path;
private final WatchService watchService;
private final ExecutorService executor;
private WatchInitLoader initLoader;
private LocalWatchServiceRegistry(Path path, WatchService watchService, ExecutorService executor) {
this.path = path;
this.watchService = watchService;
this.executor = executor;
} }
@Override interface InitLoader {
public WatchServiceBuild registerCreate(WatchEventHandler handler) { void load(Path path);
handlers.put(StandardWatchEventKinds.ENTRY_CREATE, handler);
return this;
} }
@Override class BuildRegistry implements LocalWatchServiceBuild {
public WatchServiceBuild registerModify(WatchEventHandler handler) {
handlers.put(StandardWatchEventKinds.ENTRY_MODIFY, handler);
return this;
}
@Override private final Map<WatchEvent.Kind<?>, EventHandler> handlers = new HashMap<>();
public WatchServiceBuild registerDelete(WatchEventHandler handler) { private final Path path;
handlers.put(StandardWatchEventKinds.ENTRY_DELETE, handler); private final WatchService watchService;
return this; private final ExecutorService executor;
} private InitLoader initLoader;
@Override private BuildRegistry(Path path, WatchService watchService, ExecutorService executor) {
public WatchServiceBuild registerOverflow(WatchEventHandler handler) { this.path = path;
handlers.put(StandardWatchEventKinds.OVERFLOW, handler); this.watchService = watchService;
return this; this.executor = executor;
} }
@Override @Override
public WatchServiceBuild initialLoad(WatchInitLoader loader) { public LocalWatchServiceBuild registerCreate(EventHandler handler) {
initLoader = loader; handlers.put(StandardWatchEventKinds.ENTRY_CREATE, handler);
return this; return this;
} }
@Override @Override
public void commit() { public LocalWatchServiceBuild registerModify(EventHandler handler) {
if (initLoader != null) initLoader.load(path); handlers.put(StandardWatchEventKinds.ENTRY_MODIFY, handler);
executor.execute(buildWatchTask()); return this;
} }
private Runnable buildWatchTask() { @Override
return () -> { public LocalWatchServiceBuild registerDelete(EventHandler handler) {
String pathStr = path.toString(); handlers.put(StandardWatchEventKinds.ENTRY_DELETE, handler);
log.info("行动程序目录监听器已启动,监听目录: {}", pathStr); return this;
while (true) { }
WatchKey key;
try { @Override
key = watchService.take(); public LocalWatchServiceBuild registerOverflow(EventHandler handler) {
List<WatchEvent<?>> events = key.pollEvents(); handlers.put(StandardWatchEventKinds.OVERFLOW, handler);
for (WatchEvent<?> e : events) { return this;
WatchEvent.Kind<?> kind = e.kind(); }
Object context = e.context();
log.info("行动程序目录变更事件: {} - {} - {}", pathStr, kind.name(), context); @Override
Path thisDir = (Path) key.watchable(); public LocalWatchServiceBuild initialLoad(InitLoader loader) {
if (!thisDir.equals(path)) { initLoader = loader;
// 若事件所在目录不为为 path忽略并步入下一轮循环 return this;
continue; }
@Override
public void commit() {
if (initLoader != null) initLoader.load(path);
executor.execute(buildWatchTask());
}
private Runnable buildWatchTask() {
return () -> {
String pathStr = path.toString();
log.info("行动程序目录监听器已启动,监听目录: {}", pathStr);
while (true) {
WatchKey key;
try {
key = watchService.take();
List<WatchEvent<?>> events = key.pollEvents();
for (WatchEvent<?> e : events) {
WatchEvent.Kind<?> kind = e.kind();
Object context = e.context();
log.info("行动程序目录变更事件: {} - {} - {}", pathStr, kind.name(), context);
Path thisDir = (Path) key.watchable();
if (!thisDir.equals(path)) {
// 若事件所在目录不为为 path忽略并步入下一轮循环
continue;
}
EventHandler handler = handlers.get(kind);
if (handler == null) {
continue;
}
handler.handle(thisDir, context instanceof Path ? (Path) context : null);
} }
WatchEventHandler handler = handlers.get(kind); } catch (InterruptedException e) {
if (handler == null) { log.info("监听线程被中断,准备退出...");
continue; Thread.currentThread().interrupt(); // 恢复中断标志
} break;
handler.handle(thisDir, context instanceof Path ? (Path) context : null); } catch (ClosedWatchServiceException e) {
log.info("WatchService 已关闭,监听线程退出。");
break;
} }
} catch (InterruptedException e) {
log.info("监听线程被中断,准备退出...");
Thread.currentThread().interrupt(); // 恢复中断标志
break;
} catch (ClosedWatchServiceException e) {
log.info("WatchService 已关闭,监听线程退出。");
break;
} }
} };
}; }
}
}
} }
private sealed static abstract class LocalWatchServiceHelper permits LocalWatchServiceHelper.Dynamic, LocalWatchServiceHelper.Desc, LocalWatchServiceHelper.Common { private sealed static abstract class LocalWatchServiceHelper permits LocalWatchServiceHelper.Dynamic, LocalWatchServiceHelper.Desc, LocalWatchServiceHelper.Common {
@@ -394,15 +394,15 @@ public class LocalRunnerClient extends RunnerClient {
this.existedMetaActions = existedMetaActions; this.existedMetaActions = existedMetaActions;
} }
protected abstract @NotNull WatchInitLoader buildLoad(); protected abstract @NotNull LocalWatchServiceBuild.InitLoader buildLoad();
protected abstract @NotNull WatchEventHandler buildModify(); protected abstract @NotNull LocalWatchServiceBuild.EventHandler buildModify();
protected abstract @NotNull WatchEventHandler buildCreate(); protected abstract @NotNull LocalWatchServiceBuild.EventHandler buildCreate();
protected abstract @NotNull WatchEventHandler buildDelete(); protected abstract @NotNull LocalWatchServiceBuild.EventHandler buildDelete();
protected abstract @NotNull WatchEventHandler buildOverflow(); protected abstract @NotNull LocalWatchServiceBuild.EventHandler buildOverflow();
private static final class Dynamic extends LocalWatchServiceHelper { private static final class Dynamic extends LocalWatchServiceHelper {
@@ -417,29 +417,31 @@ public class LocalRunnerClient extends RunnerClient {
@NotNull @NotNull
protected WatchInitLoader buildLoad() { protected WatchInitLoader buildLoad() {
return null; return null;
protected LocalWatchServiceBuild.InitLoader buildLoad() {
} }
@Override @Override
@NotNull @NotNull
protected WatchEventHandler buildModify() { protected WatchEventHandler buildModify() {
return null; return null;
protected LocalWatchServiceBuild.EventHandler buildModify() {
} }
@Override @Override
@NotNull @NotNull
protected WatchEventHandler buildCreate() { protected LocalWatchServiceBuild.EventHandler buildCreate() {
return buildModify();
}
@Override
@NotNull
protected LocalWatchServiceBuild.EventHandler buildDelete() {
return null; return null;
} }
@Override @Override
@NotNull @NotNull
protected WatchEventHandler buildDelete() { protected LocalWatchServiceBuild.EventHandler buildOverflow() {
return null;
}
@Override
@NotNull
protected WatchEventHandler buildOverflow() {
return null; return null;
} }
} }
@@ -455,31 +457,31 @@ public class LocalRunnerClient extends RunnerClient {
@Override @Override
@NotNull @NotNull
protected WatchInitLoader buildLoad() { protected LocalWatchServiceBuild.InitLoader buildLoad() {
return null; return null;
} }
@Override @Override
@NotNull @NotNull
protected WatchEventHandler buildModify() { protected LocalWatchServiceBuild.EventHandler buildModify() {
return null; return null;
} }
@Override @Override
@NotNull @NotNull
protected WatchEventHandler buildCreate() { protected LocalWatchServiceBuild.EventHandler buildCreate() {
return null; return null;
} }
@Override @Override
@NotNull @NotNull
protected WatchEventHandler buildDelete() { protected LocalWatchServiceBuild.EventHandler buildDelete() {
return null; return null;
} }
@Override @Override
@NotNull @NotNull
protected WatchEventHandler buildOverflow() { protected LocalWatchServiceBuild.EventHandler buildOverflow() {
return null; return null;
} }
} }
@@ -495,31 +497,31 @@ public class LocalRunnerClient extends RunnerClient {
@Override @Override
@NotNull @NotNull
protected WatchInitLoader buildLoad() { protected LocalWatchServiceBuild.InitLoader buildLoad() {
return null; return null;
} }
@Override @Override
@NotNull @NotNull
protected WatchEventHandler buildModify() { protected LocalWatchServiceBuild.EventHandler buildModify() {
return null; return null;
} }
@Override @Override
@NotNull @NotNull
protected WatchEventHandler buildCreate() { protected LocalWatchServiceBuild.EventHandler buildCreate() {
return null; return null;
} }
@Override @Override
@NotNull @NotNull
protected WatchEventHandler buildDelete() { protected LocalWatchServiceBuild.EventHandler buildDelete() {
return null; return null;
} }
@Override @Override
@NotNull @NotNull
protected WatchEventHandler buildOverflow() { protected LocalWatchServiceBuild.EventHandler buildOverflow() {
return null; return null;
} }
} }