From 88466128d6d775a2fa295340921ef1cf44660b4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ra=C4=8D=C3=A1k?= Date: Mon, 17 Feb 2025 16:46:49 +0100 Subject: [PATCH] Add site redirects for recent chart redirects We take Grapher redirects into consideration only when a route returns 404 and Cloudflare caches assets up to a week in the CDN, so it's possible to still get the old page after a redirect is created for it. Authors are confused why they don't see chart redirects working after they push changes. It also means different users can see different charts when clicking on the same link, depending on whether the CDN data center that handles their request had the old page cached. I tested this case with Pablo A. We take a similar approach as for deleting articles and add redirects in the special `_redirects` file - that Cloudflare always takes into consideration - for Grapher redirects that are less than a week old. --- baker/redirects.ts | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/baker/redirects.ts b/baker/redirects.ts index 2037368b59..b41417c6bc 100644 --- a/baker/redirects.ts +++ b/baker/redirects.ts @@ -77,16 +77,48 @@ export const getRedirects = async (knex: db.KnexReadonlyTransaction) => { (row) => `${row.source} ${row.target} ${row.code}` ) + const recentGrapherRedirects = (await getRecentGrapherRedirects(knex)).map( + (row) => `/grapher/${row.source} /grapher/${row.target} 302` + ) + // Add newlines in between so we get some more overview return [ ...staticRedirects, "", + ...recentGrapherRedirects, + "", ...redirectsFromDb, "", ...dynamicRedirects, // Cloudflare requires all dynamic redirects to be at the very end of the _redirects file ] } +async function getRecentGrapherRedirects(knex: db.KnexReadonlyTransaction) { + // Prevent Cloudflare from serving outdated grapher pages, which can remain + // in the cache for up to a week. This is necessary, since we take into + // consideration the grapher redirects only when the route returns a 404, + // which won't be the case if the page is still cached. + // + // https://developers.cloudflare.com/pages/configuration/serving-pages/#asset-retention + return await db.knexRaw<{ + source: string + target: string + }>( + knex, + `-- sql + SELECT + chart_slug_redirects.slug as source, + chart_configs.slug as target + FROM chart_slug_redirects + INNER JOIN charts ON charts.id=chart_id + INNER JOIN chart_configs ON chart_configs.id=charts.configId + WHERE + COALESCE(chart_slug_redirects.updatedAt, chart_slug_redirects.createdAt) + > (NOW() - INTERVAL 1 WEEK) + ` + ) +} + export const getGrapherRedirectsMap = async ( knex: db.KnexReadonlyTransaction, urlPrefix: string = "/grapher/"