1
0
mirror of synced 2026-01-09 15:02:41 -05:00

Merge pull request #20063 from github/repo-sync

repo sync
This commit is contained in:
Octomerger Bot
2022-08-22 16:30:48 -04:00
committed by GitHub
7 changed files with 47 additions and 15 deletions

View File

@@ -19,7 +19,7 @@ shortTitle: Create HA replica
## Creating a high availability replica
1. Set up a new {% data variables.product.prodname_ghe_server %} appliance on your desired platform. The replica appliance should mirror the primary appliance's CPU, RAM, and storage settings. We recommend that you install the replica appliance in an independent environment. The underlying hardware, software, and network components should be isolated from those of the primary appliance. If you are a using a cloud provider, use a separate region or zone. For more information, see ["Setting up a {% data variables.product.prodname_ghe_server %} instance"](/enterprise/admin/guides/installation/setting-up-a-github-enterprise-server-instance).
1. Ensure that both the primary appliance and the new replica appliance can communicate with each other over ports 122/TCP and 1194/UDP. For more information, see "[Network ports](/admin/configuration/configuring-network-settings/network-ports#administrative-ports)."
1. Ensure that the new appliance can communicate with all other appliances in this high availability environment over ports 122/TCP and 1194/UDP. For more information, see "[Network ports](/admin/configuration/configuring-network-settings/network-ports#administrative-ports)."
1. In a browser, navigate to the new replica appliance's IP address and upload your {% data variables.product.prodname_enterprise %} license.
{% data reusables.enterprise_installation.replica-steps %}
1. Connect to the replica appliance's IP address using SSH.

View File

@@ -1,5 +1,7 @@
import express from 'express'
import { readCompressedJsonFileFallbackLazily } from '../lib/read-json-file.js'
import { defaultCacheControl } from './cache-control.js'
const clientSideRestAPIRedirects = readCompressedJsonFileFallbackLazily(
'./lib/redirects/static/client-side-rest-api-redirects.json'
@@ -15,6 +17,9 @@ router.get('/', function redirects(req, res, next) {
if (!req.query.hash) {
return res.status(400).send("Missing 'hash' query string")
}
defaultCacheControl(res)
const redirectFrom = `${req.query.path}#${req.query.hash}`
res.status(200).send({ to: clientSideRestAPIRedirects()[redirectFrom] } || null)
})

View File

@@ -3,7 +3,7 @@ import express from 'express'
import searchVersions from '../../lib/search/versions.js'
import languages from '../../lib/languages.js'
import { allVersions } from '../../lib/all-versions.js'
import { cacheControlFactory } from '../cache-control.js'
import { defaultCacheControl } from '../cache-control.js'
import catchMiddlewareError from '../catch-middleware-error.js'
import { getSearchResults, ELASTICSEARCH_URL } from './es-search.js'
@@ -13,8 +13,6 @@ const languagesSet = new Set(Object.keys(languages))
const router = express.Router()
const cacheControl = cacheControlFactory(60 * 60 * 24)
const DEFAULT_SIZE = 10
const MAX_SIZE = 50 // How much you return has a strong impact on performance
const DEFAULT_PAGE = 1
@@ -137,7 +135,7 @@ router.get(
}
})
if (process.env.NODE_ENV !== 'development') {
cacheControl(res)
defaultCacheControl(res)
}
res.setHeader('x-search-legacy', 'yes')
@@ -227,7 +225,7 @@ router.get(
// So the only distinguishing key is the request URL.
// Because of that, it's safe to allow the reverse proxy (a.k.a the CDN)
// cache and hold on to this.
cacheControl(res)
defaultCacheControl(res)
}
// The v1 version of the output matches perfectly what comes out

View File

@@ -38,3 +38,20 @@ export function cacheControlFactory(
res.set(key, directives)
}
}
// 24 hours for CDN, we soft-purge this with each deploy
const defaultCDNCacheControl = cacheControlFactory(60 * 60 * 24, {
key: 'surrogate-control',
})
// Shorter because between deployments and their (sort) purges,
// we don't want the browser to overly cache because with them we
// can't control purging.
const defaultBrowserCacheControl = cacheControlFactory(60)
// A general default configuration that is useful to almost all responses
// that can be cached.
export function defaultCacheControl(res) {
defaultCDNCacheControl(res)
defaultBrowserCacheControl(res)
}

View File

@@ -8,12 +8,7 @@ import statsd from '../lib/statsd.js'
import { allVersions } from '../lib/all-versions.js'
import { isConnectionDropped } from './halt-on-dropped-connection.js'
import { nextApp, nextHandleRequest } from './next.js'
import { cacheControlFactory } from './cache-control.js'
const browserCacheControl = cacheControlFactory(60) // 1 minute for browsers
const cdnCacheControl = cacheControlFactory(60 * 60 * 24, {
key: 'surrogate-control',
}) // 24 hours for CDN, we purge this with each deploy
import { defaultCacheControl } from './cache-control.js'
async function buildRenderedPage(req) {
const { context } = req
@@ -50,8 +45,6 @@ export default async function renderPage(req, res, next) {
const { page } = context
const path = req.pagePath || req.path
browserCacheControl(res)
cdnCacheControl(res)
// render a 404 page
if (!page) {
@@ -130,5 +123,7 @@ export default async function renderPage(req, res, next) {
}
}
defaultCacheControl(res)
return nextHandleRequest(req, res)
}

View File

@@ -15,6 +15,7 @@ import { jest, test, expect } from '@jest/globals'
import { describeIfElasticsearchURL } from '../helpers/conditional-runs.js'
import { get } from '../helpers/e2etest.js'
import { SURROGATE_ENUMS } from '../../middleware/set-fastly-surrogate-key.js'
if (!process.env.ELASTICSEARCH_URL) {
console.warn(
@@ -62,7 +63,10 @@ describeIfElasticsearchURL('search middleware', () => {
// Check that it can be cached at the CDN
expect(res.headers['set-cookie']).toBeUndefined()
expect(res.headers['cache-control']).toContain('public')
expect(res.headers['cache-control']).toMatch(/max-age=\d+/)
expect(res.headers['cache-control']).toMatch(/max-age=[1-9]/)
expect(res.headers['surrogate-control']).toContain('public')
expect(res.headers['surrogate-control']).toMatch(/max-age=[1-9]/)
expect(res.headers['surrogate-key']).toBe(SURROGATE_ENUMS.DEFAULT)
})
test('debug search', async () => {

View File

@@ -1,5 +1,7 @@
import { describe, expect } from '@jest/globals'
import { get } from '../helpers/e2etest.js'
import { SURROGATE_ENUMS } from '../../middleware/set-fastly-surrogate-key.js'
import clientSideRedirects from '../../lib/redirects/static/client-side-rest-api-redirects.json'
describe('anchor-redirect middleware', () => {
@@ -41,4 +43,15 @@ describe('anchor-redirect middleware', () => {
const { to } = JSON.parse(res.text)
expect(to).toBe(undefined)
})
test('reasonably aggressive cache-control headers', async () => {
const sp = new URLSearchParams()
sp.set('path', 'foo')
sp.set('hash', 'bar')
const res = await get('/anchor-redirect?' + sp)
expect(res.headers['cache-control']).toContain('public')
expect(res.headers['cache-control']).toMatch(/max-age=[1-9]/)
expect(res.headers['surrogate-control']).toContain('public')
expect(res.headers['surrogate-control']).toMatch(/max-age=[1-9]/)
expect(res.headers['surrogate-key']).toBe(SURROGATE_ENUMS.DEFAULT)
})
})