Skip to content

Commit

Permalink
refactor(ap): devapi
Browse files Browse the repository at this point in the history
  • Loading branch information
henb13 committed Jan 1, 2024
1 parent 9b4058b commit 80a9c09
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 84 deletions.
76 changes: 76 additions & 0 deletions server/api/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
const express = require("express");
const router = express.Router();
const DB = require("../db/db");
const pool = require("../db/connect");
const NodeCache = require("node-cache");
const rateLimit = require("express-rate-limit");
const slowDown = require("express-slow-down");

router.use(express.json());

const cache = new NodeCache({ stdTTL: 3600 });

const rateLimiter = rateLimit({
windowMs: 15 * 1000,
max: 7,
});

const speedLimiter = slowDown({
windowMs: 15 * 1000,
delayAfter: 3,
delayMs: (hits) => hits * 100,
});

const CACHE_KEYS = {
missingEpisodes: "missing-episodes",
shortenedEpisodes: "shortened-episodes",
lastChecked: "last-checked",
};

router.use(rateLimiter);
router.use(speedLimiter);

router.get("/api/episodes", async (req, res, next) => {
console.info("request fired");

const missingCacheExists = cache.has(CACHE_KEYS.missingEpisodes);
const shortenedCacheExists = cache.has(CACHE_KEYS.shortenedEpisodes);
const lastCheckedExists = cache.has(CACHE_KEYS.lastChecked);

if ([missingCacheExists, shortenedCacheExists, lastCheckedExists].some((c) => !c)) {
const client = await pool.connect();
const db = DB(client);

try {
if (!missingCacheExists) {
const missingEpisodes = await db.getMissingEpisodes();
cache.set(CACHE_KEYS.missingEpisodes, missingEpisodes);
}

if (!shortenedCacheExists) {
const shortenedEpisodes = await db.getShortenedEpisodes();
cache.set(CACHE_KEYS.shortenedEpisodes, shortenedEpisodes);
}

if (!lastCheckedExists) {
const lastChecked = await db.getLastChecked();
cache.set(CACHE_KEYS.lastChecked, lastChecked);
}

client.release();
console.info("db queried and cache updated");
} catch (error) {
console.error(error.message);
client.release();
next(error);
}
}

res.json({
missingEpisodes: cache.get(CACHE_KEYS.missingEpisodes),
shortenedEpisodes: cache.get(CACHE_KEYS.shortenedEpisodes),
lastCheckedInMs: cache.get(CACHE_KEYS.lastChecked),
});
});

module.exports = { api: router };
2 changes: 1 addition & 1 deletion server/api/dev-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ router.get("/api/episodes", async (_, res) => {
//TODO: Implement supabase development database if not using mock response
});

module.exports = router;
module.exports = { devApi: router };
78 changes: 3 additions & 75 deletions server/api/index.js
Original file line number Diff line number Diff line change
@@ -1,76 +1,4 @@
const express = require("express");
const router = express.Router();
const DB = require("../db/db");
const pool = require("../db/connect");
const NodeCache = require("node-cache");
const rateLimit = require("express-rate-limit");
const slowDown = require("express-slow-down");
const { api } = require("./api");
const { devApi } = require("./dev-api");

router.use(express.json());

const cache = new NodeCache({ stdTTL: 3600 });

const rateLimiter = rateLimit({
windowMs: 15 * 1000,
max: 7,
});

const speedLimiter = slowDown({
windowMs: 15 * 1000,
delayAfter: 3,
delayMs: (hits) => hits * 100,
});

const CACHE_KEYS = {
missingEpisodes: "missing-episodes",
shortenedEpisodes: "shortened-episodes",
lastChecked: "last-checked",
};

router.use(rateLimiter);
router.use(speedLimiter);

router.get("/api/episodes", async (req, res, next) => {
console.info("request fired");

const missingCacheExists = cache.has(CACHE_KEYS.missingEpisodes);
const shortenedCacheExists = cache.has(CACHE_KEYS.shortenedEpisodes);
const lastCheckedExists = cache.has(CACHE_KEYS.lastChecked);

if ([missingCacheExists, shortenedCacheExists, lastCheckedExists].some((c) => !c)) {
const client = await pool.connect();
const db = DB(client);

try {
if (!missingCacheExists) {
const missingEpisodes = await db.getMissingEpisodes();
cache.set(CACHE_KEYS.missingEpisodes, missingEpisodes);
}

if (!shortenedCacheExists) {
const shortenedEpisodes = await db.getShortenedEpisodes();
cache.set(CACHE_KEYS.shortenedEpisodes, shortenedEpisodes);
}

if (!lastCheckedExists) {
const lastChecked = await db.getLastChecked();
cache.set(CACHE_KEYS.lastChecked, lastChecked);
}

client.release();
console.info("db queried and cache updated");
} catch (error) {
console.error(error.message);
client.release();
next(error);
}
}

res.json({
missingEpisodes: cache.get(CACHE_KEYS.missingEpisodes),
shortenedEpisodes: cache.get(CACHE_KEYS.shortenedEpisodes),
lastCheckedInMs: cache.get(CACHE_KEYS.lastChecked),
});
});

module.exports = router;
module.exports = { api, devApi };
3 changes: 1 addition & 2 deletions server/app.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
const express = require("express");
const app = express();
const api = require("./api/index.js");
const responseHeaders = require("./api/middlewares/response-headers.js");
const errorHandler = require("./api/middlewares/error-handler.js");
const devApi = require("./api/dev-api.js");
const { devApi, api } = require("./api");

const helmet = require("helmet");
require("dotenv").config();
Expand Down
2 changes: 1 addition & 1 deletion server/lib/getSpotifyEpisodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ async function getSpotifyEpisodes() {

return spotifyEpisodes;
} catch (err) {
console.error("something went wrong fetching from Spotify: ", err.message);
throw new Error(`something went wrong fetching from Spotify: ${err.message}`);
}
}

Expand Down
136 changes: 135 additions & 1 deletion server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
"eslint": "^8.52.0",
"eslint-config-prettier": "^9.0.0",
"jest": "^29.7.0",
"nodemon": "^3.0.1"
"nodemon": "^3.0.1",
"supertest": "^6.3.3"
},
"jest": {
"testEnvironment": "node"
}
}
Loading

0 comments on commit 80a9c09

Please sign in to comment.