claw-subagent-service 0.0.51 → 0.0.52
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
CHANGED
|
@@ -196,6 +196,30 @@ function startOpenClawGateway(log) {
|
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
class OpenClawClient {
|
|
199
|
+
// 全局并发限制:同时最多运行 N 个 openclaw agent 进程
|
|
200
|
+
static maxConcurrency = 2;
|
|
201
|
+
static runningCount = 0;
|
|
202
|
+
static waitQueue = [];
|
|
203
|
+
// Session 级串行锁:确保同一 session 不会并发 spawn 多个进程
|
|
204
|
+
static sessionLocks = new Map();
|
|
205
|
+
|
|
206
|
+
static async acquireSlot() {
|
|
207
|
+
if (OpenClawClient.runningCount < OpenClawClient.maxConcurrency) {
|
|
208
|
+
OpenClawClient.runningCount++;
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
return new Promise(resolve => OpenClawClient.waitQueue.push(resolve));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
static releaseSlot() {
|
|
215
|
+
OpenClawClient.runningCount--;
|
|
216
|
+
if (OpenClawClient.waitQueue.length > 0) {
|
|
217
|
+
const next = OpenClawClient.waitQueue.shift();
|
|
218
|
+
OpenClawClient.runningCount++;
|
|
219
|
+
next();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
199
223
|
constructor(log) {
|
|
200
224
|
this.log = log;
|
|
201
225
|
this.gatewayStarting = false;
|
|
@@ -260,6 +284,35 @@ class OpenClawClient {
|
|
|
260
284
|
|
|
261
285
|
async chatViaCLI(message, fromUser) {
|
|
262
286
|
const sessionId = `clawmessenger-${fromUser}`;
|
|
287
|
+
|
|
288
|
+
// 1. Session 级串行锁:同一用户的消息排队执行,避免多个进程竞争同一 session 文件
|
|
289
|
+
const previousLock = OpenClawClient.sessionLocks.get(sessionId);
|
|
290
|
+
let resolveLock;
|
|
291
|
+
const currentLock = new Promise(r => { resolveLock = r; });
|
|
292
|
+
OpenClawClient.sessionLocks.set(sessionId, currentLock);
|
|
293
|
+
if (previousLock) {
|
|
294
|
+
this.log?.info(`[OpenClawClient] session ${sessionId} 正在处理中,排队等待...`);
|
|
295
|
+
await previousLock;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// 2. 全局并发槽位限制:所有实例共享,防止服务器资源耗尽
|
|
299
|
+
await OpenClawClient.acquireSlot();
|
|
300
|
+
this.log?.info(`[OpenClawClient] 获得执行槽位 (当前运行: ${OpenClawClient.runningCount}/${OpenClawClient.maxConcurrency})`);
|
|
301
|
+
|
|
302
|
+
try {
|
|
303
|
+
return await this._runAgentCLI(message, fromUser, sessionId);
|
|
304
|
+
} finally {
|
|
305
|
+
OpenClawClient.releaseSlot();
|
|
306
|
+
this.log?.info(`[OpenClawClient] 释放执行槽位 (当前运行: ${OpenClawClient.runningCount}/${OpenClawClient.maxConcurrency})`);
|
|
307
|
+
// 释放 session 锁
|
|
308
|
+
resolveLock();
|
|
309
|
+
if (OpenClawClient.sessionLocks.get(sessionId) === currentLock) {
|
|
310
|
+
OpenClawClient.sessionLocks.delete(sessionId);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
_runAgentCLI(message, fromUser, sessionId) {
|
|
263
316
|
const escapedMessage = message
|
|
264
317
|
.replace(/\\/g, '\\\\')
|
|
265
318
|
.replace(/"/g, '\\"')
|