fix: fix race condition in poll loop#190
Conversation
There was a problem hiding this comment.
Greptile Summary
This PR fixes a race condition in the sf buy command's order polling mechanism. The issue occurred when the polling loop would re-enter after an order was already filled, potentially causing API errors if the GET /orders request failed during redundant polling attempts.
The fix involves two key changes to the useEffect hook in src/lib/buy/index.tsx:
-
Replaced
setIntervalwith recursivesetTimeout: The original implementation usedsetIntervalwhich could create multiple overlapping polling requests. The new approach uses a recursivesetTimeoutpattern where each poll completion schedules the next poll, ensuring only one polling operation is active at any time. -
Changed dependency from
ordertoorder?.id: TheuseEffectdependency array now usesorder?.idinstead oforder. This prevents the effect from re-running whensetOrder(o)updates the order object with the same ID, which was a primary cause of the race condition.
The refactored polling logic maintains the same 200ms polling interval but with cleaner lifecycle management. When an order is successfully retrieved, exit() is called immediately without scheduling another poll, ensuring the polling stops cleanly once the order is filled. This change integrates well with the existing React component architecture and maintains the same user experience while eliminating the timing issues that could cause premature errors.
Confidence score: 4/5
- This PR is safe to merge with minimal risk as it addresses a specific race condition with a well-reasoned solution
- Score reflects solid understanding of the problem and appropriate React patterns, though the timeout-based approach could benefit from additional testing
- Pay close attention to the useEffect dependency change to ensure it doesn't affect other parts of the component lifecycle
1 file reviewed, no comments
Sometimes
sf buyre-enters its poll loop after the order is already filled. IfGET /v0/ordersfails when that occurs,sf buywill error out, even though the order successfully filled.This PR attempts to fix this by doing two things:
setTimeoutinstead of asetInterval. That way, there will only ever be one poll happening at a time, which prevents redundant polls (the call toexit()will happen before theuseEffectis re-run)order?.idas the dependency to theuseEffect, notorder. This will prevent theuseEffectfrom being run after callingsetOrder(o), because the order ID will be the same.