fix(identity): Use unique session IDs for proxy rotation + add task pool gate

- Fix buildEvomiProxyUrl to use passed session ID from identity pool
  instead of truncating to worker+region (causing same IP for all workers)
- Add task pool gate feature with database-backed state
- Add /tasks/pool/toggle endpoint and UI toggle button
- Fix isTaskPoolPaused() missing await in claimTask

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Kelly
2025-12-13 20:17:52 -07:00
parent b456fe5097
commit 072388ffb2
7 changed files with 254 additions and 69 deletions

View File

@@ -49,8 +49,11 @@ function getRequestMetadata(req: Request): Record<string, unknown> {
import { pool } from '../db/pool';
import {
isTaskPoolPaused,
isTaskPoolOpen,
pauseTaskPool,
resumeTaskPool,
closeTaskPool,
openTaskPool,
getTaskPoolStatus,
} from '../tasks/task-pool-state';
@@ -1546,40 +1549,93 @@ router.get('/states', async (_req: Request, res: Response) => {
/**
* GET /api/tasks/pool/status
* Check if task pool is paused
* Check if task pool is open or closed
*/
router.get('/pool/status', async (_req: Request, res: Response) => {
const status = getTaskPoolStatus();
res.json({
success: true,
...status,
});
try {
const status = await getTaskPoolStatus();
res.json({
success: true,
...status,
});
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
});
/**
* POST /api/tasks/pool/pause
* Pause the task pool - workers won't pick up new tasks
* POST /api/tasks/pool/close
* Close the task pool - workers won't pick up new tasks
*/
router.post('/pool/close', async (_req: Request, res: Response) => {
try {
await closeTaskPool();
res.json({
success: true,
open: false,
message: 'Pool is Closed - workers will not pick up new tasks',
});
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
});
/**
* POST /api/tasks/pool/open
* Open the task pool - workers will pick up tasks again
*/
router.post('/pool/open', async (_req: Request, res: Response) => {
try {
await openTaskPool();
res.json({
success: true,
open: true,
message: 'Pool is Open - workers are picking up tasks',
});
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
});
/**
* POST /api/tasks/pool/toggle
* Toggle the task pool state
*/
router.post('/pool/toggle', async (_req: Request, res: Response) => {
try {
const isOpen = await isTaskPoolOpen();
if (isOpen) {
await closeTaskPool();
} else {
await openTaskPool();
}
const status = await getTaskPoolStatus();
res.json({
success: true,
...status,
});
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
});
// Legacy endpoints for compatibility
router.post('/pool/pause', async (_req: Request, res: Response) => {
pauseTaskPool();
res.json({
success: true,
paused: true,
message: 'Task pool paused - workers will not pick up new tasks',
});
try {
await closeTaskPool();
res.json({ success: true, paused: true, message: 'Task pool closed' });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
});
/**
* POST /api/tasks/pool/resume
* Resume the task pool - workers will pick up tasks again
*/
router.post('/pool/resume', async (_req: Request, res: Response) => {
resumeTaskPool();
res.json({
success: true,
paused: false,
message: 'Task pool resumed - workers will pick up new tasks',
});
try {
await openTaskPool();
res.json({ success: true, paused: false, message: 'Task pool opened' });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
});
export default router;