fix: moderation fixes (#6952)

* fix: skip deleted projects

* fix: remove unnesecary blocker
This commit is contained in:
Calum H.
2026-08-04 21:33:17 +00:00
committed by GitHub
parent 540b3269df
commit f42a3bfde3
@@ -777,11 +777,17 @@ function isEligibleQueueCandidate(result: QueueCandidateCheck | undefined): bool
return !result.locked || !!result.expired || !!result.isOwnLock return !result.locked || !!result.expired || !!result.isOwnLock
} }
function isNotFoundError(error: unknown): boolean {
if (!error || typeof error !== 'object') return false
const fetchError = error as { statusCode?: number; response?: { status?: number } }
return fetchError.statusCode === 404 || fetchError.response?.status === 404
}
function notifySkippedQueueProjects(count: number) { function notifySkippedQueueProjects(count: number) {
if (count <= 0) return if (count <= 0) return
addNotification({ addNotification({
title: 'Skipped projects', title: 'Skipped projects',
text: `Skipped ${count} project(s) already moderated or locked by others.`, text: `Skipped ${count} project(s) already moderated, deleted, or locked by others.`,
type: 'info', type: 'info',
autoCloseMs: 2000, autoCloseMs: 2000,
}) })
@@ -812,10 +818,10 @@ async function batchCheckQueueCandidates(
projectIds.map(async (id) => { projectIds.map(async (id) => {
const [lockResponse, projectData] = await Promise.all([ const [lockResponse, projectData] = await Promise.all([
moderationQueue.checkLock(id), moderationQueue.checkLock(id),
useBaseFetch(`project/${id}`, { method: 'GET' }).catch(() => null), useBaseFetch(`project/${id}`, { method: 'GET' }),
]) ])
const status = (projectData as { status?: string } | null)?.status const status = (projectData as { status?: string }).status
return { return {
id, id,
@@ -825,7 +831,7 @@ async function batchCheckQueueCandidates(
slug: (projectData as { slug?: string } | null)?.slug, slug: (projectData as { slug?: string } | null)?.slug,
projectType: (projectData as { project_type?: string } | null)?.project_type, projectType: (projectData as { project_type?: string } | null)?.project_type,
status, status,
isProcessing: projectData === null ? true : status === 'processing', isProcessing: status === 'processing',
} }
}), }),
) )
@@ -833,6 +839,8 @@ async function batchCheckQueueCandidates(
checks.forEach((result, index) => { checks.forEach((result, index) => {
if (result.status === 'fulfilled') { if (result.status === 'fulfilled') {
results.set(result.value.id, result.value) results.set(result.value.id, result.value)
} else if (isNotFoundError(result.reason)) {
results.set(projectIds[index], { locked: false, isProcessing: false })
} else { } else {
results.set(projectIds[index], { locked: false, isProcessing: true }) results.set(projectIds[index], { locked: false, isProcessing: true })
} }
@@ -979,7 +987,7 @@ async function skipToNextProject() {
debug('[skipToNextProject] No eligible projects in queue') debug('[skipToNextProject] No eligible projects in queue')
addNotification({ addNotification({
title: 'No projects available', title: 'No projects available',
text: 'All remaining projects are already moderated or locked by others.', text: 'All remaining projects are already moderated, deleted, or locked by others.',
type: 'warning', type: 'warning',
}) })
} }
@@ -1649,9 +1657,15 @@ async function sendMessage(status: ProjectStatus) {
} }
} }
await refreshModerationCaches(threadId)
const willHaveNext = await moderationQueue.completeCurrentProject(projectId, 'completed') const willHaveNext = await moderationQueue.completeCurrentProject(projectId, 'completed')
// Set both states together - hasNextProject MUST be set before done
// to avoid the race condition where done=true renders with hasNextProject=false
hasNextProject.value = willHaveNext
done.value = true
clearGeneratedMessageState()
await nextTick()
await refreshModerationCaches(threadId)
await Promise.race([ await Promise.race([
moderationQueue.releaseLock(projectId), moderationQueue.releaseLock(projectId),
@@ -1661,16 +1675,9 @@ async function sendMessage(status: ProjectStatus) {
if (projectFixChanges?.slug) { if (projectFixChanges?.slug) {
const urlType = getProjectTypeForUrlShorthand(projectV2.value.project_type, [], tags.value) const urlType = getProjectTypeForUrlShorthand(projectV2.value.project_type, [], tags.value)
localStorage.setItem('moderation-checklist-finished', projectId) localStorage.setItem('moderation-checklist-finished', projectId)
clearGeneratedMessageState()
await navigateTo(`/${urlType}/${projectFixChanges.slug}/moderation`, { replace: true }) await navigateTo(`/${urlType}/${projectFixChanges.slug}/moderation`, { replace: true })
return return
} }
// Set both states together - hasNextProject MUST be set before done
// to avoid the race condition where done=true renders with hasNextProject=false
hasNextProject.value = willHaveNext
done.value = true
clearGeneratedMessageState()
} catch (error) { } catch (error) {
console.error('Error submitting moderation:', error) console.error('Error submitting moderation:', error)
addNotification({ addNotification({
@@ -1733,7 +1740,7 @@ async function endChecklist(status?: string) {
) )
addNotification({ addNotification({
title: 'No projects available', title: 'No projects available',
text: 'All remaining projects are already moderated or locked by others.', text: 'All remaining projects are already moderated, deleted, or locked by others.',
type: 'warning', type: 'warning',
}) })
} }