tt-help-cli-ycl 1.4.158 → 1.4.159
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/clash/daemon.js +28 -5
package/package.json
CHANGED
package/src/clash/daemon.js
CHANGED
|
@@ -342,6 +342,12 @@ export class ClashDaemon {
|
|
|
342
342
|
error: "等待控制端就绪",
|
|
343
343
|
meta: this._buildMeta(null),
|
|
344
344
|
});
|
|
345
|
+
// 等待期也消费订阅命令:setSubscription 不依赖控制器上下文,应用成功即落盘,
|
|
346
|
+
// 下轮重试 readStoredSubscriptions 即可拉起实例 → 解除"无订阅↔无控制端"死锁
|
|
347
|
+
// (全新机器首次后台配置订阅的场景:没有它,命令永远无人消费)
|
|
348
|
+
try {
|
|
349
|
+
await this._pollCommands({ subscriptionOnly: true });
|
|
350
|
+
} catch {}
|
|
345
351
|
this._running = false;
|
|
346
352
|
this._waitTimer = setTimeout(() => this.start(), 10_000);
|
|
347
353
|
return;
|
|
@@ -836,18 +842,31 @@ export class ClashDaemon {
|
|
|
836
842
|
|
|
837
843
|
// ── 命令轮询(多通道:默认通道 + 每端口通道) ──
|
|
838
844
|
|
|
839
|
-
|
|
845
|
+
/**
|
|
846
|
+
* 命令轮询消费
|
|
847
|
+
* @param {object} [opts]
|
|
848
|
+
* @param {boolean} [opts.subscriptionOnly] 等待控制端就绪期:只消费不依赖控制器上下文的命令
|
|
849
|
+
* (setSubscription),其余保留在通道内待就绪后处理,避免丢失
|
|
850
|
+
*/
|
|
851
|
+
_pollCommands({ subscriptionOnly = false } = {}) {
|
|
840
852
|
if (!this._running) return;
|
|
841
|
-
this._withLock(async () => {
|
|
853
|
+
return this._withLock(async () => {
|
|
842
854
|
for (const ch of ipc.listCommandChannels()) {
|
|
843
855
|
let cmds = null;
|
|
844
856
|
try {
|
|
845
857
|
cmds = ipc.readCommand(ch);
|
|
846
858
|
} catch {}
|
|
847
859
|
if (!cmds) continue;
|
|
860
|
+
const kept = [];
|
|
848
861
|
for (const cmd of cmds) {
|
|
849
862
|
const target = this._routeController(cmd);
|
|
850
|
-
|
|
863
|
+
// 无控制端(等待就绪期/命令目标缺失)时,仅 setSubscription 可脱离控制器上下文执行,
|
|
864
|
+
// 其余命令保留,防止误消费后丢失
|
|
865
|
+
if ((!target || subscriptionOnly) && cmd.action !== "setSubscription") {
|
|
866
|
+
kept.push(cmd);
|
|
867
|
+
continue;
|
|
868
|
+
}
|
|
869
|
+
if (target) this._useController(target);
|
|
851
870
|
const handler = this._cmdHandlers[cmd.action];
|
|
852
871
|
if (handler) {
|
|
853
872
|
await handler(cmd, target);
|
|
@@ -855,9 +874,10 @@ export class ClashDaemon {
|
|
|
855
874
|
this._log(`📋 未知命令: ${JSON.stringify(cmd)}`);
|
|
856
875
|
}
|
|
857
876
|
}
|
|
858
|
-
ipc.
|
|
877
|
+
if (kept.length) ipc.writeCommand(kept, ch);
|
|
878
|
+
else ipc.clearCommand(ch);
|
|
859
879
|
}
|
|
860
|
-
}).catch(() => {});
|
|
880
|
+
}).catch((e) => this._log(`命令消费异常: ${e.message}`));
|
|
861
881
|
}
|
|
862
882
|
|
|
863
883
|
async _handleSwitchNode(cmd, c) {
|
|
@@ -1015,6 +1035,9 @@ export class ClashDaemon {
|
|
|
1015
1035
|
* 保证 daemon/机器重启后自动恢复,不依赖服务端可达
|
|
1016
1036
|
*/
|
|
1017
1037
|
async _handleSetSubscription(cmd, c) {
|
|
1038
|
+
// 等待就绪期 _primary 为 null:用哑控制器上下文(proxyPort=0 → 默认通道)
|
|
1039
|
+
// 保证订阅应用/落盘/健康上报不中断
|
|
1040
|
+
c = c || { proxyPort: 0, clientName: "mihomo(内置)", _meta: {} };
|
|
1018
1041
|
try {
|
|
1019
1042
|
const subs = runtime.normalizeSubscriptions(cmd.subscriptions);
|
|
1020
1043
|
if (!subs.length) {
|