feat(retry): NoteRepository — findFailedIds/countFailed/retryAllFailed/setNextRunAt (#2 v0.2.3)
This commit is contained in:
@@ -156,6 +156,65 @@ export class NoteRepository {
|
||||
tx();
|
||||
}
|
||||
|
||||
findFailedIds(): string[] {
|
||||
const rows = this.db
|
||||
.prepare(
|
||||
`SELECT id FROM notes WHERE ai_status='failed' AND deleted_at IS NULL ORDER BY updated_at DESC, id DESC`
|
||||
)
|
||||
.all() as Array<{ id: string }>;
|
||||
return rows.map((r) => r.id);
|
||||
}
|
||||
|
||||
countFailed(): number {
|
||||
const row = this.db
|
||||
.prepare(
|
||||
`SELECT COUNT(*) AS c FROM notes WHERE ai_status='failed' AND deleted_at IS NULL`
|
||||
)
|
||||
.get() as { c: number };
|
||||
return row.c;
|
||||
}
|
||||
|
||||
/**
|
||||
* 모든 ai_status='failed' (active) 노트를 'pending' 으로 reset 하고 pending_jobs 재투입.
|
||||
* 단일 transaction. v0.2.3 #2 retryAllFailed.
|
||||
*
|
||||
* INSERT OR IGNORE 로 race 안전 (이미 pending_jobs row 존재 시 skip).
|
||||
*/
|
||||
retryAllFailed(now: string): { ids: string[] } {
|
||||
const ids: string[] = [];
|
||||
const tx = this.db.transaction(() => {
|
||||
const rows = this.db
|
||||
.prepare(`SELECT id FROM notes WHERE ai_status='failed' AND deleted_at IS NULL`)
|
||||
.all() as Array<{ id: string }>;
|
||||
if (rows.length === 0) return;
|
||||
const reset = this.db.prepare(
|
||||
`UPDATE notes SET ai_status='pending', ai_error=NULL, updated_at=? WHERE id=?`
|
||||
);
|
||||
const insert = this.db.prepare(
|
||||
`INSERT OR IGNORE INTO pending_jobs (note_id, attempts, next_run_at) VALUES (?, 0, ?)`
|
||||
);
|
||||
for (const r of rows) {
|
||||
reset.run(now, r.id);
|
||||
insert.run(r.id, now);
|
||||
ids.push(r.id);
|
||||
}
|
||||
});
|
||||
tx();
|
||||
return { ids };
|
||||
}
|
||||
|
||||
/**
|
||||
* pending_jobs 의 next_run_at + last_error 만 갱신, attempts 변경 없음.
|
||||
* v0.2.3 #2 — unreachable/timeout 무한 retry 시 사용 (incrementJobAttempt 와 별도 경로).
|
||||
*/
|
||||
setNextRunAt(noteId: string, nextRunAt: string, lastError: string): void {
|
||||
this.db
|
||||
.prepare(
|
||||
`UPDATE pending_jobs SET next_run_at=?, last_error=? WHERE note_id=?`
|
||||
)
|
||||
.run(nextRunAt, lastError.slice(0, 500), noteId);
|
||||
}
|
||||
|
||||
updateUserAiFields(
|
||||
id: string,
|
||||
fields: { title?: string; summary?: string; tags?: string[] }
|
||||
|
||||
Reference in New Issue
Block a user