Files
clash-proxy/src/services/delay.ts

132 lines
3.4 KiB
TypeScript
Raw Normal View History

import { cmdGetProxyDelay } from "./cmds";
2022-02-16 02:22:01 +08:00
const hashKey = (name: string, group: string) => `${group ?? ""}::${name}`;
class DelayManager {
private cache = new Map<string, [number, number]>();
private urlMap = new Map<string, string>();
// 每个item的监听
private listenerMap = new Map<string, (time: number) => void>();
// 每个分组的监听
private groupListenerMap = new Map<string, () => void>();
setUrl(group: string, url: string) {
this.urlMap.set(group, url);
}
getUrl(group: string) {
return this.urlMap.get(group);
}
2022-02-16 02:22:01 +08:00
setListener(name: string, group: string, listener: (time: number) => void) {
const key = hashKey(name, group);
this.listenerMap.set(key, listener);
}
removeListener(name: string, group: string) {
const key = hashKey(name, group);
this.listenerMap.delete(key);
}
setGroupListener(group: string, listener: () => void) {
this.groupListenerMap.set(group, listener);
}
removeGroupListener(group: string) {
this.groupListenerMap.delete(group);
}
2022-02-16 02:22:01 +08:00
setDelay(name: string, group: string, delay: number) {
const key = hashKey(name, group);
this.cache.set(key, [Date.now(), delay]);
this.listenerMap.get(key)?.(delay);
this.groupListenerMap.get(group)?.();
2022-02-16 02:22:01 +08:00
}
getDelay(name: string, group: string) {
if (!name) return -1;
const result = this.cache.get(hashKey(name, group));
if (result && Date.now() - result[0] <= 18e5) {
return result[1];
}
return -1;
}
2022-11-11 01:21:23 +08:00
/// 暂时修复provider的节点延迟排序的问题
2022-11-19 17:22:29 +08:00
getDelayFix(proxy: IProxyItem, group: string) {
2022-12-14 15:29:02 +08:00
if (!proxy.provider) {
const delay = this.getDelay(proxy.name, group);
if (delay >= 0 || delay === -2) return delay;
}
2022-11-11 01:21:23 +08:00
if (proxy.history.length > 0) {
// 0ms以error显示
return proxy.history[proxy.history.length - 1].delay || 1e6;
}
return -1;
}
async checkDelay(name: string, group: string, timeout: number) {
2022-02-16 02:22:01 +08:00
let delay = -1;
try {
const url = this.getUrl(group);
const result = await cmdGetProxyDelay(name, timeout, url);
2022-02-16 02:22:01 +08:00
delay = result.delay;
} catch {
delay = 1e6; // error
}
this.setDelay(name, group, delay);
return delay;
}
2022-02-27 00:58:14 +08:00
async checkListDelay(
nameList: string[],
group: string,
timeout: number,
concurrency = 36
) {
2022-12-15 12:23:57 +08:00
const names = nameList.filter(Boolean);
// 设置正在延迟测试中
names.forEach((name) => this.setDelay(name, group, -2));
let total = names.length;
let current = 0;
return new Promise((resolve) => {
const help = async (): Promise<void> => {
if (current >= concurrency) return;
const task = names.shift();
if (!task) return;
current += 1;
await this.checkDelay(task, group, timeout);
current -= 1;
total -= 1;
if (total <= 0) resolve(null);
else return help();
};
for (let i = 0; i < concurrency; ++i) help();
});
2022-02-27 00:58:14 +08:00
}
formatDelay(delay: number, timeout = 10000) {
2024-01-17 11:02:17 +08:00
if (delay <= 0) return "Error";
if (delay > 1e5) return "Error";
if (delay >= timeout) return "Timeout"; // 10s
2024-01-21 13:46:19 +08:00
return `${delay}`;
}
formatDelayColor(delay: number, timeout = 10000) {
if (delay >= timeout) return "error.main";
2024-01-17 11:02:17 +08:00
if (delay <= 0) return "error.main";
if (delay > 500) return "warning.main";
return "success.main";
}
2022-02-16 02:22:01 +08:00
}
export default new DelayManager();