Move reads into firebase transaction
This commit is contained in:
parent
7b83a3c7c9
commit
03a1c82c54
|
@ -2,7 +2,6 @@ import * as functions from 'firebase-functions'
|
|||
import * as admin from 'firebase-admin'
|
||||
import { REFERRAL_AMOUNT, User } from '../../common/user'
|
||||
import { HOUSE_LIQUIDITY_PROVIDER_ID } from '../../common/antes'
|
||||
import { getValues, getContract } from './utils'
|
||||
import { createNotification } from './create-notification'
|
||||
import { ReferralTxn, Txn } from '../../common/txn'
|
||||
import { Contract } from '../../common/contract'
|
||||
|
@ -29,37 +28,46 @@ async function handleUserUpdatedReferral(user: User, eventId: string) {
|
|||
}
|
||||
const referredByUserId = user.referredByUserId
|
||||
|
||||
// get user that referred this user
|
||||
const referredByUserDoc = firestore.doc(`users/${referredByUserId}`)
|
||||
const referredByUserSnap = await referredByUserDoc.get()
|
||||
if (!referredByUserSnap.exists) {
|
||||
console.log(`User ${referredByUserId} not found`)
|
||||
return
|
||||
}
|
||||
const referredByUser = referredByUserSnap.data() as User
|
||||
|
||||
let referredByContract: Contract | undefined = undefined
|
||||
if (user.referredByContractId)
|
||||
referredByContract = await getContract(user.referredByContractId)
|
||||
console.log(`referredByContract: ${referredByContract}`)
|
||||
|
||||
const txnQuery = firestore
|
||||
.collection('txns')
|
||||
.where('toId', '==', referredByUserId)
|
||||
.where('category', '==', 'REFERRAL')
|
||||
const referralTxns = await getValues<Txn>(txnQuery).catch((err) => {
|
||||
console.error('error getting txns:', err)
|
||||
throw err
|
||||
})
|
||||
// If the referring user already has a referral txn due to referring this user, halt
|
||||
if (referralTxns.map((txn) => txn.description).includes(user.id)) {
|
||||
console.log('found referral txn with the same details, aborting')
|
||||
return
|
||||
}
|
||||
console.log('creating referral txns')
|
||||
const fromId = HOUSE_LIQUIDITY_PROVIDER_ID
|
||||
|
||||
await firestore.runTransaction(async (transaction) => {
|
||||
// get user that referred this user
|
||||
const referredByUserDoc = firestore.doc(`users/${referredByUserId}`)
|
||||
const referredByUserSnap = await transaction.get(referredByUserDoc)
|
||||
if (!referredByUserSnap.exists) {
|
||||
console.log(`User ${referredByUserId} not found`)
|
||||
return
|
||||
}
|
||||
const referredByUser = referredByUserSnap.data() as User
|
||||
|
||||
let referredByContract: Contract | undefined = undefined
|
||||
if (user.referredByContractId) {
|
||||
const referredByContractDoc = firestore.doc(
|
||||
`contracts/${user.referredByContractId}`
|
||||
)
|
||||
referredByContract = await transaction
|
||||
.get(referredByContractDoc)
|
||||
.then((snap) => snap.data() as Contract)
|
||||
}
|
||||
console.log(`referredByContract: ${referredByContract}`)
|
||||
|
||||
const txns = (
|
||||
await firestore
|
||||
.collection('txns')
|
||||
.where('toId', '==', referredByUserId)
|
||||
.where('category', '==', 'REFERRAL')
|
||||
.get()
|
||||
).docs.map((txn) => txn.ref)
|
||||
const referralTxns = await transaction.getAll(...txns).catch((err) => {
|
||||
console.error('error getting txns:', err)
|
||||
throw err
|
||||
})
|
||||
// If the referring user already has a referral txn due to referring this user, halt
|
||||
if (referralTxns.map((txn) => txn.data()?.description).includes(user.id)) {
|
||||
console.log('found referral txn with the same details, aborting')
|
||||
return
|
||||
}
|
||||
console.log('creating referral txns')
|
||||
const fromId = HOUSE_LIQUIDITY_PROVIDER_ID
|
||||
|
||||
// if they're updating their referredId, create a txn for both
|
||||
const txn: ReferralTxn = {
|
||||
id: eventId,
|
||||
|
|
|
@ -22,7 +22,7 @@ import { TweetButton } from '../tweet-button'
|
|||
import { InfoTooltip } from '../info-tooltip'
|
||||
import { TagsInput } from 'web/components/tags-input'
|
||||
|
||||
export const ContractDetailsButtonClassName =
|
||||
export const contractDetailsButtonClassName =
|
||||
'group flex items-center rounded-md px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-100 text-gray-400 hover:text-gray-500'
|
||||
|
||||
export function ContractInfoDialog(props: { contract: Contract; bets: Bet[] }) {
|
||||
|
@ -50,7 +50,7 @@ export function ContractInfoDialog(props: { contract: Contract; bets: Bet[] }) {
|
|||
return (
|
||||
<>
|
||||
<button
|
||||
className={ContractDetailsButtonClassName}
|
||||
className={contractDetailsButtonClassName}
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
<DotsHorizontalIcon
|
||||
|
|
|
@ -42,7 +42,7 @@ function ReferralsDialog(props: {
|
|||
const { user, referralIds, isOpen, setIsOpen } = props
|
||||
|
||||
useEffect(() => {
|
||||
prefetchUsers([...referralIds])
|
||||
prefetchUsers(referralIds)
|
||||
}, [referralIds])
|
||||
|
||||
return (
|
||||
|
|
|
@ -8,7 +8,7 @@ import { contractPath } from 'web/lib/firebase/contracts'
|
|||
import { ENV_CONFIG } from 'common/envs/constants'
|
||||
import { ToastClipboard } from 'web/components/toast-clipboard'
|
||||
import { track } from 'web/lib/service/analytics'
|
||||
import { ContractDetailsButtonClassName } from 'web/components/contract/contract-info-dialog'
|
||||
import { contractDetailsButtonClassName } from 'web/components/contract/contract-info-dialog'
|
||||
import { Group } from 'common/group'
|
||||
import { groupPath } from 'web/lib/firebase/groups'
|
||||
|
||||
|
@ -49,7 +49,7 @@ export function ShareIconButton(props: {
|
|||
return (
|
||||
<div className="relative z-10 flex-shrink-0">
|
||||
<button
|
||||
className={clsx(ContractDetailsButtonClassName, buttonClassName)}
|
||||
className={clsx(contractDetailsButtonClassName, buttonClassName)}
|
||||
onClick={() => {
|
||||
if (contract) copyContractWithReferral(contract, username)
|
||||
if (group) copyGroupWithReferral(group, username)
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
updateDoc,
|
||||
where,
|
||||
} from 'firebase/firestore'
|
||||
import { sortBy } from 'lodash'
|
||||
import { sortBy, uniq } from 'lodash'
|
||||
import { Group } from 'common/group'
|
||||
import { getContractFromId } from './contracts'
|
||||
import { db } from './init'
|
||||
|
@ -98,12 +98,13 @@ export async function getGroupsWithContractId(
|
|||
export async function addUserToGroupViaSlug(groupSlug: string, userId: string) {
|
||||
// get group to get the member ids
|
||||
const group = await getGroupBySlug(groupSlug)
|
||||
if (group && !group.memberIds.includes(userId))
|
||||
return await updateGroup(group, {
|
||||
memberIds: [userId, ...group.memberIds],
|
||||
})
|
||||
return null
|
||||
if (!group) {
|
||||
console.error(`Group not found: ${groupSlug}`)
|
||||
return
|
||||
}
|
||||
return await joinGroup(group, userId)
|
||||
}
|
||||
|
||||
export async function joinGroup(group: Group, userId: string): Promise<Group> {
|
||||
const { memberIds } = group
|
||||
if (memberIds.includes(userId)) {
|
||||
|
@ -111,7 +112,7 @@ export async function joinGroup(group: Group, userId: string): Promise<Group> {
|
|||
}
|
||||
const newMemberIds = [...memberIds, userId]
|
||||
const newGroup = { ...group, memberIds: newMemberIds }
|
||||
await updateGroup(newGroup, { memberIds: newMemberIds })
|
||||
await updateGroup(newGroup, { memberIds: uniq(newMemberIds) })
|
||||
return newGroup
|
||||
}
|
||||
export async function leaveGroup(group: Group, userId: string): Promise<Group> {
|
||||
|
@ -121,6 +122,6 @@ export async function leaveGroup(group: Group, userId: string): Promise<Group> {
|
|||
}
|
||||
const newMemberIds = memberIds.filter((id) => id !== userId)
|
||||
const newGroup = { ...group, memberIds: newMemberIds }
|
||||
await updateGroup(newGroup, { memberIds: newMemberIds })
|
||||
await updateGroup(newGroup, { memberIds: uniq(newMemberIds) })
|
||||
return newGroup
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user