Skip to content

Commit df686d4

Browse files
authored
Merge pull request #118 from EdgeApp/paul/fixMapSync
Run setupCurrencyCodeMapsSync at startup
2 parents 60b0a85 + 6a846f6 commit df686d4

File tree

3 files changed

+60
-12
lines changed

3 files changed

+60
-12
lines changed

src/exchangeRateRouter.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { mul } from 'biggystring'
1+
import { div, eq, mul } from 'biggystring'
22
import { asArray, asMaybe, asObject, asOptional, asString } from 'cleaners'
33
import express from 'express'
44
import nano from 'nano'
@@ -7,7 +7,7 @@ import promisify from 'promisify-node'
77

88
import { config } from './config'
99
import { REDIS_COINRANK_KEY_PREFIX } from './constants'
10-
import { asReturnGetRate, getExchangeRates } from './rates'
10+
import { asReturnGetRate, getExchangeRates, PRECISION } from './rates'
1111
import {
1212
asCoinrankAssetReq,
1313
asCoinrankReq,
@@ -293,13 +293,46 @@ const queryExchangeRates: express.RequestHandler = async (
293293
return next()
294294
}
295295

296+
const flippedAssets: { [key: string]: true } = {}
297+
298+
// To prevent redudant rate requests and storage, sort the assets in alphabetical order
299+
// ie. iso:USD_BTC -> BTC_iso:USD. Mark any flipped assets with the flippedAssets flag true
300+
// so we can flip them back later.
301+
const normalizedRequestedRates = exReq.requestedRates.data.map(req => {
302+
const [assetA, assetB] = req.currency_pair.split('_')
303+
if (assetA > assetB) {
304+
const flippedPair = `${assetB}_${assetA}`
305+
flippedAssets[`${flippedPair}_${req.date}`] = true
306+
return { ...req, currency_pair: flippedPair }
307+
}
308+
return req
309+
})
310+
296311
try {
297312
const queriedRates = await getExchangeRates(
298-
exReq.requestedRates.data,
313+
normalizedRequestedRates,
299314
dbRates
300315
)
316+
const unflippedRates = queriedRates.data.map(rate => {
317+
const key = `${rate.currency_pair}_${rate.date}`
318+
if (flippedAssets[key] === true) {
319+
delete flippedAssets[key]
320+
const [assetA, assetB] = rate.currency_pair.split('_')
321+
const unflippedPair = `${assetB}_${assetA}`
322+
if (rate.exchangeRate != null) {
323+
if (eq(rate.exchangeRate, '0')) {
324+
rate.exchangeRate = '0'
325+
} else {
326+
const unflippedRate = div('1', rate.exchangeRate, PRECISION)
327+
rate.exchangeRate = unflippedRate
328+
}
329+
}
330+
return { ...rate, currency_pair: unflippedPair }
331+
}
332+
return rate
333+
})
301334
exReq.requestedRatesResult = {
302-
data: [...(exReq.requestedRatesResult?.data ?? []), ...queriedRates.data],
335+
data: [...(exReq.requestedRatesResult?.data ?? []), ...unflippedRates],
303336
documents: [...queriedRates.documents] // TODO: Change data type since the douch docs aren't needed after this
304337
}
305338
} catch (e) {

src/rates.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ import {
3939
checkConstantCode,
4040
currencyCodeArray,
4141
fromCode,
42-
getNullRateArray,
43-
invertPair,
44-
isNotANumber,
42+
getNullRateArray, isNotANumber,
4543
logger,
4644
normalizeDate,
4745
safeUpperCase,
@@ -115,9 +113,10 @@ const sanitizeNewRates = (
115113
}
116114

117115
rateMap[pairCodes] = rate
118-
rateMap[invertPair(pairCodes)] = eq(rate, '0')
119-
? '0'
120-
: div('1', rate, PRECISION)
116+
// Save storage by not saving the inverted pair
117+
// rateMap[invertPair(pairCodes)] = eq(rate, '0')
118+
// ? '0'
119+
// : div('1', rate, PRECISION)
121120
}
122121

123122
return rateMap

src/utils/currencyCodeMapsSync.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { asArray, asMaybe, asObject, asString } from 'cleaners'
22
import { syncedDocument } from 'edge-server-tools'
3+
import nano from 'nano'
34

5+
import { config } from '../config'
46
import currencyCodeMaps from './currencyCodeMaps.json'
57
import { hsetAsync } from './dbUtils'
68
import { logger } from './utils'
@@ -24,6 +26,8 @@ const asCurrencyCodeMaps = asMaybe(
2426
defaultCurrencyCodeMaps
2527
)
2628

29+
type CurrencyCodeMaps = ReturnType<typeof asCurrencyCodeMaps>
30+
2731
export const syncedCurrencyCodeMaps = syncedDocument(
2832
'currencyCodeMaps',
2933
asCurrencyCodeMaps
@@ -37,8 +41,11 @@ export const ratesDbSetup = {
3741
}
3842

3943
// Set up the sync logic - this will only run in the indexEngines process
44+
const nanoDb = nano(config.couchUri)
45+
const dbRates = nanoDb.db.use('db_rates')
46+
4047
export const setupCurrencyCodeMapsSync = (): void => {
41-
syncedCurrencyCodeMaps.onChange(currencyCodeMaps => {
48+
const onChange = (currencyCodeMaps: CurrencyCodeMaps): void => {
4249
const timestamp = new Date().toISOString()
4350
logger(
4451
`[${timestamp}] SYNC TRIGGERED: Syncing currency code maps with redis cache...`
@@ -78,5 +85,14 @@ export const setupCurrencyCodeMapsSync = (): void => {
7885
// Fire and forget - don't await in the callback
7986
updateKey().catch(e => logger('Unhandled error in updateKey', key, e))
8087
}
81-
})
88+
}
89+
90+
syncedCurrencyCodeMaps.onChange(onChange)
91+
92+
dbRates
93+
.get('currencyCodeMaps')
94+
.then((maps: unknown) => {
95+
onChange(asCurrencyCodeMaps(maps))
96+
})
97+
.catch(e => logger('currencyCodeMaps sync error', e))
8298
}

0 commit comments

Comments
 (0)