Labels: bug, reliability, tech-debt
Problem
Five services all fetch from the same class of Flux stats API and count/sum results, but handle failure completely differently:
| Service |
Retry on failure |
Falls back to last-good data |
Logging style |
cloudService.js |
2x, shared retryApiCall() helper |
Returns cached data |
structured (createLogger) |
gamingService.js |
3x / 10s delay, inline loop |
Throws, no fallback |
console.log/console.error |
cryptoService.js |
3x / 10s delay, inline loop (near-duplicate of gaming's) |
Throws, no fallback |
console.log/console.error |
wordpressService.js |
None |
Throws, no fallback |
console.log/console.error |
nodeService.js |
None |
Throws, no fallback |
console.log/console.error |
cloudService.js is the most resilient — it retries, and on total failure returns last-known-good cached data instead of leaving the dashboard blank or throwing. The other four either throw immediately or throw after retries with no fallback, so a single bad response from Flux's API can leave that metric stuck or erroring with no graceful degradation.
gamingService.js and cryptoService.js also contain near-identical fetch/count/retry code (same structure, different config object) — a maintenance risk, since a fix applied to one is easy to forget on the other. This kind of duplication is part of how the original stale-count issue could get worse over time.
Solution
- Extract
cloudService.js's retryApiCall() + cache-fallback pattern into a shared helper, e.g. src/lib/services/resilientFetch.js:
export async function resilientFetch(url, { retries = 2, timeout = 15000, cacheKey } = {}) {
// retry loop + cache fallback, generalized from cloudService.js
}
- Have
gamingService.js, cryptoService.js, wordpressService.js, and nodeService.js all use it instead of their own copy-pasted or missing retry logic.
- Collapse
gamingService.js and cryptoService.js into one generic function:
export async function fetchRepoStats(REPOS_CONFIG, totalDbKey, syncStatusName) {
// shared node/app/image counting loop, parameterized by config
}
and have both gaming and crypto call it with their respective config.
4. Standardize all five services on the existing createLogger() pattern (already used in cloudService.js, revenueScheduler.js, servicesScheduler.js, database.js) instead of raw console.log, for consistent, filterable logs.
Files: src/lib/services/gamingService.js, cryptoService.js, wordpressService.js, nodeService.js, cloudService.js (source of the pattern to extract)
Labels:
bug,reliability,tech-debtProblem
Five services all fetch from the same class of Flux stats API and count/sum results, but handle failure completely differently:
cloudService.jsretryApiCall()helpercreateLogger)gamingService.jsconsole.log/console.errorcryptoService.jsconsole.log/console.errorwordpressService.jsconsole.log/console.errornodeService.jsconsole.log/console.errorcloudService.jsis the most resilient — it retries, and on total failure returns last-known-good cached data instead of leaving the dashboard blank or throwing. The other four either throw immediately or throw after retries with no fallback, so a single bad response from Flux's API can leave that metric stuck or erroring with no graceful degradation.gamingService.jsandcryptoService.jsalso contain near-identical fetch/count/retry code (same structure, different config object) — a maintenance risk, since a fix applied to one is easy to forget on the other. This kind of duplication is part of how the original stale-count issue could get worse over time.Solution
cloudService.js'sretryApiCall()+ cache-fallback pattern into a shared helper, e.g.src/lib/services/resilientFetch.js:gamingService.js,cryptoService.js,wordpressService.js, andnodeService.jsall use it instead of their own copy-pasted or missing retry logic.gamingService.jsandcryptoService.jsinto one generic function:and have both gaming and crypto call it with their respective config.
4. Standardize all five services on the existing
createLogger()pattern (already used incloudService.js,revenueScheduler.js,servicesScheduler.js,database.js) instead of rawconsole.log, for consistent, filterable logs.Files:
src/lib/services/gamingService.js,cryptoService.js,wordpressService.js,nodeService.js,cloudService.js(source of the pattern to extract)