mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-30 21:49:18 +01:00
fix(server): preserve terminal workspace recovery cursor precision
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
a1a7bfd915
commit
28a197cdfd
4 files changed
+74
-15
No files matched your search
@@ -40,7 +40,7 @@ import { createHash } from "node:crypto";
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { isDeepStrictEqual, promisify } from "node:util";
|
||||
import { and, asc, desc, eq, gt, inArray, isNull, lte, ne, or, sql } from "drizzle-orm";
|
||||
import { and, asc, desc, eq, inArray, isNull, lte, ne, or, sql } from "drizzle-orm";
|
||||
import type { Db } from "@paperclipai/db";
|
||||
import {
|
||||
executionWorkspaces,
|
||||
@@ -1746,7 +1746,7 @@ export function executionWorkspaceService(db: Db, opts: ExecutionWorkspaceServic
|
||||
// required: without it the query re-selects the oldest ineligible rows every
|
||||
// sweep and starves eligible rows behind them. The cursor resets to the start
|
||||
// when a sweep reaches the end of the candidate set.
|
||||
let terminalSweepCursor: { updatedAt: Date; id: string } | null = null;
|
||||
let terminalSweepCursor: { updatedAt: string; id: string } | null = null;
|
||||
const terminalInspections = new Map<string, { revision: string; issueIds: Set<string>; nextAt: number }>();
|
||||
const terminalWorkspaceDeadlines = new Map<string, number>();
|
||||
const isolatedRehomeDeadlines = new Map<string, number>();
|
||||
@@ -3312,17 +3312,11 @@ export function executionWorkspaceService(db: Db, opts: ExecutionWorkspaceServic
|
||||
? lte(executionWorkspaces.updatedAt, boundary)
|
||||
: undefined;
|
||||
const cursorFilter = cursor
|
||||
? or(
|
||||
gt(executionWorkspaces.updatedAt, cursor.updatedAt),
|
||||
and(
|
||||
eq(executionWorkspaces.updatedAt, cursor.updatedAt),
|
||||
gt(executionWorkspaces.id, cursor.id),
|
||||
),
|
||||
)
|
||||
? sql`(${executionWorkspaces.updatedAt}, ${executionWorkspaces.id}) > (${cursor.updatedAt}::timestamptz, ${cursor.id}::uuid)`
|
||||
: undefined;
|
||||
const scanFilter = and(baseCandidateFilter, boundaryFilter, cursorFilter);
|
||||
const candidates = await db
|
||||
.select()
|
||||
.select({ workspace: executionWorkspaces, cursorAt: sql<string>`${executionWorkspaces.updatedAt}::text` })
|
||||
.from(executionWorkspaces)
|
||||
.where(scanFilter)
|
||||
.orderBy(asc(executionWorkspaces.updatedAt), asc(executionWorkspaces.id))
|
||||
@@ -3335,7 +3329,7 @@ export function executionWorkspaceService(db: Db, opts: ExecutionWorkspaceServic
|
||||
terminalSweepBoundary = null;
|
||||
} else {
|
||||
const lastCandidate = candidates[candidates.length - 1]!;
|
||||
terminalSweepCursor = { updatedAt: lastCandidate.updatedAt, id: lastCandidate.id };
|
||||
terminalSweepCursor = { updatedAt: lastCandidate.cursorAt, id: lastCandidate.workspace.id };
|
||||
}
|
||||
const result = {
|
||||
checked: candidates.length,
|
||||
@@ -3355,7 +3349,8 @@ export function executionWorkspaceService(db: Db, opts: ExecutionWorkspaceServic
|
||||
};
|
||||
const readinessByWorkingTree = new Map<string, ReturnType<typeof inspectGitCloseReadiness>>();
|
||||
|
||||
for (let workspace of candidates) {
|
||||
for (const candidate of candidates) {
|
||||
let workspace = candidate.workspace;
|
||||
signal?.throwIfAborted();
|
||||
// Trash deletion is part of compaction, so a sweep that skips compaction
|
||||
// also leaves leftover trash for a later sweep.
|
||||
|
||||
Reference in new issue
Block a user