@teamvibe/poller 0.1.27 → 0.1.29
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/dist/claude-spawner.d.ts +1 -0
- package/dist/claude-spawner.js +23 -0
- package/dist/poller.js +12 -2
- package/package.json +1 -1
package/dist/claude-spawner.d.ts
CHANGED
package/dist/claude-spawner.js
CHANGED
|
@@ -298,3 +298,26 @@ export function getActiveProcessCount() {
|
|
|
298
298
|
export function isAtCapacity() {
|
|
299
299
|
return activeProcesses.size >= config.MAX_CONCURRENT_SESSIONS;
|
|
300
300
|
}
|
|
301
|
+
export function killAllActiveProcesses() {
|
|
302
|
+
if (activeProcesses.size === 0)
|
|
303
|
+
return Promise.resolve();
|
|
304
|
+
logger.info(`Killing ${activeProcesses.size} active Claude process(es)...`);
|
|
305
|
+
const killPromises = Array.from(activeProcesses.entries()).map(([id, proc]) => new Promise((resolve) => {
|
|
306
|
+
if (proc.exitCode !== null) {
|
|
307
|
+
resolve();
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const forceKillTimer = setTimeout(() => {
|
|
311
|
+
logger.warn(`Process ${id} did not exit after SIGTERM, sending SIGKILL`);
|
|
312
|
+
proc.kill('SIGKILL');
|
|
313
|
+
}, 5000);
|
|
314
|
+
proc.once('close', () => {
|
|
315
|
+
clearTimeout(forceKillTimer);
|
|
316
|
+
resolve();
|
|
317
|
+
});
|
|
318
|
+
proc.kill('SIGTERM');
|
|
319
|
+
}));
|
|
320
|
+
return Promise.all(killPromises).then(() => {
|
|
321
|
+
logger.info('All active processes terminated');
|
|
322
|
+
});
|
|
323
|
+
}
|
package/dist/poller.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { config } from './config.js';
|
|
2
2
|
import { logger } from './logger.js';
|
|
3
3
|
import { pollMessages, deleteMessage, extendVisibility, } from './sqs-poller.js';
|
|
4
|
-
import { spawnClaudeCode, isAtCapacity, getActiveProcessCount } from './claude-spawner.js';
|
|
4
|
+
import { spawnClaudeCode, isAtCapacity, getActiveProcessCount, killAllActiveProcesses } from './claude-spawner.js';
|
|
5
5
|
import { sendSlackError, addReaction, getUserInfo, startTypingIndicator } from './slack-client.js';
|
|
6
6
|
import { acquireSessionLock, releaseSessionLock, updateSessionId } from './session-store.js';
|
|
7
7
|
import { getBrainPath, ensureDirectories, ensureBaseBrain, pushBrainChanges } from './brain-manager.js';
|
|
@@ -191,7 +191,7 @@ async function processMessage(received) {
|
|
|
191
191
|
}
|
|
192
192
|
async function pollLoop() {
|
|
193
193
|
logger.info('Poll loop started');
|
|
194
|
-
while (
|
|
194
|
+
while (!shuttingDown) {
|
|
195
195
|
try {
|
|
196
196
|
if (isAtCapacity()) {
|
|
197
197
|
logger.debug(`At capacity (${getActiveProcessCount()}/${config.MAX_CONCURRENT_SESSIONS}), waiting...`);
|
|
@@ -229,6 +229,16 @@ async function shutdown(signal) {
|
|
|
229
229
|
shuttingDown = true;
|
|
230
230
|
logger.info(`${signal} received, shutting down gracefully...`);
|
|
231
231
|
stopRefresh();
|
|
232
|
+
// Unblock all messages waiting on thread completion so they can exit
|
|
233
|
+
for (const [threadId, signals] of threadCompletionSignals.entries()) {
|
|
234
|
+
logger.info(`Unblocking ${signals.length} waiting message(s) on thread ${threadId}`);
|
|
235
|
+
signals.forEach((resolve) => resolve());
|
|
236
|
+
}
|
|
237
|
+
threadCompletionSignals.clear();
|
|
238
|
+
waitingCountByThread.clear();
|
|
239
|
+
// Kill all active Claude child processes
|
|
240
|
+
await killAllActiveProcesses();
|
|
241
|
+
// Wait for processingMessages to drain (with timeout)
|
|
232
242
|
const shutdownTimeout = 30000;
|
|
233
243
|
const startTime = Date.now();
|
|
234
244
|
while (processingMessages.size > 0) {
|