Skip to content

Commit

Permalink
Remove all code related to Redis page caching (github#20457)
Browse files Browse the repository at this point in the history
Towards simplification for github/docs-engineering#678
  • Loading branch information
JamesMGreene authored Jul 21, 2021
1 parent 9d25c78 commit df301cb
Show file tree
Hide file tree
Showing 7 changed files with 1 addition and 815 deletions.
2 changes: 0 additions & 2 deletions Procfile
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
web: NODE_ENV=production node server.mjs

release: NODE_ENV=production script/release-heroku
138 changes: 0 additions & 138 deletions lib/redis-accessor.js

This file was deleted.

94 changes: 1 addition & 93 deletions middleware/render-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,9 @@ import { get } from 'lodash-es'
import patterns from '../lib/patterns.js'
import getMiniTocItems from '../lib/get-mini-toc-items.js'
import Page from '../lib/page.js'
import statsd from '../lib/statsd.js'
import RedisAccessor from '../lib/redis-accessor.js'
import { isConnectionDropped } from './halt-on-dropped-connection.js'
import { nextApp, nextHandleRequest } from './next.js'

const { HEROKU_RELEASE_VERSION } = process.env

const pageCacheDatabaseNumber = 1

const pageCache = new RedisAccessor({
databaseNumber: pageCacheDatabaseNumber,
prefix: (HEROKU_RELEASE_VERSION ? HEROKU_RELEASE_VERSION + ':' : '') + 'rp',
// Allow for graceful failures if a Redis SET operation fails
allowSetFailures: true,
// Allow for graceful failures if a Redis GET operation fails
allowGetFailures: true,
name: 'page-cache',
})

// a list of query params that *do* alter the rendered page, and therefore should be cached separately
const cacheableQueries = ['learn']

function modifyOutput(req, text) {
return addColorMode(req, addCsrf(req, text))
}

function addCsrf(req, text) {
return text.replace('$CSRFTOKEN$', req.csrfToken())
}

function addColorMode(req, text) {
let colorMode = 'auto'
let darkTheme = 'dark'
let lightTheme = 'light'

try {
const cookieValue = JSON.parse(decodeURIComponent(req.cookies.color_mode))
colorMode = encodeURIComponent(cookieValue.color_mode) || colorMode
darkTheme = encodeURIComponent(cookieValue.dark_theme.name) || darkTheme
lightTheme = encodeURIComponent(cookieValue.light_theme.name) || lightTheme
} catch (e) {
// do nothing
}

return text
.replace('$COLORMODE$', colorMode)
.replace('$DARKTHEME$', darkTheme)
.replace('$LIGHTTHEME$', lightTheme)
}

export default async function renderPage(req, res, next) {
const page = req.context.page
// render a 404 page
Expand All @@ -64,59 +17,14 @@ export default async function renderPage(req, res, next) {
return nextApp.render404(req, res)
}

// Just finish fast without all the details like Content-Length
if (req.method === 'HEAD') {
return res.status(200).end()
}

// Remove any query string (?...) and/or fragment identifier (#...)
const { pathname, searchParams } = new URL(req.originalUrl, 'https://docs.github.com')

for (const queryKey in req.query) {
if (!cacheableQueries.includes(queryKey)) {
searchParams.delete(queryKey)
}
}
const originalUrl = pathname + ([...searchParams].length > 0 ? `?${searchParams}` : '')

// Is the request for JSON debugging info?
const isRequestingJsonForDebugging = 'json' in req.query && process.env.NODE_ENV !== 'production'

// Is in an airgapped session?
const isAirgapped = Boolean(req.cookies.AIRGAP)

// Is the request for the GraphQL Explorer page?
const isGraphQLExplorer = req.context.currentPathWithoutLanguage === '/graphql/overview/explorer'

// Serve from the cache if possible
const isCacheable =
// Skip for CI
!process.env.CI &&
// Skip for tests
process.env.NODE_ENV !== 'test' &&
// Skip for HTTP methods other than GET
req.method === 'GET' &&
// Skip for JSON debugging info requests
!isRequestingJsonForDebugging &&
// Skip for airgapped sessions
!isAirgapped &&
// Skip for the GraphQL Explorer page
!isGraphQLExplorer

if (isCacheable) {
// Stop processing if the connection was already dropped
if (isConnectionDropped(req, res)) return

const cachedHtml = await pageCache.get(originalUrl)
if (cachedHtml) {
// Stop processing if the connection was already dropped
if (isConnectionDropped(req, res)) return

console.log(`Serving from cached version of ${originalUrl}`)
statsd.increment('page.sent_from_cache')
return res.send(modifyOutput(req, cachedHtml))
}
}

// add page context
const context = Object.assign({}, req.context, { page })

Expand Down
7 changes: 0 additions & 7 deletions script/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,13 +338,6 @@ Run this script to manually purge the Fastly cache for all language variants of
---


### [`purge-redis-pages.js`](purge-redis-pages.js)

Run this script to manually purge the Redis rendered page cache. This will typically only be run by Heroku during the deployment process, as triggered via our Procfile's "release" phase configuration.

---


### [`reconcile-category-dirs-with-ids.js`](reconcile-category-dirs-with-ids.js)

An automated test checks for discrepancies between category directory names and slugified category titles as IDs.
Expand Down
Loading

0 comments on commit df301cb

Please sign in to comment.