Leaderboard calc: update profit even when portfolio didn't change (#845)

* Leaderboard calc: remove didProfitChange optimization that was incorrect

* Put back didPortfolioChange for deciding whether to create new history doc.
This commit is contained in:
James Grugett 2022-09-02 15:59:32 -05:00 committed by GitHub
parent b6449ad296
commit 00de66cd79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,13 +1,12 @@
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 { groupBy, isEmpty, keyBy, sum, sumBy } from 'lodash' import { groupBy, isEmpty, keyBy, last, sortBy, sum, sumBy } from 'lodash'
import { getValues, log, logMemory, writeAsync } from './utils' import { getValues, log, logMemory, writeAsync } from './utils'
import { Bet } from '../../common/bet' import { Bet } from '../../common/bet'
import { Contract } from '../../common/contract' import { Contract } from '../../common/contract'
import { PortfolioMetrics, User } from '../../common/user' import { PortfolioMetrics, User } from '../../common/user'
import { calculatePayout } from '../../common/calculate' import { calculatePayout } from '../../common/calculate'
import { DAY_MS } from '../../common/util/time' import { DAY_MS } from '../../common/util/time'
import { last } from 'lodash'
import { getLoanUpdates } from '../../common/loans' import { getLoanUpdates } from '../../common/loans'
const firestore = admin.firestore() const firestore = admin.firestore()
@ -88,23 +87,20 @@ export const updateMetricsCore = async () => {
currentBets currentBets
) )
const lastPortfolio = last(portfolioHistory) const lastPortfolio = last(portfolioHistory)
const didProfitChange = const didPortfolioChange =
lastPortfolio === undefined || lastPortfolio === undefined ||
lastPortfolio.balance !== newPortfolio.balance || lastPortfolio.balance !== newPortfolio.balance ||
lastPortfolio.totalDeposits !== newPortfolio.totalDeposits || lastPortfolio.totalDeposits !== newPortfolio.totalDeposits ||
lastPortfolio.investmentValue !== newPortfolio.investmentValue lastPortfolio.investmentValue !== newPortfolio.investmentValue
const newProfit = calculateNewProfit( const newProfit = calculateNewProfit(portfolioHistory, newPortfolio)
portfolioHistory,
newPortfolio,
didProfitChange
)
return { return {
user, user,
newCreatorVolume, newCreatorVolume,
newPortfolio, newPortfolio,
newProfit, newProfit,
didProfitChange, didPortfolioChange,
} }
}) })
@ -120,16 +116,20 @@ export const updateMetricsCore = async () => {
const nextLoanByUser = keyBy(userPayouts, (payout) => payout.user.id) const nextLoanByUser = keyBy(userPayouts, (payout) => payout.user.id)
const userUpdates = userMetrics.map( const userUpdates = userMetrics.map(
({ user, newCreatorVolume, newPortfolio, newProfit, didProfitChange }) => { ({
user,
newCreatorVolume,
newPortfolio,
newProfit,
didPortfolioChange,
}) => {
const nextLoanCached = nextLoanByUser[user.id]?.payout ?? 0 const nextLoanCached = nextLoanByUser[user.id]?.payout ?? 0
return { return {
fieldUpdates: { fieldUpdates: {
doc: firestore.collection('users').doc(user.id), doc: firestore.collection('users').doc(user.id),
fields: { fields: {
creatorVolumeCached: newCreatorVolume, creatorVolumeCached: newCreatorVolume,
...(didProfitChange && {
profitCached: newProfit, profitCached: newProfit,
}),
nextLoanCached, nextLoanCached,
}, },
}, },
@ -140,11 +140,7 @@ export const updateMetricsCore = async () => {
.doc(user.id) .doc(user.id)
.collection('portfolioHistory') .collection('portfolioHistory')
.doc(), .doc(),
fields: { fields: didPortfolioChange ? newPortfolio : {},
...(didProfitChange && {
...newPortfolio,
}),
},
}, },
} }
} }
@ -171,15 +167,15 @@ const computeVolume = (contractBets: Bet[], since: number) => {
const calculateProfitForPeriod = ( const calculateProfitForPeriod = (
startTime: number, startTime: number,
portfolioHistory: PortfolioMetrics[], descendingPortfolio: PortfolioMetrics[],
currentProfit: number currentProfit: number
) => { ) => {
const startingPortfolio = [...portfolioHistory] const startingPortfolio = descendingPortfolio.find(
.reverse() // so we search in descending order (most recent first), for efficiency (p) => p.timestamp < startTime
.find((p) => p.timestamp < startTime) )
if (startingPortfolio === undefined) { if (startingPortfolio === undefined) {
return 0 return currentProfit
} }
const startingProfit = calculateTotalProfit(startingPortfolio) const startingProfit = calculateTotalProfit(startingPortfolio)
@ -233,28 +229,28 @@ const calculateNewPortfolioMetrics = (
const calculateNewProfit = ( const calculateNewProfit = (
portfolioHistory: PortfolioMetrics[], portfolioHistory: PortfolioMetrics[],
newPortfolio: PortfolioMetrics, newPortfolio: PortfolioMetrics
didProfitChange: boolean
) => { ) => {
if (!didProfitChange) {
return {} // early return for performance
}
const allTimeProfit = calculateTotalProfit(newPortfolio) const allTimeProfit = calculateTotalProfit(newPortfolio)
const descendingPortfolio = sortBy(
portfolioHistory,
(p) => p.timestamp
).reverse()
const newProfit = { const newProfit = {
daily: calculateProfitForPeriod( daily: calculateProfitForPeriod(
Date.now() - 1 * DAY_MS, Date.now() - 1 * DAY_MS,
portfolioHistory, descendingPortfolio,
allTimeProfit allTimeProfit
), ),
weekly: calculateProfitForPeriod( weekly: calculateProfitForPeriod(
Date.now() - 7 * DAY_MS, Date.now() - 7 * DAY_MS,
portfolioHistory, descendingPortfolio,
allTimeProfit allTimeProfit
), ),
monthly: calculateProfitForPeriod( monthly: calculateProfitForPeriod(
Date.now() - 30 * DAY_MS, Date.now() - 30 * DAY_MS,
portfolioHistory, descendingPortfolio,
allTimeProfit allTimeProfit
), ),
allTime: allTimeProfit, allTime: allTimeProfit,