fix race condition caused by race condition fix

This commit is contained in:
keyan 2023-07-11 13:33:13 -05:00
parent 0ff4da1a4f
commit bc9081eaab
1 changed files with 49 additions and 48 deletions

View File

@ -6,7 +6,7 @@ import ActionTooltip from './action-tooltip'
import ItemAct from './item-act' import ItemAct from './item-act'
import { useMe } from './me' import { useMe } from './me'
import Rainbow from '../lib/rainbow' import Rainbow from '../lib/rainbow'
import { useCallback, useEffect, useRef, useState } from 'react' import { useEffect, useMemo, useRef, useState } from 'react'
import LongPressable from 'react-longpressable' import LongPressable from 'react-longpressable'
import { Overlay, Popover } from 'react-bootstrap' import { Overlay, Popover } from 'react-bootstrap'
import { useShowModal } from './modal' import { useShowModal } from './modal'
@ -78,8 +78,6 @@ export default function UpVote ({ item, className, pendingSats, setPendingSats }
}` }`
) )
const fwd2me = me && Number(me?.id) === item?.fwdUserId
const setVoteShow = (yes) => { const setVoteShow = (yes) => {
if (!me) return if (!me) return
@ -117,8 +115,6 @@ export default function UpVote ({ item, className, pendingSats, setPendingSats }
} }
}`, { }`, {
update (cache, { data: { act: { sats } } }) { update (cache, { data: { act: { sats } } }) {
setPendingSats(0)
cache.modify({ cache.modify({
id: `Item:${item.id}`, id: `Item:${item.id}`,
fields: { fields: {
@ -155,27 +151,28 @@ export default function UpVote ({ item, className, pendingSats, setPendingSats }
} }
) )
// prevent updating pendingSats after unmount
useEffect(() => {
return () => { timerRef.current = null }
}, [])
// if we want to use optimistic response, we need to buffer the votes // if we want to use optimistic response, we need to buffer the votes
// because if someone votes in quick succession, responses come back out of order // because if someone votes in quick succession, responses come back out of order
// so we wait a bit to see if there are more votes coming in // so we wait a bit to see if there are more votes coming in
// this effectively performs our own debounced optimistic response // this effectively performs our own debounced optimistic response
const bufferVotes = useCallback((sats) => { useEffect(() => {
if (timerRef.current) { if (timerRef.current) {
clearTimeout(timerRef.current) clearTimeout(timerRef.current)
} }
timerRef.current = setTimeout(async (pendingSats, sats) => { if (pendingSats > 0) {
timerRef.current = setTimeout(async (pendingSats) => {
try { try {
timerRef.current && setPendingSats(0)
await act({ await act({
variables: { id: item.id, sats: pendingSats + sats } variables: { id: item.id, sats: pendingSats },
optimisticResponse: {
act: {
sats: pendingSats
}
}
}) })
} catch (error) { } catch (error) {
timerRef.current && setPendingSats(0)
if (error.toString().includes('insufficient funds')) { if (error.toString().includes('insufficient funds')) {
showModal(onClose => { showModal(onClose => {
return <FundError onClose={onClose} /> return <FundError onClose={onClose} />
@ -184,11 +181,20 @@ export default function UpVote ({ item, className, pendingSats, setPendingSats }
} }
throw new Error({ message: error.toString() }) throw new Error({ message: error.toString() })
} }
}, 1000, pendingSats, sats) }, 1000, pendingSats)
}
timerRef.current && setPendingSats(pendingSats + sats) return () => {
clearTimeout(timerRef.current)
timerRef.current = null
}
}, [item, pendingSats, act, setPendingSats, showModal]) }, [item, pendingSats, act, setPendingSats, showModal])
const disabled = useMemo(() => {
return item?.mine || (me && Number(me.id) === item?.fwdUserId) || item?.deletedAt
}, [me?.id, item?.fwdUserId, item?.mine, item?.deletedAt])
const [meSats, sats, overlayText, color] = useMemo(() => {
const meSats = (item?.meSats || 0) + pendingSats const meSats = (item?.meSats || 0) + pendingSats
// what should our next tip be? // what should our next tip be?
@ -202,13 +208,9 @@ export default function UpVote ({ item, className, pendingSats, setPendingSats }
sats = raiseTip - meSats sats = raiseTip - meSats
} }
const overlayText = () => { return [meSats, sats, `${sats} sat${sats > 1 ? 's' : ''}`, getColor(meSats)]
return `${sats} sat${sats > 1 ? 's' : ''}` }, [item?.meSats, pendingSats, me?.tipDefault, me?.turboDefault])
}
const disabled = item?.mine || fwd2me || item?.deletedAt
const color = getColor(meSats)
return ( return (
<LightningConsumer> <LightningConsumer>
{({ strike }) => {({ strike }) =>
@ -244,7 +246,7 @@ export default function UpVote ({ item, className, pendingSats, setPendingSats }
strike() strike()
bufferVotes(sats) setPendingSats(pendingSats + sats)
} }
: async () => await router.push({ : async () => await router.push({
pathname: '/signup', pathname: '/signup',
@ -252,10 +254,9 @@ export default function UpVote ({ item, className, pendingSats, setPendingSats }
}) })
} }
> >
<ActionTooltip notForm disable={disabled} overlayText={overlayText()}> <ActionTooltip notForm disable={disabled} overlayText={overlayText}>
<div <div
className={`${disabled ? styles.noSelfTips : ''} className={`${disabled ? styles.noSelfTips : ''} ${styles.upvoteWrapper}`}
${styles.upvoteWrapper}`}
> >
<UpBolt <UpBolt
width={24} width={24}