Skip to content

Commit a1ad1ac

Browse files
jony376cursoragent
andauthored
fix(miner): treat repeat markDone as a no-op (#2891)
Only transition portfolio rows that are not already done and return null when no row changed, matching releaseClaim semantics. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent a715135 commit a1ad1ac

2 files changed

Lines changed: 19 additions & 3 deletions

File tree

packages/gittensory-miner/lib/portfolio-queue.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ export function initPortfolioQueueStore(dbPath = resolvePortfolioQueueDbPath())
124124
)
125125
RETURNING *
126126
`);
127-
const setStatusStatement = db.prepare(
128-
"UPDATE miner_portfolio_queue SET status = ? WHERE repo_full_name = ? AND identifier = ?",
127+
const markDoneStatement = db.prepare(
128+
"UPDATE miner_portfolio_queue SET status = 'done' WHERE repo_full_name = ? AND identifier = ? AND status <> 'done'",
129129
);
130130
const listAllStatement = db.prepare(`SELECT * FROM miner_portfolio_queue ${ORDER}`);
131131
const listRepoStatement = db.prepare(
@@ -155,7 +155,8 @@ export function initPortfolioQueueStore(dbPath = resolvePortfolioQueueDbPath())
155155
markDone(repoFullName, identifier) {
156156
const normalizedRepo = normalizeRepoFullName(repoFullName);
157157
const normalizedIdentifier = normalizeIdentifier(identifier);
158-
setStatusStatement.run("done", normalizedRepo, normalizedIdentifier);
158+
const result = markDoneStatement.run(normalizedRepo, normalizedIdentifier);
159+
if (result.changes === 0) return null;
159160
const row = getStatement.get(normalizedRepo, normalizedIdentifier);
160161
return row ? rowToEntry(row) : null;
161162
},

test/unit/miner-portfolio-queue.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,21 @@ describe("gittensory-miner portfolio/queue store (#2292)", () => {
8888
expect(store.markDone("o/a", "missing")).toBeNull(); // no such row → null branch
8989
});
9090

91+
it("markDone is a no-op when the item is already done", () => {
92+
const store = tempStore();
93+
store.enqueue({ repoFullName: "o/a", identifier: "x", priority: 1 });
94+
expect(store.markDone("o/a", "x")?.status).toBe("done");
95+
expect(store.markDone("o/a", "x")).toBeNull();
96+
});
97+
98+
it("markDone transitions in-progress items to done", () => {
99+
const store = tempStore();
100+
store.enqueue({ repoFullName: "o/a", identifier: "work", priority: 1 });
101+
expect(store.dequeueNext()?.status).toBe("in_progress");
102+
expect(store.markDone("o/a", "work")?.status).toBe("done");
103+
expect(store.markDone("o/a", "work")).toBeNull();
104+
});
105+
91106
it("isolates listQueue by repo and lists everything when unfiltered", () => {
92107
const store = tempStore();
93108
store.enqueue({ repoFullName: "o/a", identifier: "1", priority: 1 });

0 commit comments

Comments
 (0)