-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 605caf7
Showing
19 changed files
with
4,377 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"presets": [ | ||
"@babel/preset-env" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# ignore all by default | ||
* | ||
|
||
!src/ | ||
!.babelrc | ||
!package.json | ||
!yarn.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Global configurations | ||
LOG_LEVEL=DEBUG | ||
|
||
# Queue configurations | ||
QUEUE_REDIS_DSN=redis://redis:6379 | ||
|
||
# Manager configurations | ||
MANAGER_ENABLED=1 | ||
MANAGER_HTTP_SERVER_PORT=8990 | ||
|
||
# Worker configurations | ||
WORKER_ENABLED=1 | ||
WORKER_RENDERER_AUTHORIZED_REQUEST_DOMAINS=front.preprod-knp.i24news.org,api.preprod-knp.i24news.org | ||
WORKER_RENDERER_AUTHORIZED_REQUEST_TYPES=document,script,xhr,fetch,eventsource,websocket |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/build | ||
/node_modules | ||
.env | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
FROM node:slim as dev | ||
|
||
# Install latest chrome dev package and fonts to support major charsets (Chinese, Japanese, Arabic, Hebrew, Thai and a few others) | ||
# Note: this installs the necessary libs to make the bundled version of Chromium that Puppeteer | ||
# installs, work. | ||
# https://www.ubuntuupdates.org/package/google_chrome/stable/main/base/google-chrome-unstable | ||
RUN apt-get update \ | ||
&& apt-get install -y wget gnupg \ | ||
&& wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ | ||
&& sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \ | ||
&& apt-get update \ | ||
&& apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \ | ||
--no-install-recommends \ | ||
&& rm -rf /var/lib/apt/lists/* | ||
|
||
ADD https://github.com/Yelp/dumb-init/releases/download/v1.2.1/dumb-init_1.2.1_amd64 /usr/local/bin/dumb-init | ||
RUN chmod +x /usr/local/bin/dumb-init | ||
|
||
WORKDIR /app | ||
|
||
COPY --chown=1000:1000 src/ src/ | ||
COPY --chown=1000:1000 package.json package.json | ||
COPY --chown=1000:1000 yarn.lock yarn.lock | ||
COPY --chown=1000:1000 .babelrc .babelrc | ||
|
||
RUN yarn install | ||
|
||
USER 1000 | ||
|
||
ENTRYPOINT ["dumb-init", "--"] | ||
CMD ["yarn", "dev"] | ||
|
||
################################################################################ | ||
|
||
FROM dev as prod | ||
|
||
USER root | ||
|
||
ENV BABEL_ENV=production | ||
ENV NODE_ENV=production | ||
|
||
RUN yarn run build | ||
|
||
USER 1000 | ||
|
||
CMD ["yarn", "start"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
IMAGE_NAME = knplabs/server-side-renderer | ||
|
||
.PHONY: build | ||
build: .validate-tag | ||
docker build -t ${IMAGE_NAME}:${IMAGE_TAG} . | ||
|
||
.PHONY: build | ||
push: .validate-tag | ||
docker push ${IMAGE_NAME}:${IMAGE_TAG} | ||
|
||
.PHONY: .validate-tag | ||
.validate-tag: | ||
ifeq ($(IMAGE_TAG),) | ||
@echo "You can't build and push without an IMAGE_TAG.\n" | ||
@exit 1 | ||
endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
version: '3.6' | ||
|
||
services: | ||
chromium_pool: | ||
image: knplabs:chromium_pool | ||
env_file: .env | ||
build: | ||
context: . | ||
target: dev | ||
command: 'yarn dev' | ||
ports: | ||
- "8990:8990" | ||
volumes: | ||
- ./:/app | ||
|
||
redis: | ||
image: redis:6.2.2-buster |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "chromium-pool", | ||
"version": "1.0.0", | ||
"main": "index.js", | ||
"license": "MIT", | ||
"dependencies": { | ||
"bull": "^3.22.4", | ||
"express": "^4.17.1", | ||
"puppeteer": "^9.1.1", | ||
"ramda": "^0.27.1", | ||
"tree-kill": "^1.2.2", | ||
"uuid": "^8.3.2" | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.13.16", | ||
"@babel/core": "^7.14.0", | ||
"@babel/node": "^7.13.13", | ||
"@babel/preset-env": "^7.14.1", | ||
"nodemon": "^2.0.7", | ||
"regenerator-runtime": "^0.13.7" | ||
}, | ||
"scripts": { | ||
"dev": "nodemon --watch src/ --exec babel-node src/index.js", | ||
"build": "babel src/ -d build/ --ignore 'src/**/*.test.js'", | ||
"start": "node build/index.js" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import 'regenerator-runtime/runtime' // needed by the SSR to be able to execute transpiled generator functions like async/await | ||
import { call, equals, pipe } from 'ramda' | ||
import { default as createLogger, DEFAULT_LEVEL } from './logger' | ||
import setupProcessHandlers from './processHandlers' | ||
import createQueue from './queue' | ||
import initManager from './manager' | ||
import initWorker from './worker' | ||
|
||
const logger = createLogger(process.env.LOG_LEVEL || DEFAULT_LEVEL, console) | ||
|
||
const queue = createQueue(process.env.QUEUE_REDIS_DSN) | ||
|
||
const shouldStartManager = () => equals(1, Number(process.env.MANAGER_ENABLED)) | ||
|
||
const shouldStartWorker = () => equals(1, Number(process.env.WORKER_ENABLED)) | ||
|
||
// main :: (Logger, Queue) => _ | ||
const main = (logger, queue) => call(pipe( | ||
() => shouldStartManager() && initManager(logger, queue), | ||
() => shouldStartWorker() && initWorker(logger, queue), | ||
() => setupProcessHandlers(logger), | ||
)) | ||
|
||
main(logger, queue) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { __, bind, equals, findIndex, gt, gte, partial, pipe, when, pickAll } from 'ramda' | ||
|
||
const LEVEL_ERROR = 'ERROR' | ||
const LEVEL_WARN = 'WARN' | ||
const LEVEL_INFO = 'INFO' | ||
const LEVEL_DEBUG = 'DEBUG' | ||
|
||
const levels = [ | ||
LEVEL_ERROR, | ||
LEVEL_WARN, | ||
LEVEL_INFO, | ||
LEVEL_DEBUG, | ||
] | ||
|
||
// resolveLogLevelIndex :: String -> Number | ||
const resolveLogLevelIndex = pipe( | ||
level => findIndex(equals(level), levels), | ||
when(gt(0), levels.length), | ||
) | ||
|
||
// loggerHead :: (String, String) -> Boolean | ||
const shouldPrintLog = (loggerLevel, logLevel) => gte( | ||
resolveLogLevelIndex(loggerLevel), | ||
resolveLogLevelIndex(logLevel), | ||
) | ||
|
||
// loggerHead :: String-> String | ||
const loggerHead = type => `[${(new Date()).toISOString()}] ${type.toUpperCase()}:` | ||
|
||
// error :: (String, Output) -> Function | ||
const error = (level, output) => when( | ||
level => shouldPrintLog(level, LEVEL_ERROR), | ||
() => partial( | ||
bind(output.error, output), | ||
[loggerHead(LEVEL_ERROR)], | ||
), | ||
)(level) | ||
|
||
// warn :: (String, Output) -> Function | ||
const warn = (level, output) => when( | ||
level => shouldPrintLog(level, LEVEL_WARN), | ||
() => partial( | ||
bind(output.warn, output), | ||
[loggerHead(LEVEL_WARN)], | ||
), | ||
)(level) | ||
|
||
// info :: (String, Output) -> Function | ||
const info = (level, output) => when( | ||
level => shouldPrintLog(level, LEVEL_INFO), | ||
() => partial( | ||
bind(output.info, output), | ||
[loggerHead(LEVEL_INFO)], | ||
), | ||
)(level) | ||
|
||
// debug :: (String, Output) -> Function | ||
const debug = (level, output) => when( | ||
level => shouldPrintLog(level, LEVEL_DEBUG), | ||
() => partial( | ||
bind(output.log, output), | ||
[loggerHead(LEVEL_DEBUG)], | ||
), | ||
)(level) | ||
|
||
export const DEFAULT_LEVEL = LEVEL_DEBUG | ||
|
||
export const formatException = e => JSON.stringify(pickAll(['code', 'message', 'stack'], e)) | ||
|
||
// createLogger :: (String, Output) -> Logger | ||
export default (level, output) => ({ | ||
error: error(level, output), | ||
info: info(level, output), | ||
debug: debug(level, output), | ||
warn: warn(level, output), | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { pipe } from 'ramda' | ||
import express from 'express' | ||
import attachRenderMiddleware from './middlewares/render' | ||
|
||
// createHttpServer => (Logger, Queue) -> HttpServer | ||
export default (logger, queue, requestRegistry) => pipe( | ||
attachRenderMiddleware(logger, queue, requestRegistry), | ||
app => app.listen( | ||
Number(process.env.MANAGER_HTTP_SERVER_PORT) || 8990, | ||
process.env.MANAGER_HTTP_SERVER_HOST || '0.0.0.0', | ||
() => logger.info('Manager http server started.'), | ||
) | ||
)(express()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { call, complement, compose, ifElse, isNil, path, pipe } from 'ramda' | ||
import { DEFAULT_JOB_OPTIONS } from '../../../queue' | ||
|
||
export default (logger, queue, requestRegistry) => app => | ||
app.get('/render', (req, res, next) => call(pipe( | ||
() => logger.info(`Render request for url "${req.query.url}" started.`), | ||
ifElse( | ||
() => compose(complement(isNil), path(['query', 'url']))(req), | ||
pipe( | ||
() => requestRegistry.add(req, res, next), | ||
jobId => queue.add({ | ||
url: req.query.url | ||
}, { | ||
...DEFAULT_JOB_OPTIONS, | ||
jobId, | ||
}), | ||
), | ||
() => res.status(400).end('Missing url query parameter.') | ||
), | ||
))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { call, juxt, pipe, tap, when } from 'ramda' | ||
import initHttpServer from './http-server' | ||
import createRequestRegistry from './requestRegistry' | ||
|
||
const onJobCompleted = (logger, requestRegistry) => (jobId, result) => when( | ||
jobId => requestRegistry.has(jobId), | ||
juxt([ | ||
jobId => requestRegistry.complete(jobId, JSON.parse(result)), | ||
jobId => logger.info(`Completed job "${jobId}"`), | ||
]), | ||
)(jobId) | ||
|
||
const onJobFailed = (logger, requestRegistry) => (jobId, error) => when( | ||
jobId => requestRegistry.has(jobId), | ||
juxt([ | ||
jobId => requestRegistry.fail(jobId, error), | ||
jobId => logger.error(`Job "${jobId}" has failed. ${error}.`), | ||
]), | ||
)(jobId) | ||
|
||
// initManager :: (Logger, Queue) -> _ | ||
export default (logger, queue) => call(pipe( | ||
() => logger.info('Initializing manager.'), | ||
() => createRequestRegistry(), | ||
tap(requestRegistry => queue.on('global:completed', onJobCompleted(logger, requestRegistry))), | ||
tap(requestRegistry => queue.on('global:failed', onJobFailed(logger, requestRegistry))), | ||
requestRegistry => initHttpServer(logger, queue, requestRegistry), | ||
() => logger.info('Manager initialized.'), | ||
)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { v4 as uuidv4 } from 'uuid' | ||
|
||
export default () => ({ | ||
_requests: {}, | ||
|
||
has: function (id) { | ||
return this._requests.hasOwnProperty(id) | ||
}, | ||
|
||
add: function (req, res, next) { | ||
const id = uuidv4() | ||
|
||
this._requests[id] = { req, res, next } | ||
|
||
return id | ||
}, | ||
|
||
complete: function (id, result) { | ||
if (this.has(id)) { | ||
this._requests[id].res.send(result) | ||
delete this._requests[id] | ||
} | ||
}, | ||
|
||
fail: function (id, error) { | ||
if (this.has(id)) { | ||
this._requests[id].res.status(500).end() | ||
delete this._requests[id] | ||
} | ||
}, | ||
}) |
Oops, something went wrong.