mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
fix: address roomote review concerns
- Improve calculateTaskStorageSize() logging to show actual error message instead of generic 'directory not found' - Serialize task deletions when using provider-backed deleteTaskById to avoid taskHistory state race conditions (parallel deletion kept for filesystem-only operations)
This commit is contained in:
parent
9c92200cf2
commit
30f2aa2546
2 changed files with 56 additions and 45 deletions
|
|
@ -246,7 +246,7 @@ export async function purgeOldTasks(
|
|||
return { purgedCount: 0, cutoff }
|
||||
}
|
||||
|
||||
// Phase 3: Delete tasks in parallel
|
||||
// Phase 3: Delete tasks
|
||||
if (dryRun) {
|
||||
for (const { metadata, reason } of tasksToDelete) {
|
||||
logv(`[Retention][DRY RUN] Would delete task ${metadata.taskId} (${reason}) @ ${metadata.taskDir}`)
|
||||
|
|
@ -257,52 +257,61 @@ export async function purgeOldTasks(
|
|||
return { purgedCount: tasksToDelete.length, cutoff }
|
||||
}
|
||||
|
||||
logv(`[Retention] Phase 3: Deleting ${tasksToDelete.length} tasks (concurrency: ${DELETION_CONCURRENCY})`)
|
||||
const deleteLimit = pLimit(DELETION_CONCURRENCY)
|
||||
// Helper function to delete a single task
|
||||
const deleteTask = async (metadata: TaskMetadata, reason: string): Promise<boolean> => {
|
||||
let deleted = false
|
||||
|
||||
const deleteResults = await Promise.all(
|
||||
tasksToDelete.map(({ metadata, reason }) =>
|
||||
deleteLimit(async (): Promise<boolean> => {
|
||||
let deleted = false
|
||||
try {
|
||||
if (deleteTaskById) {
|
||||
logv(`[Retention] Deleting task ${metadata.taskId} via provider @ ${metadata.taskDir} (${reason})`)
|
||||
await deleteTaskById(metadata.taskId, metadata.taskDir)
|
||||
deleted = !(await pathExists(metadata.taskDir))
|
||||
} else {
|
||||
logv(`[Retention] Deleting task ${metadata.taskId} via fs.rm @ ${metadata.taskDir} (${reason})`)
|
||||
await fs.rm(metadata.taskDir, { recursive: true, force: true })
|
||||
deleted = !(await pathExists(metadata.taskDir))
|
||||
}
|
||||
} catch (e) {
|
||||
// Primary deletion failed, try fallback
|
||||
logv(
|
||||
`[Retention] Primary deletion failed for ${metadata.taskId}: ${
|
||||
e instanceof Error ? e.message : String(e)
|
||||
}`,
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
if (deleteTaskById) {
|
||||
logv(
|
||||
`[Retention] Deleting task ${metadata.taskId} via provider @ ${metadata.taskDir} (${reason})`,
|
||||
)
|
||||
await deleteTaskById(metadata.taskId, metadata.taskDir)
|
||||
deleted = !(await pathExists(metadata.taskDir))
|
||||
} else {
|
||||
logv(`[Retention] Deleting task ${metadata.taskId} via fs.rm @ ${metadata.taskDir} (${reason})`)
|
||||
await fs.rm(metadata.taskDir, { recursive: true, force: true })
|
||||
deleted = !(await pathExists(metadata.taskDir))
|
||||
}
|
||||
} catch (e) {
|
||||
// Primary deletion failed, try fallback
|
||||
logv(
|
||||
`[Retention] Primary deletion failed for ${metadata.taskId}: ${
|
||||
e instanceof Error ? e.message : String(e)
|
||||
}`,
|
||||
)
|
||||
}
|
||||
// Fallback: simplified removal
|
||||
if (!deleted) {
|
||||
deleted = await removeDir(metadata.taskDir)
|
||||
}
|
||||
|
||||
// Fallback: simplified removal
|
||||
if (!deleted) {
|
||||
deleted = await removeDir(metadata.taskDir)
|
||||
}
|
||||
if (!deleted) {
|
||||
log?.(`[Retention] Failed to delete task ${metadata.taskId} @ ${metadata.taskDir}: directory still present`)
|
||||
} else {
|
||||
logv(`[Retention] Deleted task ${metadata.taskId} (${reason}) @ ${metadata.taskDir}`)
|
||||
}
|
||||
|
||||
if (!deleted) {
|
||||
log?.(
|
||||
`[Retention] Failed to delete task ${metadata.taskId} @ ${metadata.taskDir}: directory still present`,
|
||||
)
|
||||
} else {
|
||||
logv(`[Retention] Deleted task ${metadata.taskId} (${reason}) @ ${metadata.taskDir}`)
|
||||
}
|
||||
return deleted
|
||||
}
|
||||
|
||||
return deleted
|
||||
}),
|
||||
),
|
||||
)
|
||||
let deleteResults: boolean[]
|
||||
|
||||
if (deleteTaskById) {
|
||||
// Sequential deletion when using provider-backed deletion to avoid taskHistory state races
|
||||
logv(`[Retention] Phase 3: Deleting ${tasksToDelete.length} tasks sequentially (provider-backed)`)
|
||||
deleteResults = []
|
||||
for (const { metadata, reason } of tasksToDelete) {
|
||||
const result = await deleteTask(metadata, reason)
|
||||
deleteResults.push(result)
|
||||
}
|
||||
} else {
|
||||
// Parallel deletion for filesystem-only operations (no shared state)
|
||||
logv(`[Retention] Phase 3: Deleting ${tasksToDelete.length} tasks (concurrency: ${DELETION_CONCURRENCY})`)
|
||||
const deleteLimit = pLimit(DELETION_CONCURRENCY)
|
||||
deleteResults = await Promise.all(
|
||||
tasksToDelete.map(({ metadata, reason }) => deleteLimit(() => deleteTask(metadata, reason))),
|
||||
)
|
||||
}
|
||||
|
||||
const purged = deleteResults.filter(Boolean).length
|
||||
|
||||
|
|
|
|||
|
|
@ -51,9 +51,11 @@ export async function calculateTaskStorageSize(
|
|||
try {
|
||||
const entries = await fs.readdir(tasksDir, { withFileTypes: true })
|
||||
taskCount = entries.filter((d) => d.isDirectory()).length
|
||||
} catch {
|
||||
// Tasks directory doesn't exist yet
|
||||
log?.(`[TaskStorageSize] Tasks directory not found at ${tasksDir}`)
|
||||
} catch (e) {
|
||||
// Tasks directory doesn't exist yet (or is unreadable)
|
||||
log?.(
|
||||
`[TaskStorageSize] Failed to read tasks directory at ${tasksDir}: ${e instanceof Error ? e.message : String(e)}`,
|
||||
)
|
||||
return defaultResult
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue