@okrlinkhub/agent-factory 1.0.1 → 1.0.2
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/client/index.d.ts +3 -3
- package/dist/component/identity.d.ts +5 -5
- package/dist/component/pushing.d.ts +25 -25
- package/dist/component/queue.d.ts +42 -42
- package/dist/component/queue.d.ts.map +1 -1
- package/dist/component/queue.js +19 -1
- package/dist/component/queue.js.map +1 -1
- package/dist/component/scheduler.d.ts +18 -18
- package/dist/component/scheduler.js +5 -4
- package/dist/component/scheduler.js.map +1 -1
- package/dist/component/schema.d.ts +22 -22
- package/package.json +1 -1
- package/src/component/lib.test.ts +241 -0
- package/src/component/queue.ts +41 -1
- package/src/component/scheduler.ts +7 -4
package/src/component/queue.ts
CHANGED
|
@@ -1041,6 +1041,7 @@ export const claimNextJob = mutation({
|
|
|
1041
1041
|
returns: v.union(v.null(), claimedJobValidator),
|
|
1042
1042
|
handler: async (ctx, args) => {
|
|
1043
1043
|
const nowMs = args.nowMs ?? Date.now();
|
|
1044
|
+
const staleHeartbeatCutoff = nowMs - DEFAULT_CONFIG.lease.staleAfterMs;
|
|
1044
1045
|
const worker = await ctx.db
|
|
1045
1046
|
.query("workers")
|
|
1046
1047
|
.withIndex("by_workerId", (q) => q.eq("workerId", args.workerId))
|
|
@@ -1055,6 +1056,7 @@ export const claimNextJob = mutation({
|
|
|
1055
1056
|
) {
|
|
1056
1057
|
return null;
|
|
1057
1058
|
}
|
|
1059
|
+
const workers = await ctx.db.query("workers").collect();
|
|
1058
1060
|
const candidates = await ctx.db
|
|
1059
1061
|
.query("messageQueue")
|
|
1060
1062
|
.withIndex("by_status_and_scheduledFor", (q) =>
|
|
@@ -1093,6 +1095,15 @@ export const claimNextJob = mutation({
|
|
|
1093
1095
|
) {
|
|
1094
1096
|
continue;
|
|
1095
1097
|
}
|
|
1098
|
+
const existingOwner = findActiveAssignmentOwner(workers, {
|
|
1099
|
+
conversationId: candidate.conversationId,
|
|
1100
|
+
agentKey: candidate.agentKey,
|
|
1101
|
+
excludeWorkerId: args.workerId,
|
|
1102
|
+
staleHeartbeatCutoff,
|
|
1103
|
+
});
|
|
1104
|
+
if (existingOwner) {
|
|
1105
|
+
continue;
|
|
1106
|
+
}
|
|
1096
1107
|
|
|
1097
1108
|
const lock = conversation.processingLock;
|
|
1098
1109
|
if (lock && lock.leaseExpiresAt > nowMs) continue;
|
|
@@ -2292,7 +2303,7 @@ async function scheduleIdleShutdownWatchdog(
|
|
|
2292
2303
|
}
|
|
2293
2304
|
}
|
|
2294
2305
|
|
|
2295
|
-
async function scheduleLeaseRecoveryWatchdog(ctx: any,
|
|
2306
|
+
async function scheduleLeaseRecoveryWatchdog(ctx: any, _nowMs: number) {
|
|
2296
2307
|
const delayMs = DEFAULT_CONFIG.lease.leaseMs + 1_000;
|
|
2297
2308
|
try {
|
|
2298
2309
|
await ctx.scheduler.runAfter(delayMs, (internal.scheduler as any).reconcileWorkerPoolInternal, {
|
|
@@ -2376,6 +2387,35 @@ function clearAssignmentForMessage(
|
|
|
2376
2387
|
return worker.assignment;
|
|
2377
2388
|
}
|
|
2378
2389
|
|
|
2390
|
+
function findActiveAssignmentOwner(
|
|
2391
|
+
workers: Array<{
|
|
2392
|
+
workerId: string;
|
|
2393
|
+
status: "active" | "draining" | "stopping" | "stopped";
|
|
2394
|
+
heartbeatAt: number;
|
|
2395
|
+
assignment?: {
|
|
2396
|
+
conversationId: string;
|
|
2397
|
+
agentKey: string;
|
|
2398
|
+
leaseId: string;
|
|
2399
|
+
assignedAt: number;
|
|
2400
|
+
};
|
|
2401
|
+
}>,
|
|
2402
|
+
args: {
|
|
2403
|
+
conversationId: string;
|
|
2404
|
+
agentKey: string;
|
|
2405
|
+
excludeWorkerId: string;
|
|
2406
|
+
staleHeartbeatCutoff: number;
|
|
2407
|
+
},
|
|
2408
|
+
) {
|
|
2409
|
+
return workers.find(
|
|
2410
|
+
(candidate) =>
|
|
2411
|
+
candidate.workerId !== args.excludeWorkerId &&
|
|
2412
|
+
isWorkerClaimable(candidate.status) &&
|
|
2413
|
+
candidate.heartbeatAt > args.staleHeartbeatCutoff &&
|
|
2414
|
+
candidate.assignment?.conversationId === args.conversationId &&
|
|
2415
|
+
candidate.assignment.agentKey === args.agentKey,
|
|
2416
|
+
);
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2379
2419
|
function dedupeMessagesById<T extends { _id: string }>(messages: Array<T>): Array<T> {
|
|
2380
2420
|
const seen = new Set<string>();
|
|
2381
2421
|
const deduped: Array<T> = [];
|
|
@@ -765,20 +765,23 @@ function countWorkersAvailableForActiveConversations(
|
|
|
765
765
|
staleHeartbeatCutoff: number,
|
|
766
766
|
) {
|
|
767
767
|
const activeConversationSet = new Set(activeConversationIds);
|
|
768
|
-
|
|
768
|
+
const assignedConversationKeys = new Set<string>();
|
|
769
|
+
let unassignedWorkers = 0;
|
|
769
770
|
for (const worker of workerRows) {
|
|
770
771
|
if (!isWorkerClaimable(worker.status) || worker.heartbeatAt <= staleHeartbeatCutoff) {
|
|
771
772
|
continue;
|
|
772
773
|
}
|
|
773
774
|
if (!worker.assignment) {
|
|
774
|
-
|
|
775
|
+
unassignedWorkers += 1;
|
|
775
776
|
continue;
|
|
776
777
|
}
|
|
777
778
|
if (activeConversationSet.has(worker.assignment.conversationId)) {
|
|
778
|
-
|
|
779
|
+
assignedConversationKeys.add(
|
|
780
|
+
`${worker.assignment.agentKey}::${worker.assignment.conversationId}`,
|
|
781
|
+
);
|
|
779
782
|
}
|
|
780
783
|
}
|
|
781
|
-
return
|
|
784
|
+
return unassignedWorkers + assignedConversationKeys.size;
|
|
782
785
|
}
|
|
783
786
|
|
|
784
787
|
function deriveScheduledShutdownAt(
|