Optimize updateContractMetrics (#476)

* Don't query bets repeatedly

* Don't read entire database of contracts for no reason

* Fix lint
This commit is contained in:
Marshall Polaris 2022-06-10 21:00:09 -07:00 committed by GitHub
parent 3a6960c71b
commit d8dc91d4b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,9 +1,8 @@
import * as functions from 'firebase-functions' import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin' import * as admin from 'firebase-admin'
import { sumBy } from 'lodash' import { max, sumBy } from 'lodash'
import { getValues } from './utils' import { getValues } from './utils'
import { Contract } from '../../common/contract'
import { Bet } from '../../common/bet' import { Bet } from '../../common/bet'
import { batchedWaitAll } from '../../common/util/promise' import { batchedWaitAll } from '../../common/util/promise'
@ -14,17 +13,14 @@ const oneDay = 1000 * 60 * 60 * 24
export const updateContractMetrics = functions.pubsub export const updateContractMetrics = functions.pubsub
.schedule('every 15 minutes') .schedule('every 15 minutes')
.onRun(async () => { .onRun(async () => {
const contracts = await getValues<Contract>( const contractDocs = await firestore.collection('contracts').listDocuments()
firestore.collection('contracts')
)
await batchedWaitAll( await batchedWaitAll(
contracts.map((contract) => async () => { contractDocs.map((doc) => async () => {
const volume24Hours = await computeVolumeFrom(contract, oneDay) const [volume24Hours, volume7Days] = await computeVolumes(doc.id, [
const volume7Days = await computeVolumeFrom(contract, oneDay * 7) oneDay,
oneDay * 7,
const contractRef = firestore.doc(`contracts/${contract.id}`) ])
return contractRef.update({ return doc.update({
volume24Hours, volume24Hours,
volume7Days, volume7Days,
}) })
@ -32,12 +28,17 @@ export const updateContractMetrics = functions.pubsub
) )
}) })
const computeVolumeFrom = async (contract: Contract, timeAgoMs: number) => { const computeVolumes = async (contractId: string, durationsMs: number[]) => {
const bets = await getValues<Bet>( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const longestDurationMs = max(durationsMs)!
const allBets = await getValues<Bet>(
firestore firestore
.collection(`contracts/${contract.id}/bets`) .collection(`contracts/${contractId}/bets`)
.where('createdTime', '>', Date.now() - timeAgoMs) .where('createdTime', '>', Date.now() - longestDurationMs)
) )
return durationsMs.map((duration) => {
return sumBy(bets, (bet) => (bet.isRedemption ? 0 : Math.abs(bet.amount))) const cutoff = Date.now() - duration
const bets = allBets.filter((b) => b.createdTime > cutoff)
return sumBy(bets, (bet) => (bet.isRedemption ? 0 : Math.abs(bet.amount)))
})
} }