mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-24 01:41:42 +02:00
fix(agents): clear heartbeat refs before removal
This commit is contained in:
1 parent
47f767d4a9
commit
d82963ce87
2 files changed
+55
-1
No files matched your search
@@ -7,6 +7,7 @@ import {
|
||||
companies,
|
||||
companySkills,
|
||||
createDb,
|
||||
heartbeatRunEvents,
|
||||
heartbeatRuns,
|
||||
issueComments,
|
||||
issueExecutionDecisions,
|
||||
@@ -44,6 +45,7 @@ describeEmbeddedPostgres("cleanup removal services", () => {
|
||||
await db.delete(issueComments);
|
||||
await db.delete(issueExecutionDecisions);
|
||||
await db.delete(companySkills);
|
||||
await db.delete(heartbeatRunEvents);
|
||||
await db.delete(heartbeatRuns);
|
||||
await db.delete(issues);
|
||||
await db.delete(agents);
|
||||
@@ -99,6 +101,15 @@ describeEmbeddedPostgres("cleanup removal services", () => {
|
||||
contextSnapshot: { issueId },
|
||||
});
|
||||
|
||||
await db
|
||||
.update(issues)
|
||||
.set({
|
||||
executionRunId: runId,
|
||||
executionAgentNameKey: "codexcoder",
|
||||
executionLockedAt: new Date(),
|
||||
})
|
||||
.where(eq(issues.id, issueId));
|
||||
|
||||
return { agentId, companyId, issueId, runId };
|
||||
}
|
||||
|
||||
@@ -137,13 +148,29 @@ describeEmbeddedPostgres("cleanup removal services", () => {
|
||||
createdByRunId: runId,
|
||||
});
|
||||
|
||||
await db.insert(heartbeatRunEvents).values({
|
||||
companyId,
|
||||
runId,
|
||||
agentId,
|
||||
seq: 1,
|
||||
eventType: "status",
|
||||
message: "Run finished",
|
||||
});
|
||||
|
||||
const removed = await agentService(db).remove(agentId);
|
||||
|
||||
expect(removed?.id).toBe(agentId);
|
||||
await expect(db.select().from(agents).where(eq(agents.id, agentId))).resolves.toHaveLength(0);
|
||||
await expect(db.select().from(heartbeatRuns).where(eq(heartbeatRuns.id, runId))).resolves.toHaveLength(0);
|
||||
await expect(db.select().from(heartbeatRunEvents).where(eq(heartbeatRunEvents.runId, runId))).resolves.toHaveLength(0);
|
||||
await expect(db.select().from(issueComments).where(eq(issueComments.issueId, issueId))).resolves.toHaveLength(0);
|
||||
await expect(db.select().from(activityLog).where(eq(activityLog.companyId, companyId))).resolves.toHaveLength(0);
|
||||
await expect(
|
||||
db
|
||||
.select({ executionRunId: issues.executionRunId })
|
||||
.from(issues)
|
||||
.where(eq(issues.id, issueId)),
|
||||
).resolves.toEqual([{ executionRunId: null }]);
|
||||
});
|
||||
|
||||
it("removes issue read states and activity rows before deleting the company", async () => {
|
||||
|
||||
@@ -477,11 +477,38 @@ export function agentService(db: Db) {
|
||||
if (!existing) return null;
|
||||
|
||||
return db.transaction(async (tx) => {
|
||||
const agentRunIds = await tx
|
||||
.select({ id: heartbeatRuns.id })
|
||||
.from(heartbeatRuns)
|
||||
.where(eq(heartbeatRuns.agentId, id))
|
||||
.then((rows) => rows.map((row) => row.id));
|
||||
|
||||
await tx.update(agents).set({ reportsTo: null }).where(eq(agents.reportsTo, id));
|
||||
await tx
|
||||
.update(issues)
|
||||
.set({ assigneeAgentId: null, createdByAgentId: null })
|
||||
.set({
|
||||
assigneeAgentId: null,
|
||||
createdByAgentId: null,
|
||||
...(agentRunIds.length > 0
|
||||
? {
|
||||
executionRunId: null,
|
||||
executionAgentNameKey: null,
|
||||
executionLockedAt: null,
|
||||
}
|
||||
: {}),
|
||||
})
|
||||
.where(or(eq(issues.assigneeAgentId, id), eq(issues.createdByAgentId, id)));
|
||||
if (agentRunIds.length > 0) {
|
||||
await tx
|
||||
.update(issues)
|
||||
.set({
|
||||
executionRunId: null,
|
||||
executionAgentNameKey: null,
|
||||
executionLockedAt: null,
|
||||
})
|
||||
.where(inArray(issues.executionRunId, agentRunIds));
|
||||
await tx.delete(heartbeatRunEvents).where(inArray(heartbeatRunEvents.runId, agentRunIds));
|
||||
}
|
||||
await tx.delete(heartbeatRunEvents).where(eq(heartbeatRunEvents.agentId, id));
|
||||
await tx.delete(agentTaskSessions).where(eq(agentTaskSessions.agentId, id));
|
||||
await tx.delete(activityLog).where(
|
||||
|
||||
Reference in new issue
Block a user