mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-26 14:32:04 -04:00
fix cache invalidation
This commit is contained in:
parent
c3f22ae36d
commit
38c5247ded
@ -6,12 +6,12 @@ import {buildDict, now, shuffle, handleErrorAsync, buildLocaleList} from "../../
|
||||
import locales from '../../src/locales';
|
||||
import {calculateStats, statsFile} from '../../src/stats';
|
||||
import fs from 'fs';
|
||||
import cache from "../../src/cache";
|
||||
import { caches } from "../../src/cache";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get('/admin/list', handleErrorAsync(async (req, res) => {
|
||||
return res.json(await cache('main', 'admins.js', 10, async () => {
|
||||
return res.json(await caches.admins.fetch(async () => {
|
||||
const admins = await req.db.all(SQL`
|
||||
SELECT u.username, p.teamName, p.locale, u.id, u.email, u.avatarSource
|
||||
FROM users u
|
||||
@ -47,7 +47,7 @@ router.get('/admin/list', handleErrorAsync(async (req, res) => {
|
||||
}));
|
||||
|
||||
router.get('/admin/list/footer', handleErrorAsync(async (req, res) => {
|
||||
return res.json(shuffle(await cache('main', 'footer.js', 10, async () => {
|
||||
return res.json(shuffle(await caches.adminsFooter.fetch(async () => {
|
||||
const fromDb = await req.db.all(SQL`
|
||||
SELECT u.username, p.footerName, p.footerAreas, p.locale
|
||||
FROM users u
|
||||
|
@ -6,8 +6,7 @@ import avatar from '../avatar';
|
||||
import {buildPronoun, parsePronouns} from "../../src/buildPronoun";
|
||||
import {loadTsv} from "../../src/tsv";
|
||||
import {handleErrorAsync} from "../../src/helpers";
|
||||
import cache from "../../src/cache";
|
||||
import fs from "fs";
|
||||
import { CacheObject } from "../../src/cache";
|
||||
|
||||
const translations = loadSuml('translations');
|
||||
|
||||
@ -38,7 +37,7 @@ router.get('/banner/:pronounName*.png', handleErrorAsync(async (req, res) => {
|
||||
|
||||
const pronounName = req.params.pronounName + req.params[0];
|
||||
|
||||
const result = await cache('banner', `${pronounName}.png`, 24 * 60, async () => {
|
||||
const result = await new CacheObject('banner', `${pronounName}.png`, 24 * 60).fetch(async () => {
|
||||
registerFont('static/fonts/quicksand-v21-latin-ext_latin-regular.ttf', {family: 'Quicksand', weight: 'regular'});
|
||||
registerFont('static/fonts/quicksand-v21-latin-ext_latin-700.ttf', {family: 'Quicksand', weight: 'bold'});
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { Router } from 'express';
|
||||
import {handleErrorAsync, shuffle} from "../../src/helpers";
|
||||
import fs from 'fs';
|
||||
import cache from "../../src/cache";
|
||||
import { caches } from "../../src/cache";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get('/blog', handleErrorAsync(async (req, res) => {
|
||||
return res.json(await cache('main', 'blog.js', Infinity, async () => {
|
||||
return res.json(await caches.blog.fetch(async () => {
|
||||
const dir = __dirname + '/../../data/blog';
|
||||
const posts = [];
|
||||
fs.readdirSync(dir).forEach(file => {
|
||||
|
@ -2,6 +2,7 @@ import { Router } from 'express';
|
||||
import SQL from 'sql-template-strings';
|
||||
import {ulid} from "ulid";
|
||||
import {isTroll, handleErrorAsync} from "../../src/helpers";
|
||||
import { caches } from "../../src/cache";
|
||||
|
||||
const approve = async (db, id) => {
|
||||
const { base_id } = await db.get(SQL`SELECT base_id FROM inclusive WHERE id=${id}`);
|
||||
@ -17,19 +18,22 @@ const approve = async (db, id) => {
|
||||
SET approved = 1, base_id = NULL
|
||||
WHERE id = ${id}
|
||||
`);
|
||||
await caches.inclusive.invalidate();
|
||||
}
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get('/inclusive', handleErrorAsync(async (req, res) => {
|
||||
return res.json(await req.db.all(SQL`
|
||||
SELECT i.*, u.username AS author FROM inclusive i
|
||||
LEFT JOIN users u ON i.author_id = u.id
|
||||
WHERE i.locale = ${global.config.locale}
|
||||
AND i.approved >= ${req.isGranted('inclusive') ? 0 : 1}
|
||||
AND i.deleted = 0
|
||||
ORDER BY i.approved, i.insteadOf
|
||||
`));
|
||||
return res.json(await caches.inclusive.fetch(async () => {
|
||||
return await req.db.all(SQL`
|
||||
SELECT i.*, u.username AS author FROM inclusive i
|
||||
LEFT JOIN users u ON i.author_id = u.id
|
||||
WHERE i.locale = ${global.config.locale}
|
||||
AND i.approved >= ${req.isGranted('inclusive') ? 0 : 1}
|
||||
AND i.deleted = 0
|
||||
ORDER BY i.approved, i.insteadOf
|
||||
`);
|
||||
}));
|
||||
}));
|
||||
|
||||
router.get('/inclusive/search/:term', handleErrorAsync(async (req, res) => {
|
||||
@ -79,6 +83,8 @@ router.post('/inclusive/hide/:id', handleErrorAsync(async (req, res) => {
|
||||
WHERE id = ${req.params.id}
|
||||
`);
|
||||
|
||||
await caches.inclusive.invalidate();
|
||||
|
||||
return res.json('ok');
|
||||
}));
|
||||
|
||||
@ -103,6 +109,8 @@ router.post('/inclusive/remove/:id', handleErrorAsync(async (req, res) => {
|
||||
WHERE id = ${req.params.id}
|
||||
`);
|
||||
|
||||
await caches.inclusive.invalidate();
|
||||
|
||||
return res.json('ok');
|
||||
}));
|
||||
|
||||
|
@ -4,6 +4,7 @@ import {ulid} from "ulid";
|
||||
import {createCanvas, loadImage, registerFont} from "canvas";
|
||||
import {loadSuml} from "../loader";
|
||||
import {handleErrorAsync, isTroll} from "../../src/helpers";
|
||||
import { caches } from "../../src/cache";
|
||||
|
||||
const translations = loadSuml('translations');
|
||||
|
||||
@ -21,6 +22,7 @@ const approve = async (db, id) => {
|
||||
SET approved = 1, base_id = NULL
|
||||
WHERE id = ${id}
|
||||
`);
|
||||
await caches.nouns.invalidate();
|
||||
}
|
||||
|
||||
const addVersions = async (req, nouns) => {
|
||||
@ -69,14 +71,16 @@ const selectFragment = (sourcesMap, keyAndFragment) => {
|
||||
const router = Router();
|
||||
|
||||
router.get('/nouns', handleErrorAsync(async (req, res) => {
|
||||
return res.json(await addVersions(req, await req.db.all(SQL`
|
||||
SELECT n.*, u.username AS author FROM nouns n
|
||||
LEFT JOIN users u ON n.author_id = u.id
|
||||
WHERE n.locale = ${global.config.locale}
|
||||
AND n.deleted = 0
|
||||
AND n.approved >= ${req.isGranted('nouns') ? 0 : 1}
|
||||
ORDER BY n.approved, n.masc
|
||||
`)));
|
||||
return res.json(await caches.nouns.fetch(async () => {
|
||||
return await addVersions(req, await req.db.all(SQL`
|
||||
SELECT n.*, u.username AS author FROM nouns n
|
||||
LEFT JOIN users u ON n.author_id = u.id
|
||||
WHERE n.locale = ${global.config.locale}
|
||||
AND n.deleted = 0
|
||||
AND n.approved >= ${req.isGranted('nouns') ? 0 : 1}
|
||||
ORDER BY n.approved, n.masc
|
||||
`))
|
||||
}));
|
||||
}));
|
||||
|
||||
router.get('/nouns/search/:term', handleErrorAsync(async (req, res) => {
|
||||
@ -127,6 +131,8 @@ router.post('/nouns/hide/:id', handleErrorAsync(async (req, res) => {
|
||||
WHERE id = ${req.params.id}
|
||||
`);
|
||||
|
||||
await caches.nouns.invalidate();
|
||||
|
||||
return res.json('ok');
|
||||
}));
|
||||
|
||||
@ -151,6 +157,8 @@ router.post('/nouns/remove/:id', handleErrorAsync(async (req, res) => {
|
||||
WHERE id = ${req.params.id}
|
||||
`);
|
||||
|
||||
await caches.nouns.invalidate();
|
||||
|
||||
return res.json('ok');
|
||||
}));
|
||||
|
||||
|
@ -4,6 +4,7 @@ import md5 from "js-md5";
|
||||
import {ulid} from "ulid";
|
||||
import avatar from "../avatar";
|
||||
import {handleErrorAsync} from "../../src/helpers";
|
||||
import { caches } from "../../src/cache";
|
||||
|
||||
const normalise = s => s.trim().toLowerCase();
|
||||
|
||||
@ -102,6 +103,11 @@ router.post('/profile/save', handleErrorAsync(async (req, res) => {
|
||||
)`);
|
||||
}
|
||||
|
||||
if (req.body.teamName) {
|
||||
await caches.admins.invalidate();
|
||||
await caches.adminsFooter.invalidate();
|
||||
}
|
||||
|
||||
return res.json(await fetchProfiles(req.db, req.user.username, true));
|
||||
}));
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { Router } from 'express';
|
||||
import SQL from 'sql-template-strings';
|
||||
import {ulid} from "ulid";
|
||||
import {isTroll, handleErrorAsync} from "../../src/helpers";
|
||||
import cache from "../../src/cache";
|
||||
import { caches } from "../../src/cache";
|
||||
|
||||
const approve = async (db, id) => {
|
||||
const { base_id } = await db.get(SQL`SELECT base_id FROM terms WHERE id=${id}`);
|
||||
@ -18,12 +18,13 @@ const approve = async (db, id) => {
|
||||
SET approved = 1, base_id = NULL
|
||||
WHERE id = ${id}
|
||||
`);
|
||||
await caches.terms.invalidate();
|
||||
}
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get('/terms', handleErrorAsync(async (req, res) => {
|
||||
return res.json(await cache('main', 'terms.js', 10, () => {
|
||||
return res.json(await caches.terms.fetch(() => {
|
||||
return req.db.all(SQL`
|
||||
SELECT i.*, u.username AS author FROM terms i
|
||||
LEFT JOIN users u ON i.author_id = u.id
|
||||
@ -82,6 +83,8 @@ router.post('/terms/hide/:id', handleErrorAsync(async (req, res) => {
|
||||
WHERE id = ${req.params.id}
|
||||
`);
|
||||
|
||||
await caches.terms.invalidate();
|
||||
|
||||
return res.json('ok');
|
||||
}));
|
||||
|
||||
@ -106,6 +109,8 @@ router.post('/terms/remove/:id', handleErrorAsync(async (req, res) => {
|
||||
WHERE id = ${req.params.id}
|
||||
`);
|
||||
|
||||
await caches.terms.invalidate();
|
||||
|
||||
return res.json('ok');
|
||||
}));
|
||||
|
||||
|
40
src/cache.js
40
src/cache.js
@ -1,18 +1,36 @@
|
||||
import fs from 'fs';
|
||||
|
||||
export default async (dir, filename, maxAgeMinutes, generator) => {
|
||||
const cacheDir = `${__dirname}/../cache/${dir}`
|
||||
fs.mkdirSync(cacheDir, { recursive: true });
|
||||
const cacheFilename = `${cacheDir}/${filename}`;
|
||||
|
||||
if (fs.existsSync(cacheFilename) && fs.statSync(cacheFilename).mtimeMs >= (new Date() - maxAgeMinutes*60*1000)) {
|
||||
const content = fs.readFileSync(cacheFilename);
|
||||
return filename.endsWith('.js') ? JSON.parse(content) : content;
|
||||
export class CacheObject {
|
||||
constructor(dir, filename, maxAgeMinutes) {
|
||||
const cacheDir = `${__dirname}/../cache/${dir}`
|
||||
fs.mkdirSync(cacheDir, { recursive: true });
|
||||
this.path = `${cacheDir}/${filename}`;
|
||||
this.maxAgeMinutes = maxAgeMinutes;
|
||||
}
|
||||
|
||||
const result = await generator();
|
||||
async fetch(generator) {
|
||||
if (fs.existsSync(this.path) && fs.statSync(this.path).mtimeMs >= (new Date() - this.maxAgeMinutes*60*1000)) {
|
||||
const content = fs.readFileSync(this.path);
|
||||
return this.path.endsWith('.js') ? JSON.parse(content) : content;
|
||||
}
|
||||
|
||||
fs.writeFileSync(cacheFilename, filename.endsWith('.js') ? JSON.stringify(result) : result);
|
||||
const result = await generator();
|
||||
|
||||
return result;
|
||||
fs.writeFileSync(this.path, this.path.endsWith('.js') ? JSON.stringify(result) : result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async invalidate() {
|
||||
fs.unlinkSync(this.path);
|
||||
}
|
||||
}
|
||||
|
||||
export const caches = {
|
||||
admins: new CacheObject('main', 'admins.js', 10),
|
||||
adminsFooter: new CacheObject('main', 'footer.js', 10),
|
||||
blog: new CacheObject('main', 'blog.js', Infinity),
|
||||
nouns: new CacheObject('main', 'nouns.js', 10),
|
||||
terms: new CacheObject('main', 'terms.js', 10),
|
||||
inclusive: new CacheObject('main', 'inclusive.js', 10),
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user