Move reads into firebase transaction

This commit is contained in:
Ian Philips 2022-06-29 17:41:03 -05:00
parent 7b83a3c7c9
commit 03a1c82c54
5 changed files with 53 additions and 44 deletions

View File

@ -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,

View File

@ -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

View File

@ -42,7 +42,7 @@ function ReferralsDialog(props: {
const { user, referralIds, isOpen, setIsOpen } = props
useEffect(() => {
prefetchUsers([...referralIds])
prefetchUsers(referralIds)
}, [referralIds])
return (

View File

@ -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)

View File

@ -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
}