@@ -28,6 +28,7 @@ import {
2828 addIso ,
2929 fromCode ,
3030 isIsoCode ,
31+ logger ,
3132 normalizeDate ,
3233 subIso ,
3334 toCode ,
@@ -329,34 +330,70 @@ const getRedisMarkets = async (
329330 const now = new Date ( )
330331 const nowTimestamp = now . getTime ( )
331332
332- const jsonString = await getAsync ( `${ REDIS_COINRANK_KEY_PREFIX } _${ fiatCode } ` )
333- let redisResult : CoinrankRedis = JSON . parse ( jsonString )
333+ try {
334+ // First try to get data for the requested fiat code
335+ const jsonString = await getAsync (
336+ `${ REDIS_COINRANK_KEY_PREFIX } _${ fiatCode } `
337+ )
334338
335- if ( fiatCode !== defaultFiatCode ) {
336- const lastUpdated =
337- redisResult != null ? new Date ( redisResult . lastUpdate ) . getTime ( ) : 0
339+ // Only parse if jsonString is not null/undefined
340+ let redisResult : CoinrankRedis | undefined
341+ if ( jsonString != null ) {
342+ try {
343+ redisResult = JSON . parse ( jsonString )
344+
345+ // If we have valid data that hasn't expired, return it
346+ const lastUpdated =
347+ redisResult != null ? new Date ( redisResult . lastUpdate ) . getTime ( ) : 0
348+ if ( nowTimestamp - lastUpdated <= EXPIRE_TIME ) {
349+ return redisResult
350+ }
351+ // We have cached data but it's expired - we'll try to refresh it below
352+ // but will fall back to this expired data if refresh fails
353+ } catch ( e ) {
354+ // JSON parsing error, redisResult remains undefined
355+ logger ( `Error parsing Redis data for ${ fiatCode } : ${ e } ` )
356+ // Continue to try to get fresh data
357+ }
358+ }
338359
339- // If no result in redis or it's out of date
340- if ( redisResult == null || nowTimestamp - lastUpdated > EXPIRE_TIME ) {
341- // Attempt to scale prices by foreign exchange rate
360+ // For USD requests, return the result immediately (could be undefined if not found)
361+ if ( fiatCode === defaultFiatCode ) {
362+ return redisResult
363+ }
342364
365+ // If we need to convert from USD (either no data or expired data)
366+ try {
343367 // Get exchange rate
344368 const result = await fetch (
345369 `${ ratesServerAddress } /v2/exchangeRate?currency_pair=${ defaultFiatCode } _${ fiatCode } `
346370 )
371+ if ( ! result . ok ) {
372+ throw new Error ( `Exchange rate API returned status ${ result . status } ` )
373+ }
374+
347375 const resultJson = await result . json ( )
348376 const { exchangeRate } = asExchangeRateResponse ( resultJson )
349377 const rate = Number ( exchangeRate )
350378
379+ // Validate the rate
380+ if ( rate == null || isNaN ( rate ) || rate <= 0 ) {
381+ throw new Error ( `Invalid exchange rate: ${ exchangeRate } ` )
382+ }
383+
351384 // Get USD rankings
352- const jsonString = await getAsync (
385+ const usdJsonString = await getAsync (
353386 `${ REDIS_COINRANK_KEY_PREFIX } _${ defaultFiatCode } `
354387 )
355- redisResult = JSON . parse ( jsonString )
356- let { markets } = redisResult
388+ if ( usdJsonString == null ) {
389+ throw new Error ( `No USD data available in Redis` )
390+ }
391+
392+ const usdRedisResult = JSON . parse ( usdJsonString )
393+ const { markets } = usdRedisResult
357394
358395 // Modify fiat-related fields with the forex rate
359- markets = markets . map ( m => ( {
396+ const convertedMarkets = markets . map ( m => ( {
360397 ...m ,
361398 marketCap : m . marketCap * rate ,
362399 price : m . price * rate ,
@@ -374,17 +411,29 @@ const getRedisMarkets = async (
374411
375412 // Update redis cache
376413 const redisData : CoinrankRedis = {
377- markets,
378- lastUpdate : now . toISOString ( )
414+ markets : convertedMarkets ,
415+ lastUpdate : redisResult ?. lastUpdate ?? now . toISOString ( )
379416 }
380417 await setAsync (
381418 `${ REDIS_COINRANK_KEY_PREFIX } _${ fiatCode } ` ,
382419 JSON . stringify ( redisData )
383420 )
421+
422+ return redisData
423+ } catch ( e ) {
424+ logger ( `Error converting USD data to ${ fiatCode } : ${ e } ` )
425+ // If conversion fails but we have cached data (even if expired), return that
426+ if ( redisResult != null ) {
427+ logger ( `Falling back to cached data for ${ fiatCode } ` )
428+ return redisResult
429+ }
430+ // Only return undefined if we have no cached data at all
431+ return undefined
384432 }
433+ } catch ( e ) {
434+ logger ( `Error in getRedisMarkets for ${ fiatCode } : ${ e } ` )
435+ return undefined
385436 }
386-
387- return redisResult
388437}
389438
390439const sendCoinrankList : express . RequestHandler = async (
0 commit comments