diff --git a/src/services/codechef.service.js b/src/services/codechef.service.js index 9e3e1c5..3f9abf7 100644 --- a/src/services/codechef.service.js +++ b/src/services/codechef.service.js @@ -1,3 +1,4 @@ +import { githubCache } from '../utils/cache.js'; import { HttpErrorCode, httpRequest } from '../utils/http-client.js'; function getDivision(rating) { @@ -8,6 +9,21 @@ function getDivision(rating) { } export async function getCodeChefData(handle) { + if (!handle) { + return { + success: false, + error: 'CodeChef handle not provided', + }; + } + + const cacheKey = `codechef:${handle}`; + + // Check cache first + const cached = githubCache.get(cacheKey); + if (cached) { + return cached; + } + try { const safeHandle = encodeURIComponent(handle); @@ -27,7 +43,7 @@ export async function getCodeChefData(handle) { const currentRating = data.rating_number ?? 0; - return { + const result = { success: true, data: { handle: data.username ?? handle, @@ -36,9 +52,14 @@ export async function getCodeChefData(handle) { globalRank: data.globalRank ?? data.global_rank ?? 'N/A', problemsSolved: data.problemsSolved ?? data.problems_solved ?? 0, division: getDivision(currentRating), - } + }, }; + + // Store successful result in cache + githubCache.set(cacheKey, result); + + return result; } catch (err) { - return { success: false, error: "CodeChef API error" }; + return { success: false, error: 'CodeChef API error' }; } -} +} \ No newline at end of file diff --git a/src/services/codeforces.service.js b/src/services/codeforces.service.js index 5f892ed..27f5bca 100644 --- a/src/services/codeforces.service.js +++ b/src/services/codeforces.service.js @@ -1,6 +1,22 @@ +import { githubCache } from '../utils/cache.js'; import { HttpErrorCode, httpRequest } from '../utils/http-client.js'; export async function getCodeforcesData(handle) { + if (!handle) { + return { + success: false, + error: 'Codeforces handle not provided', + }; + } + + const cacheKey = `codeforces:${handle}`; + + // Check cache first + const cached = githubCache.get(cacheKey); + if (cached) { + return cached; + } + try { const safeHandle = encodeURIComponent(handle); @@ -36,7 +52,7 @@ export async function getCodeforcesData(handle) { problemsSolved = solved.size; } - return { + const result = { success: true, data: { handle: user.handle, @@ -45,9 +61,14 @@ export async function getCodeforcesData(handle) { rank: user.rank ?? 'unrated', maxRank: user.maxRank ?? 'unrated', problemsSolved, - } + }, }; + + // Store successful result in cache + githubCache.set(cacheKey, result); + + return result; } catch (err) { - return { success: false, error: "Codeforces API error" }; + return { success: false, error: 'Codeforces API error' }; } -} +} \ No newline at end of file diff --git a/src/services/github.service.js b/src/services/github.service.js index 8da3201..aa04442 100644 --- a/src/services/github.service.js +++ b/src/services/github.service.js @@ -93,32 +93,26 @@ async function fetchUserProfile(username) { /* fetch public repos for a user */ async function fetchUserRepos(username) { + const repos = []; + let page = 1; const perPage = 100; - // Fetch first page - const response1 = await httpRequest( - `${GITHUB_API_BASE}/users/${username}/repos?per_page=${perPage}&page=1&sort=updated`, - { headers: getHeaders() } - ); - await assertOk(response1); - const repos = response1.data || []; - - // If first page has exactly 100 items, fetch pages 2 and 3 in parallel - if (repos.length === perPage) { - const promises = [2, 3].map(page => - httpRequest( - `${GITHUB_API_BASE}/users/${username}/repos?per_page=${perPage}&page=${page}&sort=updated`, - { headers: getHeaders() } - ) + while (true) { + const response = await httpRequest( + `${GITHUB_API_BASE}/users/${username}/repos?per_page=${perPage}&page=${page}&sort=updated`, + { headers: getHeaders() } ); - const responses = await Promise.all(promises); - for (const res of responses) { - await assertOk(res); - if (res.data && res.data.length > 0) { - repos.push(...res.data); - } + await assertOk(response); + + const data = Array.isArray(response.data) ? response.data : []; + repos.push(...data); + + if (data.length < perPage) { + break; } + + page++; } return repos; diff --git a/src/services/tests/codechef.service.test.js b/src/services/tests/codechef.service.test.js index 660c7d2..393a2fb 100644 --- a/src/services/tests/codechef.service.test.js +++ b/src/services/tests/codechef.service.test.js @@ -1,4 +1,5 @@ -import { afterEach, describe, expect, jest, test } from '@jest/globals'; +import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globals'; +import { githubCache } from '../../utils/cache.js'; import { getCodeChefData } from '../codechef.service.js'; // --------------------------------------------------------------------------- @@ -23,6 +24,9 @@ function jsonResponse(data, init = {}) { // --------------------------------------------------------------------------- describe('codechef.service.js', () => { + beforeEach(() => { + githubCache.clear(); + }); afterEach(() => { delete globalThis.fetch; }); diff --git a/src/services/tests/codeforces.service.test.js b/src/services/tests/codeforces.service.test.js index 6e3dd5d..e7beeeb 100644 --- a/src/services/tests/codeforces.service.test.js +++ b/src/services/tests/codeforces.service.test.js @@ -1,4 +1,5 @@ -import { afterEach, describe, expect, jest, test } from '@jest/globals'; +import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globals'; +import { githubCache } from '../../utils/cache.js'; import { getCodeforcesData } from '../codeforces.service.js'; // --------------------------------------------------------------------------- @@ -31,6 +32,9 @@ function errorResponse(status) { // --------------------------------------------------------------------------- describe('codeforces.service.js', () => { + beforeEach(() => { + githubCache.clear(); + }); afterEach(() => { delete globalThis.fetch; });