From 28e3d1b2b64d827890cd0faa0741a081679bf804 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Mon, 10 Oct 2022 14:12:37 -0500 Subject: [PATCH] Fetch less data for portfolio query --- common/calculate-metrics.ts | 36 ++++++---------------- functions/src/update-metrics.ts | 54 +++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 36 deletions(-) diff --git a/common/calculate-metrics.ts b/common/calculate-metrics.ts index 9cd1a57a..47fccd86 100644 --- a/common/calculate-metrics.ts +++ b/common/calculate-metrics.ts @@ -1,4 +1,4 @@ -import { Dictionary, groupBy, last, sortBy, sum, sumBy, uniq } from 'lodash' +import { Dictionary, groupBy, last, sum, sumBy, uniq } from 'lodash' import { calculatePayout, getContractBetMetrics } from './calculate' import { Bet, LimitBet } from './bet' import { @@ -199,14 +199,9 @@ export const calculateNewPortfolioMetrics = ( } const calculateProfitForPeriod = ( - startTime: number, - descendingPortfolio: PortfolioMetrics[], + startingPortfolio: PortfolioMetrics | undefined, currentProfit: number ) => { - const startingPortfolio = descendingPortfolio.find( - (p) => p.timestamp < startTime - ) - if (startingPortfolio === undefined) { return currentProfit } @@ -221,31 +216,18 @@ export const calculatePortfolioProfit = (portfolio: PortfolioMetrics) => { } export const calculateNewProfit = ( - portfolioHistory: PortfolioMetrics[], + portfolioHistory: Record< + 'current' | 'day' | 'week' | 'month', + PortfolioMetrics | undefined + >, newPortfolio: PortfolioMetrics ) => { const allTimeProfit = calculatePortfolioProfit(newPortfolio) - const descendingPortfolio = sortBy( - portfolioHistory, - (p) => p.timestamp - ).reverse() const newProfit = { - daily: calculateProfitForPeriod( - Date.now() - 1 * DAY_MS, - descendingPortfolio, - allTimeProfit - ), - weekly: calculateProfitForPeriod( - Date.now() - 7 * DAY_MS, - descendingPortfolio, - allTimeProfit - ), - monthly: calculateProfitForPeriod( - Date.now() - 30 * DAY_MS, - descendingPortfolio, - allTimeProfit - ), + daily: calculateProfitForPeriod(portfolioHistory.day, allTimeProfit), + weekly: calculateProfitForPeriod(portfolioHistory.week, allTimeProfit), + monthly: calculateProfitForPeriod(portfolioHistory.month, allTimeProfit), allTime: allTimeProfit, } diff --git a/functions/src/update-metrics.ts b/functions/src/update-metrics.ts index 39faadbf..fcaf9f08 100644 --- a/functions/src/update-metrics.ts +++ b/functions/src/update-metrics.ts @@ -1,6 +1,6 @@ import * as functions from 'firebase-functions' import * as admin from 'firebase-admin' -import { groupBy, keyBy, last, sortBy } from 'lodash' +import { groupBy, keyBy, sortBy } from 'lodash' import fetch from 'node-fetch' import { getValues, log, logMemory, writeAsync } from './utils' @@ -60,11 +60,7 @@ export async function updateMetricsCore() { const contracts = await getValues(firestore.collection('contracts')) console.log('Loading portfolio history') - const allPortfolioHistories = await getValues( - firestore - .collectionGroup('portfolioHistory') - .where('timestamp', '>', Date.now() - 31 * DAY_MS) // so it includes just over a month ago - ) + const userPortfolioHistory = await loadPortfolioHistory(users) console.log('Loading groups') const groups = await getValues(firestore.collection('groups')) @@ -141,11 +137,10 @@ export async function updateMetricsCore() { ) const contractsByUser = groupBy(contracts, (contract) => contract.creatorId) const betsByUser = groupBy(bets, (bet) => bet.userId) - const portfolioHistoryByUser = groupBy(allPortfolioHistories, (p) => p.userId) const userMetrics = users.map((user) => { const currentBets = betsByUser[user.id] ?? [] - const portfolioHistory = portfolioHistoryByUser[user.id] ?? [] + const portfolioHistory = userPortfolioHistory[user.id] ?? [] const userContracts = contractsByUser[user.id] ?? [] const newCreatorVolume = calculateCreatorVolume(userContracts) const newPortfolio = calculateNewPortfolioMetrics( @@ -153,7 +148,7 @@ export async function updateMetricsCore() { contractsById, currentBets ) - const lastPortfolio = last(portfolioHistory) + const lastPortfolio = portfolioHistory.current const didPortfolioChange = lastPortfolio === undefined || lastPortfolio.balance !== newPortfolio.balance || @@ -301,3 +296,44 @@ const topUserScores = (scores: { [userId: string]: number }) => { type GroupContractDoc = { contractId: string; createdTime: number } const BAD_RESOLUTION_THRESHOLD = 0.1 + +const loadPortfolioHistory = async (users: User[]) => { + const now = Date.now() + const userPortfolioHistory = await batchedWaitAll( + users.map((user) => async () => { + const query = firestore + .collection('users') + .doc(user.id) + .collection('portfolioHistory') + .orderBy('timestamp', 'desc') + .limit(1) + + const portfolioMetrics = await Promise.all([ + getValues(query), + getValues( + query.where('timestamp', '<', now - DAY_MS) + ), + getValues( + query.where('timestamp', '<', now - 7 * DAY_MS) + ), + getValues( + query.where('timestamp', '<', now - 30 * DAY_MS) + ), + ]) + const [current, day, week, month] = portfolioMetrics.map( + (p) => p[0] as PortfolioMetrics | undefined + ) + + return { + userId: user.id, + current, + day, + week, + month, + } + }), + 100 + ) + + return keyBy(userPortfolioHistory, (p) => p.userId) +}