mirror of
https://github.com/ddaodan/minechatgpt.git
synced 2026-06-21 21:45:28 +08:00
feat: 增强调度功能,支持Folia调度器并优化任务管理
This commit is contained in:
@@ -6,13 +6,16 @@ import com.ddaodan.MineChatGPT.Main;
|
|||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
public class RequestCoordinator {
|
public class RequestCoordinator {
|
||||||
@@ -32,6 +35,7 @@ public class RequestCoordinator {
|
|||||||
private volatile TokenEstimator tokenEstimator;
|
private volatile TokenEstimator tokenEstimator;
|
||||||
private volatile RequestQueue<RequestJob> queue;
|
private volatile RequestQueue<RequestJob> queue;
|
||||||
private volatile int dispatchTaskId = -1;
|
private volatile int dispatchTaskId = -1;
|
||||||
|
private volatile Object foliaDispatchTask;
|
||||||
|
|
||||||
public RequestCoordinator(Main plugin, ConfigManager configManager, ApiService apiService, UserSessionManager sessionManager) {
|
public RequestCoordinator(Main plugin, ConfigManager configManager, ApiService apiService, UserSessionManager sessionManager) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
@@ -57,10 +61,10 @@ public class RequestCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
if (dispatchTaskId != -1) {
|
if (dispatchTaskId != -1 || foliaDispatchTask != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatchTaskId = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
|
Runnable dispatchRunnable = () -> {
|
||||||
if (!configManager.isQueueEnabled()) {
|
if (!configManager.isQueueEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -76,10 +80,30 @@ public class RequestCoordinator {
|
|||||||
}
|
}
|
||||||
dispatch(job);
|
dispatch(job);
|
||||||
}
|
}
|
||||||
}, 1L, 1L).getTaskId();
|
};
|
||||||
|
|
||||||
|
if (isFoliaSchedulerAvailable()) {
|
||||||
|
try {
|
||||||
|
foliaDispatchTask = runFoliaRepeating(dispatchRunnable, 1L, 1L);
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.getLogger().log(Level.WARNING, "Failed to schedule Folia repeating task, fallback to Bukkit scheduler.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatchTaskId = Bukkit.getScheduler().runTaskTimer(plugin, dispatchRunnable, 1L, 1L).getTaskId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
|
if (foliaDispatchTask != null) {
|
||||||
|
try {
|
||||||
|
cancelFoliaTask(foliaDispatchTask);
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.getLogger().log(Level.WARNING, "Failed to cancel Folia dispatch task.", e);
|
||||||
|
} finally {
|
||||||
|
foliaDispatchTask = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (dispatchTaskId != -1) {
|
if (dispatchTaskId != -1) {
|
||||||
Bukkit.getScheduler().cancelTask(dispatchTaskId);
|
Bukkit.getScheduler().cancelTask(dispatchTaskId);
|
||||||
dispatchTaskId = -1;
|
dispatchTaskId = -1;
|
||||||
@@ -163,7 +187,7 @@ public class RequestCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleCompletion(RequestJob job, String characterName, ApiService.ChatCompletionResult result) {
|
private void handleCompletion(RequestJob job, String characterName, ApiService.ChatCompletionResult result) {
|
||||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
runOnMainThread(() -> {
|
||||||
if (!plugin.isEnabled()) {
|
if (!plugin.isEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -270,7 +294,7 @@ public class RequestCoordinator {
|
|||||||
|
|
||||||
private CompletableFuture<Void> runSync(Runnable runnable) {
|
private CompletableFuture<Void> runSync(Runnable runnable) {
|
||||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
runOnMainThread(() -> {
|
||||||
try {
|
try {
|
||||||
runnable.run();
|
runnable.run();
|
||||||
future.complete(null);
|
future.complete(null);
|
||||||
@@ -281,6 +305,63 @@ public class RequestCoordinator {
|
|||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void runOnMainThread(Runnable runnable) {
|
||||||
|
if (isFoliaSchedulerAvailable()) {
|
||||||
|
try {
|
||||||
|
runFoliaNow(runnable);
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.getLogger().log(Level.WARNING, "Failed to execute on Folia scheduler, fallback to Bukkit scheduler.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Bukkit.getScheduler().runTask(plugin, runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object runFoliaRepeating(Runnable runnable, long initialDelayTicks, long periodTicks) throws Exception {
|
||||||
|
Object scheduler = getGlobalRegionScheduler();
|
||||||
|
Method method = scheduler.getClass().getMethod("runAtFixedRate", Plugin.class, Consumer.class, long.class, long.class);
|
||||||
|
Consumer<Object> consumer = task -> runnable.run();
|
||||||
|
return method.invoke(scheduler, plugin, consumer, initialDelayTicks, periodTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelFoliaTask(Object task) throws Exception {
|
||||||
|
try {
|
||||||
|
// Prefer invoking through public ScheduledTask interface when available.
|
||||||
|
Class<?> scheduledTaskInterface = Class.forName("io.papermc.paper.threadedregions.scheduler.ScheduledTask");
|
||||||
|
Method cancel = scheduledTaskInterface.getMethod("cancel");
|
||||||
|
cancel.invoke(task);
|
||||||
|
return;
|
||||||
|
} catch (ClassNotFoundException ignored) {
|
||||||
|
// Fall through to reflective invocation on task implementation.
|
||||||
|
}
|
||||||
|
|
||||||
|
Method cancel = task.getClass().getDeclaredMethod("cancel");
|
||||||
|
if (!cancel.isAccessible()) {
|
||||||
|
cancel.setAccessible(true);
|
||||||
|
}
|
||||||
|
cancel.invoke(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runFoliaNow(Runnable runnable) throws Exception {
|
||||||
|
Object scheduler = getGlobalRegionScheduler();
|
||||||
|
Method method = scheduler.getClass().getMethod("execute", Plugin.class, Runnable.class);
|
||||||
|
method.invoke(scheduler, plugin, runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getGlobalRegionScheduler() throws Exception {
|
||||||
|
Method method = Bukkit.getServer().getClass().getMethod("getGlobalRegionScheduler");
|
||||||
|
return method.invoke(Bukkit.getServer());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isFoliaSchedulerAvailable() {
|
||||||
|
try {
|
||||||
|
Bukkit.getServer().getClass().getMethod("getGlobalRegionScheduler");
|
||||||
|
return true;
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void trimContextToBudget(String characterPrompt, String summary, ConversationContext context) {
|
private void trimContextToBudget(String characterPrompt, String summary, ConversationContext context) {
|
||||||
int budget = configManager.getMaxContextTokens();
|
int budget = configManager.getMaxContextTokens();
|
||||||
if (budget <= 0) {
|
if (budget <= 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user