fix cache key bloat

This commit is contained in:
k00b 2024-10-06 17:58:46 -05:00
parent 177e0f6bb0
commit 154c0e0a4a
7 changed files with 32 additions and 24 deletions

View File

@ -108,9 +108,9 @@ export function getPaymentFailureStatus (withdrawal) {
} }
} }
export const getBlockHeight = cachedFetcher(async () => { export const getBlockHeight = cachedFetcher(async ({ lnd, ...args }) => {
try { try {
const { current_block_height: height } = await getHeight({ lnd }) const { current_block_height: height } = await getHeight({ lnd, ...args })
return height return height
} catch (err) { } catch (err) {
throw new Error(`Unable to fetch block height: ${err.message}`) throw new Error(`Unable to fetch block height: ${err.message}`)
@ -118,12 +118,13 @@ export const getBlockHeight = cachedFetcher(async () => {
}, { }, {
maxSize: 1, maxSize: 1,
cacheExpiry: 60 * 1000, // 1 minute cacheExpiry: 60 * 1000, // 1 minute
forceRefreshThreshold: 5 * 60 * 1000 // 5 minutes forceRefreshThreshold: 5 * 60 * 1000, // 5 minutes
keyGenerator: () => 'getHeight'
}) })
export const getOurPubkey = cachedFetcher(async () => { export const getOurPubkey = cachedFetcher(async ({ lnd, ...args }) => {
try { try {
const { identity } = await getIdentity({ lnd }) const { identity } = await getIdentity({ lnd, ...args })
return identity.public_key return identity.public_key
} catch (err) { } catch (err) {
throw new Error(`Unable to fetch identity: ${err.message}`) throw new Error(`Unable to fetch identity: ${err.message}`)
@ -131,19 +132,24 @@ export const getOurPubkey = cachedFetcher(async () => {
}, { }, {
maxSize: 1, maxSize: 1,
cacheExpiry: 0, // never expire cacheExpiry: 0, // never expire
forceRefreshThreshold: 0 // never force refresh forceRefreshThreshold: 0, // never force refresh
keyGenerator: () => 'getOurPubkey'
}) })
export const getNodeInfo = cachedFetcher(async (args) => { export const getNodeSockets = cachedFetcher(async ({ lnd, ...args }) => {
try { try {
return await getNode({ lnd, ...args }) return (await getNode({ lnd, is_omitting_channels: true, ...args }))?.sockets
} catch (err) { } catch (err) {
throw new Error(`Unable to fetch node info: ${err.message}`) throw new Error(`Unable to fetch node info: ${err.message}`)
} }
}, { }, {
maxSize: 1000, maxSize: 100,
cacheExpiry: 1000 * 60 * 60 * 24, // 1 day cacheExpiry: 1000 * 60 * 60 * 24, // 1 day
forceRefreshThreshold: 1000 * 60 * 60 * 24 * 7 // 1 week forceRefreshThreshold: 1000 * 60 * 60 * 24 * 7, // 1 week
keyGenerator: (args) => {
const { public_key: publicKey } = args
return publicKey
}
}) })
export default lnd export default lnd

View File

@ -13,7 +13,8 @@ const getBlockHeight = cachedFetcher(async ({ lnd }) => {
}, { }, {
maxSize: 1, maxSize: 1,
cacheExpiry: 60 * 1000, // 1 minute cacheExpiry: 60 * 1000, // 1 minute
forceRefreshThreshold: 0 forceRefreshThreshold: 0,
keyGenerator: () => 'getBlockHeight'
}) })
export default { export default {

View File

@ -13,7 +13,8 @@ const getChainFeeRate = cachedFetcher(async () => {
}, { }, {
maxSize: 1, maxSize: 1,
cacheExpiry: 60 * 1000, // 1 minute cacheExpiry: 60 * 1000, // 1 minute
forceRefreshThreshold: 0 // never force refresh forceRefreshThreshold: 0, // never force refresh
keyGenerator: () => 'getChainFeeRate'
}) })
export default { export default {

View File

@ -1,8 +1,7 @@
import { SUPPORTED_CURRENCIES } from '@/lib/currency' import { SUPPORTED_CURRENCIES } from '@/lib/currency'
import { cachedFetcher } from '@/lib/fetch' import { cachedFetcher } from '@/lib/fetch'
const getPrice = cachedFetcher(async (fiat) => { const getPrice = cachedFetcher(async (fiat = 'USD') => {
fiat ??= 'USD'
const url = `https://api.coinbase.com/v2/prices/BTC-${fiat}/spot` const url = `https://api.coinbase.com/v2/prices/BTC-${fiat}/spot`
try { try {
const res = await fetch(url) const res = await fetch(url)
@ -15,7 +14,8 @@ const getPrice = cachedFetcher(async (fiat) => {
}, { }, {
maxSize: SUPPORTED_CURRENCIES.length, maxSize: SUPPORTED_CURRENCIES.length,
cacheExpiry: 60 * 1000, // 1 minute cacheExpiry: 60 * 1000, // 1 minute
forceRefreshThreshold: 0 // never force refresh forceRefreshThreshold: 0, // never force refresh
keyGenerator: (fiat = 'USD') => fiat
}) })
export default { export default {

View File

@ -22,7 +22,7 @@ import walletDefs from 'wallets/server'
import { generateResolverName, generateTypeDefName } from '@/lib/wallet' import { generateResolverName, generateTypeDefName } from '@/lib/wallet'
import { lnAddrOptions } from '@/lib/lnurl' import { lnAddrOptions } from '@/lib/lnurl'
import { GqlAuthenticationError, GqlAuthorizationError, GqlInputError } from '@/lib/error' import { GqlAuthenticationError, GqlAuthorizationError, GqlInputError } from '@/lib/error'
import { getNodeInfo, getOurPubkey } from '../lnd' import { getNodeSockets, getOurPubkey } from '../lnd'
function injectResolvers (resolvers) { function injectResolvers (resolvers) {
console.group('injected GraphQL resolvers:') console.group('injected GraphQL resolvers:')
@ -723,7 +723,7 @@ export async function createWithdrawal (parent, { invoice, maxFee }, { me, model
invoice = invoice.replace(/^lightning:/, '') invoice = invoice.replace(/^lightning:/, '')
// decode invoice to get amount // decode invoice to get amount
let decoded, node let decoded, sockets
try { try {
decoded = await parsePaymentRequest({ request: invoice }) decoded = await parsePaymentRequest({ request: invoice })
} catch (error) { } catch (error) {
@ -732,14 +732,14 @@ export async function createWithdrawal (parent, { invoice, maxFee }, { me, model
} }
try { try {
node = await getNodeInfo({ public_key: decoded.destination, is_omitting_channels: true }) sockets = await getNodeSockets({ lnd, public_key: decoded.destination })
} catch (error) { } catch (error) {
// likely not found if it's an unannounced channel, e.g. phoenix // likely not found if it's an unannounced channel, e.g. phoenix
console.log(error) console.log(error)
} }
if (node) { if (sockets) {
for (const { socket } of node.sockets) { for (const { socket } of sockets) {
const ip = socket.split(':')[0] const ip = socket.split(':')[0]
await assertGofacYourself({ models, headers, ip }) await assertGofacYourself({ models, headers, ip })
} }
@ -835,7 +835,7 @@ export async function fetchLnAddrInvoice (
// decode invoice // decode invoice
try { try {
const decoded = await parsePaymentRequest({ request: res.pr }) const decoded = await parsePaymentRequest({ request: res.pr })
const ourPubkey = await getOurPubkey() const ourPubkey = await getOurPubkey({ lnd })
if (autoWithdraw && decoded.destination === ourPubkey && process.env.NODE_ENV === 'production') { if (autoWithdraw && decoded.destination === ourPubkey && process.env.NODE_ENV === 'production') {
// unset lnaddr so we don't trigger another withdrawal with same destination // unset lnaddr so we don't trigger another withdrawal with same destination
await models.wallet.deleteMany({ await models.wallet.deleteMany({

View File

@ -36,11 +36,11 @@ class LRUCache {
} }
} }
export function cachedFetcher (fetcher, { maxSize = 100, cacheExpiry, forceRefreshThreshold }) { export function cachedFetcher (fetcher, { maxSize = 100, cacheExpiry, forceRefreshThreshold, keyGenerator }) {
const cache = new LRUCache(maxSize) const cache = new LRUCache(maxSize)
return async function cachedFetch (...args) { return async function cachedFetch (...args) {
const key = JSON.stringify(args) const key = keyGenerator ? keyGenerator(...args) : JSON.stringify(args)
const now = Date.now() const now = Date.now()
async function fetchAndCache () { async function fetchAndCache () {

View File

@ -131,7 +131,7 @@ export default async function wrapInvoice (bolt11, { msats, description, descrip
timeout: FEE_ESTIMATE_TIMEOUT_SECS timeout: FEE_ESTIMATE_TIMEOUT_SECS
}) })
const blockHeight = await getBlockHeight() const blockHeight = await getBlockHeight({ lnd })
/* /*
we want the incoming invoice to have MIN_SETTLEMENT_CLTV_DELTA higher final cltv delta than we want the incoming invoice to have MIN_SETTLEMENT_CLTV_DELTA higher final cltv delta than
the expected ctlv_delta of the outgoing invoice's entire route the expected ctlv_delta of the outgoing invoice's entire route