const express = require('express'); const axios = require('axios'); const NodeCache = require('node-cache'); const cron = require('node-cron'); const cors = require('cors'); const app = express(); const port = process.env.PORT || 7860; const cache = new NodeCache(); // Remove stdTTL to prevent automatic expiration const ERGAST_API_BASE_URL = 'https://ergast.com/api/f1/'; app.use(cors()); // Function to fetch data from Ergast API and update cache const fetchDataAndUpdateCache = async (url, cacheKey) => { try { const response = await axios.get(url); cache.set(cacheKey, response.data); console.log(`Updated ${cacheKey} cache`); } catch (error) { console.error(`Error updating ${cacheKey} cache:`, error); } }; // Schedule to update cache every 15 minutes for all endpoints //cron.schedule('*/15 * * * *', async () => { cron.schedule('0 */12 * * *', async () => { // Example: Update current season data await fetchDataAndUpdateCache(`${ERGAST_API_BASE_URL}current.json`, 'currentSeason'); // Update driver standings for the current season await fetchDataAndUpdateCache(`${ERGAST_API_BASE_URL}current/driverStandings.json`, 'driverStandings-current'); // Update driver standings for the current season await fetchDataAndUpdateCache(`${ERGAST_API_BASE_URL}2024/driverStandings.json`, 'driverStandings-2024'); await fetchDataAndUpdateCache(`${ERGAST_API_BASE_URL}2024/driverStandings.json`, 'driverStandings'); // Update constructor standings for the current season await fetchDataAndUpdateCache(`${ERGAST_API_BASE_URL}current/constructorStandings.json`, 'constructorStandings-current'); // Update constructor standings for the current season await fetchDataAndUpdateCache(`${ERGAST_API_BASE_URL}2024/constructorStandings.json`, 'constructorStandings-2024'); await fetchDataAndUpdateCache(`${ERGAST_API_BASE_URL}2024/constructorStandings.json`, 'constructorStandings'); // Update race results for 2024 season, rounds 1 to 24 // for (let round = 1; round <= 24; round++) { // await fetchDataAndUpdateCache(`${ERGAST_API_BASE_URL}current/${round}/results.json`, `raceResults-2024-${round}`); // } // Update additional endpoints as needed // await fetchDataAndUpdateCache(`${ERGAST_API_BASE_URL}current/other.json`, 'otherData'); // await fetchDataAndUpdateCache(`${ERGAST_API_BASE_URL}seasons.json`, 'seasons'); //await fetchDataAndUpdateCache(`${ERGAST_API_BASE_URL}drivers.json`, 'drivers'); // await fetchDataAndUpdateCache(`${ERGAST_API_BASE_URL}constructors.json`, 'constructors'); // Add more endpoints to update cache as needed }); // Generic endpoint handler to fetch data with caching and error handling const handleEndpointWithCache = async (req, res, url, cacheKey) => { try { const cachedData = cache.get(cacheKey); if (cachedData) { res.json(cachedData); } else { const response = await axios.get(url); cache.set(cacheKey, response.data); res.json(response.data); } } catch (error) { console.error(`Error fetching ${cacheKey} from Ergast API:`, error); const cachedData = cache.get(cacheKey); if (cachedData) { res.json(cachedData); } else { res.status(500).send(`Error fetching data from Ergast API for ${cacheKey} and no cache available.`); } } }; // Endpoint to manually trigger cache update app.get('/api/updateCache', async (req, res) => { const { url, cacheKey } = req.query; if (!url || !cacheKey) { return res.status(400).send('url and cacheKey query parameters are required.'); } try { await fetchDataAndUpdateCache(url, cacheKey); res.send(`Cache for ${cacheKey} updated successfully.`); } catch (error) { res.status(500).send(`Error updating cache for ${cacheKey}.`); } }); // Example endpoint to get current season data app.get('/api/currentSeason', async (req, res) => { await handleEndpointWithCache(req, res, `${ERGAST_API_BASE_URL}current.json`, 'currentSeason'); }); // Example endpoint to get driver standings data app.get('/api/driverStandings', async (req, res) => { const season = req.query.season || 'current'; await handleEndpointWithCache(req, res, `${ERGAST_API_BASE_URL}${season}/driverStandings.json`, `driverStandings-${season}`); }); // Example endpoint to get constructor standings data app.get('/api/constructorStandings', async (req, res) => { const season = req.query.season || 'current'; await handleEndpointWithCache(req, res, `${ERGAST_API_BASE_URL}${season}/constructorStandings.json`, `constructorStandings-${season}`); }); // Example endpoint to get race results data app.get('/api/raceResults', async (req, res) => { const season = req.query.season || 'current'; const round = req.query.round; if (!round) { return res.status(400).send('Round is required.'); } await handleEndpointWithCache(req, res, `${ERGAST_API_BASE_URL}${season}/${round}/results.json`, `raceResults-${season}-${round}`); }); // Add more endpoints with similar structure as needed // Start server app.listen(port, () => { console.log(`Server running on port ${port}`); });