Fix race condition: deduplicate startMutation calls between autosave and submit
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m5s
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m5s
Use a shared startPromiseRef so autosave and handleSubmit reuse the same in-flight "create evaluation" promise instead of firing duplicate requests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,7 @@ export default function JuryEvaluatePage({ params: paramsPromise }: PageProps) {
|
|||||||
const isSubmittedRef = useRef(false)
|
const isSubmittedRef = useRef(false)
|
||||||
const isSubmittingRef = useRef(false)
|
const isSubmittingRef = useRef(false)
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||||
|
const startPromiseRef = useRef<Promise<{ id: string }> | null>(null)
|
||||||
const autosaveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
const autosaveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||||
const [lastSavedAt, setLastSavedAt] = useState<Date | null>(null)
|
const [lastSavedAt, setLastSavedAt] = useState<Date | null>(null)
|
||||||
|
|
||||||
@@ -211,11 +212,17 @@ export default function JuryEvaluatePage({ params: paramsPromise }: PageProps) {
|
|||||||
let evalId = evaluationIdRef.current
|
let evalId = evaluationIdRef.current
|
||||||
if (!evalId && myAssignment) {
|
if (!evalId && myAssignment) {
|
||||||
try {
|
try {
|
||||||
const newEval = await startMutation.mutateAsync({ assignmentId: myAssignment.id })
|
// Reuse in-flight start promise to avoid duplicate creation
|
||||||
|
if (!startPromiseRef.current) {
|
||||||
|
startPromiseRef.current = startMutation.mutateAsync({ assignmentId: myAssignment.id })
|
||||||
|
}
|
||||||
|
const newEval = await startPromiseRef.current
|
||||||
evalId = newEval.id
|
evalId = newEval.id
|
||||||
evaluationIdRef.current = evalId
|
evaluationIdRef.current = evalId
|
||||||
} catch {
|
} catch {
|
||||||
return
|
return
|
||||||
|
} finally {
|
||||||
|
startPromiseRef.current = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!evalId) return
|
if (!evalId) return
|
||||||
@@ -297,7 +304,11 @@ export default function JuryEvaluatePage({ params: paramsPromise }: PageProps) {
|
|||||||
|
|
||||||
let evaluationId = evaluationIdRef.current
|
let evaluationId = evaluationIdRef.current
|
||||||
if (!evaluationId) {
|
if (!evaluationId) {
|
||||||
const newEval = await startMutation.mutateAsync({ assignmentId: myAssignment.id })
|
if (!startPromiseRef.current) {
|
||||||
|
startPromiseRef.current = startMutation.mutateAsync({ assignmentId: myAssignment.id })
|
||||||
|
}
|
||||||
|
const newEval = await startPromiseRef.current
|
||||||
|
startPromiseRef.current = null
|
||||||
evaluationId = newEval.id
|
evaluationId = newEval.id
|
||||||
evaluationIdRef.current = evaluationId
|
evaluationIdRef.current = evaluationId
|
||||||
}
|
}
|
||||||
@@ -384,9 +395,14 @@ export default function JuryEvaluatePage({ params: paramsPromise }: PageProps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reuse in-flight start promise to avoid duplicate creation (e.g. if autosave is mid-flight)
|
||||||
let evaluationId = evaluationIdRef.current
|
let evaluationId = evaluationIdRef.current
|
||||||
if (!evaluationId) {
|
if (!evaluationId) {
|
||||||
const newEval = await startMutation.mutateAsync({ assignmentId: myAssignment.id })
|
if (!startPromiseRef.current) {
|
||||||
|
startPromiseRef.current = startMutation.mutateAsync({ assignmentId: myAssignment.id })
|
||||||
|
}
|
||||||
|
const newEval = await startPromiseRef.current
|
||||||
|
startPromiseRef.current = null
|
||||||
evaluationId = newEval.id
|
evaluationId = newEval.id
|
||||||
evaluationIdRef.current = evaluationId
|
evaluationIdRef.current = evaluationId
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user