Skip to content

Commit

Permalink
chore(sdk): improve cache performance of getPrice (#304)
Browse files Browse the repository at this point in the history
  • Loading branch information
zfy0701 authored Jan 28, 2023
1 parent f6ee979 commit 0b4f1cc
Showing 1 changed file with 41 additions and 49 deletions.
90 changes: 41 additions & 49 deletions packages/sdk/src/utils/price.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PriceServiceClient, PriceServiceDefinition } from '@sentio/protos/lib/service/price/protos/price'
import { CoinID, PriceServiceClient, PriceServiceDefinition } from '@sentio/protos/lib/service/price/protos/price'
import { createChannel, createClientFactory } from 'nice-grpc'
import { retryMiddleware, RetryOptions } from 'nice-grpc-client-middleware-retry'
import { Endpoints } from '@sentio/runtime'
Expand All @@ -12,83 +12,75 @@ export function getPriceClient(address?: string) {
return createClientFactory().use(retryMiddleware).create(PriceServiceDefinition, channel)
}

const priceMap = new Map<string, number>()
const priceMap = new Map<string, Promise<number>>()
let priceClient: PriceServiceClient<RetryOptions>

/**
*
* @param chainId chain id refers to CHAIN_MAP
* @param coinType
* @param date
*/
export async function getPriceByType(chainId: string, coinType: string, date: Date): Promise<number> {
export async function getPriceByTypeOrSymbol(date: Date, coinId: CoinID): Promise<number> {
if (!priceClient) {
priceClient = getPriceClient()
}

const dateStr = dateString(date)
const key = `${coinType}-${dateStr}`
const todayDateString = dateString(new Date())

let key: string
if (coinId.symbol) {
key = `${coinId.symbol}-${dateStr}`
} else {
key = `${coinId.address?.address}-${coinId.address?.chain}-${dateStr}`
}
let price = priceMap.get(key)
if (price) {
return price
}

const response = await priceClient.getPrice(
const response = priceClient.getPrice(
{
timestamp: date,
coinId: {
address: {
chain: chainId,
address: coinType,
},
},
coinId,
},
{
retry: true,
retryMaxAttempts: 8,
}
)
price = response.price
if (response.timestamp && dateString(response.timestamp) === dateStr) {
priceMap.set(key, price)
}
price = response.then((res) => {
if (res.timestamp) {
const responseDateString = dateString(res.timestamp)
if (responseDateString !== dateStr || responseDateString !== todayDateString) {
priceMap.delete(key)
}
} else {
priceMap.delete(key)
}
return res.price
})
priceMap.set(key, price)
return price
}

/**
*
* @param chainId chain id refers to CHAIN_MAP
* @param coinType
* @param date
*/
async function getPriceByType(chainId: string, coinType: string, date: Date): Promise<number> {
return getPriceByTypeOrSymbol(date, {
address: {
chain: chainId,
address: coinType,
},
})
}

/**
*
* @param symbol token symbol like BTC, etc
* @param date
*/
export async function getPriceBySymbol(symbol: string, date: Date): Promise<number> {
if (!priceClient) {
priceClient = getPriceClient()
}

const dateStr = dateString(date)
const key = `${symbol}-${dateStr}`
let price = priceMap.get(key)
if (price) {
return price
}

const response = await priceClient.getPrice(
{
timestamp: date,
coinId: {
symbol,
},
},
{
retry: true,
retryMaxAttempts: 8,
}
)
price = response.price
if (response.timestamp && dateString(response.timestamp) === dateStr) {
priceMap.set(key, price)
}
return price
return getPriceByTypeOrSymbol(date, { symbol })
}

function dateString(date: Date) {
Expand Down

0 comments on commit 0b4f1cc

Please sign in to comment.