Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restart browser if killed on Mermaid #1745

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 14 additions & 4 deletions mermaid/src/browser-instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import puppeteer from 'puppeteer'

import { logger } from './logger.js'

let INSTANCE

const createBrowser = async () => {
const browser = await puppeteer.launch({
headless: 'new',
Expand Down Expand Up @@ -30,8 +32,9 @@ const createBrowser = async () => {
'--disable-software-rasterizer'
]
})

const browserProcess = browser.process()
logger.info(`Chrome instance launched with pid ${browserProcess.pid}`)

browserProcess.stdout.unpipe()
browserProcess.stderr.unpipe()
browserProcess.stdout.on('data', (data) => {
Expand All @@ -50,6 +53,9 @@ const createBrowser = async () => {
})
browserProcess.on('exit', (code, signal) => {
logger.error({ code, signal }, 'chrome process exited')
browserProcess.kill()
browser.close()
INSTANCE = undefined
})
browserProcess.on('message', (message) => {
logger.warn({ message }, 'chrome process message')
Expand All @@ -60,10 +66,14 @@ const createBrowser = async () => {
await browser.close()
throw err
} finally {
browser.disconnect()
await browser.disconnect()
}
}

export async function create () {
return createBrowser()
export async function getBrowserWSEndpoint () {
if (INSTANCE === undefined) {
INSTANCE = await createBrowser()
logger.info(`Chrome accepting connections on endpoint ${INSTANCE.wsEndpoint()}`)
}
return INSTANCE.wsEndpoint()
}
5 changes: 1 addition & 4 deletions mermaid/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@ import http from 'node:http'
import micro from 'micro'
import { SyntaxError, TimeoutError, Worker } from './worker.js'
import Task from './task.js'
import { create } from './browser-instance.js'

(async () => {
// QUESTION: should we create a pool of Chrome instances ?
const browser = await create()
logger.info(`Chrome accepting connections on endpoint ${browser.wsEndpoint()}`)
const worker = new Worker(browser)
const worker = new Worker()
const server = new http.Server(
micro.serve(async (req, res) => {
// Add a /health route that renders a sample diagram by calling the worker
Expand Down
7 changes: 4 additions & 3 deletions mermaid/src/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from 'node:path'
import puppeteer, { HTTPResponse, Page } from 'puppeteer'
import { logger } from './logger.js'
import { updateConfig } from './config.js'
import { getBrowserWSEndpoint } from './browser-instance.js'

const __dirname = fileURLToPath(new URL('.', import.meta.url))

Expand All @@ -22,8 +23,7 @@ export class SyntaxError extends Error {
}

export class Worker {
constructor (browserInstance) {
this.browserWSEndpoint = browserInstance.wsEndpoint()
constructor () {
this.pageUrl = process.env.KROKI_MERMAID_PAGE_URL || `file://${path.join(__dirname, '..', 'assets', 'index.html')}`
this.convertTimeout = process.env.KROKI_MERMAID_CONVERT_TIMEOUT || '10000'
}
Expand Down Expand Up @@ -109,8 +109,9 @@ export class Worker {
* @private
*/
async _connect () {
const browserWSEndpoint = await getBrowserWSEndpoint()
return await puppeteer.connect({
browserWSEndpoint: this.browserWSEndpoint,
browserWSEndpoint,
ignoreHTTPSErrors: true
})
}
Expand Down