fix(v026): #10 restoreNote 가 failed 노트 시 pending_jobs 재생성
restore 가 deleted_at = NULL 만 했음 → ai_status='failed' 인 노트는 영구 fail 상태로 복구. atomic transaction 안에서 ai_status='pending' reset + INSERT OR IGNORE INTO pending_jobs. - failed → pending + pending_jobs 재처리 path 복구 - done 은 영향 X (이미 결과 있음) - pending 은 pending_jobs 재생성 (defensive — trash 도중 jobs 미정상 상태 가능) - 단위 +3 cases (failed/done/pending 각 케이스) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -267,6 +267,49 @@ describe('NoteRepository', () => {
|
||||
repo.updateAiResult(d, { title: 't', summary: 'a\nb\nc', tags: ['x'], dueDate: todayKst, provider: 'p' });
|
||||
expect(repo.findRecallCandidate()?.id).toBe(d);
|
||||
});
|
||||
|
||||
it('restoreNote re-enqueues failed note (ai_status reset to pending + pending_jobs INSERT)', () => {
|
||||
const id = repo.create({ rawText: 'x' }).id;
|
||||
repo.markAiFailed(id, 'unreachable');
|
||||
repo.trash(id, new Date().toISOString());
|
||||
expect(repo.findById(id)!.aiStatus).toBe('failed');
|
||||
|
||||
repo.restoreNote(id);
|
||||
|
||||
const after = repo.findById(id)!;
|
||||
expect(after.deletedAt).toBeNull();
|
||||
expect(after.aiStatus).toBe('pending');
|
||||
expect(after.aiError).toBeNull();
|
||||
const job = db.prepare('SELECT * FROM pending_jobs WHERE note_id=?').get(id);
|
||||
expect(job).toBeDefined();
|
||||
});
|
||||
|
||||
it('restoreNote does not re-enqueue done note', () => {
|
||||
const id = repo.create({ rawText: 'x' }).id;
|
||||
repo.updateAiResult(id, { title: 't', summary: 'a\nb\nc', tags: ['x'], provider: 'p' });
|
||||
repo.trash(id, new Date().toISOString());
|
||||
expect(repo.findById(id)!.aiStatus).toBe('done');
|
||||
|
||||
repo.restoreNote(id);
|
||||
|
||||
expect(repo.findById(id)!.aiStatus).toBe('done');
|
||||
const job = db.prepare('SELECT * FROM pending_jobs WHERE note_id=?').get(id);
|
||||
expect(job).toBeUndefined();
|
||||
});
|
||||
|
||||
it('restoreNote re-enqueues pending note (defensive)', () => {
|
||||
const id = repo.create({ rawText: 'x' }).id;
|
||||
// 인공적으로 pending_jobs 비운 후 trash
|
||||
db.prepare('DELETE FROM pending_jobs WHERE note_id=?').run(id);
|
||||
repo.trash(id, new Date().toISOString());
|
||||
expect(repo.findById(id)!.aiStatus).toBe('pending');
|
||||
|
||||
repo.restoreNote(id);
|
||||
|
||||
expect(repo.findById(id)!.aiStatus).toBe('pending');
|
||||
const job = db.prepare('SELECT * FROM pending_jobs WHERE note_id=?').get(id);
|
||||
expect(job).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('NoteRepository.trash', () => {
|
||||
|
||||
Reference in New Issue
Block a user