@supaku/agentfactory-server 0.7.37 → 0.7.39
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/src/issue-lock.d.ts
CHANGED
|
@@ -110,11 +110,14 @@ export declare function isSessionParkedForIssue(issueId: string, sessionId: stri
|
|
|
110
110
|
*/
|
|
111
111
|
export declare function cleanupExpiredLocksWithPendingWork(): Promise<number>;
|
|
112
112
|
/**
|
|
113
|
-
* Release issue locks held by sessions that
|
|
113
|
+
* Release issue locks held by sessions that should no longer hold them.
|
|
114
114
|
*
|
|
115
|
-
* This handles
|
|
116
|
-
*
|
|
117
|
-
*
|
|
115
|
+
* This handles cases where:
|
|
116
|
+
* - A session completes but the lock release failed (network error during cleanup)
|
|
117
|
+
* - Orphan cleanup resets a session to 'pending' but the lock wasn't released
|
|
118
|
+
*
|
|
119
|
+
* The lock's 2-hour TTL would eventually expire, but this proactively clears it
|
|
120
|
+
* when workers have idle capacity.
|
|
118
121
|
*
|
|
119
122
|
* Only runs when workers are online -- if no workers are available, there's no
|
|
120
123
|
* point promoting parked work since nothing can pick it up.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue-lock.d.ts","sourceRoot":"","sources":["../../src/issue-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAmBH,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAoB/C;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,aAAa,CAAA;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,OAAO,CAAA;IACnB,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,OAAO,CAAC,CA4BlB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAY7E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUrE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,UAAU,GAAE,MAAyB,GACpC,OAAO,CAAC,OAAO,CAAC,CAUlB;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,UAAU,GACf,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,CAoDjD;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAqE5B;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAU1E;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,CAoD5E;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAsClB;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAwBlB;AAED;;;;;GAKG;AACH,wBAAsB,kCAAkC,IAAI,OAAO,CAAC,MAAM,CAAC,CA6C1E;
|
|
1
|
+
{"version":3,"file":"issue-lock.d.ts","sourceRoot":"","sources":["../../src/issue-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAmBH,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAoB/C;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,aAAa,CAAA;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,OAAO,CAAA;IACnB,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,OAAO,CAAC,CA4BlB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAY7E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUrE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,UAAU,GAAE,MAAyB,GACpC,OAAO,CAAC,OAAO,CAAC,CAUlB;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,UAAU,GACf,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,CAoDjD;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAqE5B;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAU1E;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,CAoD5E;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAsClB;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAwBlB;AAED;;;;;GAKG;AACH,wBAAsB,kCAAkC,IAAI,OAAO,CAAC,MAAM,CAAC,CA6C1E;AAOD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,gCAAgC,CACpD,cAAc,EAAE,OAAO,GACtB,OAAO,CAAC,MAAM,CAAC,CAgEjB"}
|
package/dist/src/issue-lock.js
CHANGED
|
@@ -424,13 +424,19 @@ export async function cleanupExpiredLocksWithPendingWork() {
|
|
|
424
424
|
}
|
|
425
425
|
return promoted;
|
|
426
426
|
}
|
|
427
|
-
|
|
427
|
+
// Statuses where a session should NOT be holding an issue lock.
|
|
428
|
+
// Terminal: session finished (completed/failed/stopped) but lock release failed.
|
|
429
|
+
// Pending: session was reset by orphan cleanup but lock wasn't released (see orphan-cleanup.ts).
|
|
430
|
+
const STALE_LOCK_STATUSES = new Set(['completed', 'failed', 'stopped', 'pending']);
|
|
428
431
|
/**
|
|
429
|
-
* Release issue locks held by sessions that
|
|
432
|
+
* Release issue locks held by sessions that should no longer hold them.
|
|
430
433
|
*
|
|
431
|
-
* This handles
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
+
* This handles cases where:
|
|
435
|
+
* - A session completes but the lock release failed (network error during cleanup)
|
|
436
|
+
* - Orphan cleanup resets a session to 'pending' but the lock wasn't released
|
|
437
|
+
*
|
|
438
|
+
* The lock's 2-hour TTL would eventually expire, but this proactively clears it
|
|
439
|
+
* when workers have idle capacity.
|
|
434
440
|
*
|
|
435
441
|
* Only runs when workers are online -- if no workers are available, there's no
|
|
436
442
|
* point promoting parked work since nothing can pick it up.
|
|
@@ -471,8 +477,8 @@ export async function cleanupStaleLocksWithIdleWorkers(hasIdleWorkers) {
|
|
|
471
477
|
promoted++;
|
|
472
478
|
continue;
|
|
473
479
|
}
|
|
474
|
-
if (
|
|
475
|
-
log.info('Releasing stale lock (session
|
|
480
|
+
if (STALE_LOCK_STATUSES.has(session.status)) {
|
|
481
|
+
log.info('Releasing stale lock (session no longer needs lock)', {
|
|
476
482
|
issueId,
|
|
477
483
|
sessionId: lock.sessionId,
|
|
478
484
|
sessionStatus: session.status,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orphan-cleanup.d.ts","sourceRoot":"","sources":["../../src/orphan-cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"orphan-cleanup.d.ts","sourceRoot":"","sources":["../../src/orphan-cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAA;AAqB7B;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,sFAAsF;IACtF,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAChE,2FAA2F;IAC3F,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAClE;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,KAAK,CAAC;QACb,SAAS,EAAE,MAAM,CAAA;QACjB,eAAe,EAAE,MAAM,CAAA;QACvB,MAAM,EAAE,UAAU,GAAG,QAAQ,CAAA;QAC7B,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,oEAAoE;QACpE,YAAY,CAAC,EAAE,MAAM,CAAA;KACtB,CAAC,CAAA;IACF,0DAA0D;IAC1D,sBAAsB,EAAE,MAAM,EAAE,CAAA;CACjC;AAED;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAuDzE;AAKD;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAiC9E;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,SAAS,CAAC,EAAE,sBAAsB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAyP9B;AASD,wBAAgB,gBAAgB,IAAI,OAAO,CAO1C;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,CAAC,EAAE,sBAAsB,GACjC,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAKrC"}
|
|
@@ -12,7 +12,7 @@ import { createLogger } from './logger.js';
|
|
|
12
12
|
import { getAllSessions, resetSessionForRequeue, } from './session-storage.js';
|
|
13
13
|
import { listWorkers } from './worker-storage.js';
|
|
14
14
|
import { releaseClaim, isSessionInQueue, } from './work-queue.js';
|
|
15
|
-
import { dispatchWork, cleanupExpiredLocksWithPendingWork, cleanupStaleLocksWithIdleWorkers, isSessionParkedForIssue, } from './issue-lock.js';
|
|
15
|
+
import { dispatchWork, cleanupExpiredLocksWithPendingWork, cleanupStaleLocksWithIdleWorkers, isSessionParkedForIssue, getIssueLock, releaseIssueLock, } from './issue-lock.js';
|
|
16
16
|
const log = createLogger('orphan-cleanup');
|
|
17
17
|
// How long a session can be running without a valid worker before being considered orphaned
|
|
18
18
|
const ORPHAN_THRESHOLD_MS = 120_000; // 2 minutes (worker TTL + buffer)
|
|
@@ -138,6 +138,19 @@ export async function cleanupOrphanedSessions(callbacks) {
|
|
|
138
138
|
});
|
|
139
139
|
// Release any existing claim
|
|
140
140
|
await releaseClaim(session.linearSessionId);
|
|
141
|
+
// Release the issue lock if held by this orphaned session.
|
|
142
|
+
// Without this, dispatchWork() below would fail to acquire the lock
|
|
143
|
+
// (SET NX) and park the work instead — leaving it stuck until the
|
|
144
|
+
// lock's 2-hour TTL expires, since the session is reset to 'pending'
|
|
145
|
+
// which the stale-lock cleanup doesn't consider terminal.
|
|
146
|
+
const existingLock = await getIssueLock(session.issueId);
|
|
147
|
+
if (existingLock && existingLock.sessionId === session.linearSessionId) {
|
|
148
|
+
log.info('Releasing issue lock held by orphaned session', {
|
|
149
|
+
sessionId: session.linearSessionId,
|
|
150
|
+
issueId: session.issueId,
|
|
151
|
+
});
|
|
152
|
+
await releaseIssueLock(session.issueId);
|
|
153
|
+
}
|
|
141
154
|
// Reset session for requeue (clears workerId so new worker can claim)
|
|
142
155
|
await resetSessionForRequeue(session.linearSessionId);
|
|
143
156
|
// Re-queue the work with higher priority
|
|
@@ -153,6 +166,7 @@ export async function cleanupOrphanedSessions(callbacks) {
|
|
|
153
166
|
prompt: session.promptContext,
|
|
154
167
|
// providerSessionId intentionally omitted - don't resume crashed sessions
|
|
155
168
|
workType: session.workType,
|
|
169
|
+
projectName: session.projectName,
|
|
156
170
|
};
|
|
157
171
|
const dispatchResult = await dispatchWork(work);
|
|
158
172
|
if (dispatchResult.dispatched || dispatchResult.parked) {
|
|
@@ -214,6 +228,15 @@ export async function cleanupOrphanedSessions(callbacks) {
|
|
|
214
228
|
sessionId: session.linearSessionId,
|
|
215
229
|
issueIdentifier,
|
|
216
230
|
});
|
|
231
|
+
// Release issue lock if held by this zombie session (same rationale as orphan cleanup)
|
|
232
|
+
const existingLock = await getIssueLock(session.issueId);
|
|
233
|
+
if (existingLock && existingLock.sessionId === session.linearSessionId) {
|
|
234
|
+
log.info('Releasing issue lock held by zombie session', {
|
|
235
|
+
sessionId: session.linearSessionId,
|
|
236
|
+
issueId: session.issueId,
|
|
237
|
+
});
|
|
238
|
+
await releaseIssueLock(session.issueId);
|
|
239
|
+
}
|
|
217
240
|
const work = {
|
|
218
241
|
sessionId: session.linearSessionId,
|
|
219
242
|
issueId: session.issueId,
|
|
@@ -222,6 +245,7 @@ export async function cleanupOrphanedSessions(callbacks) {
|
|
|
222
245
|
queuedAt: Date.now(),
|
|
223
246
|
prompt: session.promptContext,
|
|
224
247
|
workType: session.workType,
|
|
248
|
+
projectName: session.projectName,
|
|
225
249
|
};
|
|
226
250
|
const dispatchResult = await dispatchWork(work);
|
|
227
251
|
if (dispatchResult.dispatched || dispatchResult.parked) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supaku/agentfactory-server",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.39",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Webhook server and distributed worker pool for AgentFactory — Redis queues, issue locks, session management",
|
|
6
6
|
"author": "Supaku (https://supaku.com)",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"ioredis": "^5.4.2",
|
|
47
|
-
"@supaku/agentfactory": "0.7.
|
|
48
|
-
"@supaku/agentfactory-linear": "0.7.
|
|
47
|
+
"@supaku/agentfactory": "0.7.39",
|
|
48
|
+
"@supaku/agentfactory-linear": "0.7.39"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^22.5.4",
|