fix(web): resolve approval card race condition with polling
Race condition between polling (5s interval) and sign/reject operations caused cards to flicker and reappear after being approved. Fix: - Pause polling during sign/reject API calls - Resume polling after 1 second delay to allow backend state sync - Apply same pattern to both signApproval and rejectApproval Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -176,6 +176,14 @@ export const useApprovalStore = create<ApprovalState>()(
|
||||
// Sign Approval
|
||||
// ==========================================================================
|
||||
signApproval: async (id, signerId, signerName, comment) => {
|
||||
// 🔧 Race Condition 修復: 簽核期間暫停 Polling
|
||||
const wasPolling = pollingTimer !== null
|
||||
if (wasPolling) {
|
||||
clearInterval(pollingTimer!)
|
||||
pollingTimer = null
|
||||
console.log('[Approval] Polling paused during sign')
|
||||
}
|
||||
|
||||
set({ signingId: id, error: null })
|
||||
|
||||
try {
|
||||
@@ -219,6 +227,14 @@ export const useApprovalStore = create<ApprovalState>()(
|
||||
}
|
||||
})
|
||||
|
||||
// 🔧 Race Condition 修復: 延遲 1 秒後恢復 Polling,讓後端有時間更新
|
||||
if (wasPolling) {
|
||||
setTimeout(() => {
|
||||
get().startPolling(get().pollingInterval || DEFAULT_POLLING_INTERVAL)
|
||||
console.log('[Approval] Polling resumed after sign')
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
return result
|
||||
} catch (err) {
|
||||
console.error('[Approval] Sign failed:', err)
|
||||
@@ -226,6 +242,13 @@ export const useApprovalStore = create<ApprovalState>()(
|
||||
signingId: null,
|
||||
error: `Sign failed: ${err}`,
|
||||
})
|
||||
|
||||
// 🔧 失敗也要恢復 Polling
|
||||
if (wasPolling) {
|
||||
get().startPolling(get().pollingInterval || DEFAULT_POLLING_INTERVAL)
|
||||
console.log('[Approval] Polling resumed after sign error')
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
},
|
||||
@@ -234,6 +257,14 @@ export const useApprovalStore = create<ApprovalState>()(
|
||||
// Reject Approval
|
||||
// ==========================================================================
|
||||
rejectApproval: async (id, rejectorId, rejectorName, reason) => {
|
||||
// 🔧 Race Condition 修復: 拒絕期間暫停 Polling
|
||||
const wasPolling = pollingTimer !== null
|
||||
if (wasPolling) {
|
||||
clearInterval(pollingTimer!)
|
||||
pollingTimer = null
|
||||
console.log('[Approval] Polling paused during reject')
|
||||
}
|
||||
|
||||
set({ rejectingId: id, error: null })
|
||||
|
||||
try {
|
||||
@@ -266,6 +297,14 @@ export const useApprovalStore = create<ApprovalState>()(
|
||||
}
|
||||
})
|
||||
|
||||
// 🔧 Race Condition 修復: 延遲 1 秒後恢復 Polling
|
||||
if (wasPolling) {
|
||||
setTimeout(() => {
|
||||
get().startPolling(get().pollingInterval || DEFAULT_POLLING_INTERVAL)
|
||||
console.log('[Approval] Polling resumed after reject')
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error('[Approval] Reject failed:', err)
|
||||
@@ -273,6 +312,13 @@ export const useApprovalStore = create<ApprovalState>()(
|
||||
rejectingId: null,
|
||||
error: `Reject failed: ${err}`,
|
||||
})
|
||||
|
||||
// 🔧 失敗也要恢復 Polling
|
||||
if (wasPolling) {
|
||||
get().startPolling(get().pollingInterval || DEFAULT_POLLING_INTERVAL)
|
||||
console.log('[Approval] Polling resumed after reject error')
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user