backup-worker-app.mjs 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. // @ts-check
  2. // Metrics must be initialized before importing anything else
  3. import '@overleaf/metrics/initialize.js'
  4. import http from 'node:http'
  5. import { fileURLToPath } from 'node:url'
  6. import { promisify } from 'node:util'
  7. import express from 'express'
  8. import logger from '@overleaf/logger'
  9. import Metrics from '@overleaf/metrics'
  10. import { expressify } from '@overleaf/promise-utils'
  11. import { drainQueue, healthCheck } from './storage/scripts/backup_worker.mjs'
  12. const app = express()
  13. logger.initialize('history-v1-backup-worker')
  14. Metrics.open_sockets.monitor()
  15. Metrics.injectMetricsRoute(app)
  16. app.use(Metrics.http.monitor(logger))
  17. Metrics.leaked_sockets.monitor(logger)
  18. Metrics.event_loop.monitor(logger)
  19. Metrics.memory.monitor(logger)
  20. app.get('/status', (req, res) => {
  21. res.send('history-v1-backup-worker is up')
  22. })
  23. app.get(
  24. '/health_check',
  25. expressify(async (req, res) => {
  26. await healthCheck()
  27. res.sendStatus(200)
  28. })
  29. )
  30. app.use((err, req, res, next) => {
  31. req.logger.addFields({ err })
  32. req.logger.setLevel('error')
  33. next(err)
  34. })
  35. async function triggerGracefulShutdown(server, signal) {
  36. logger.info({ signal }, 'graceful shutdown: started shutdown sequence')
  37. await drainQueue()
  38. server.close(function () {
  39. logger.info({ signal }, 'graceful shutdown: closed server')
  40. setTimeout(() => {
  41. process.exit(0)
  42. }, 1000)
  43. })
  44. }
  45. /**
  46. * @param {number} port
  47. * @return {Promise<http.Server>}
  48. */
  49. export async function startApp(port) {
  50. await healthCheck()
  51. const server = http.createServer(app)
  52. await promisify(server.listen.bind(server, port))()
  53. const signals = ['SIGINT', 'SIGTERM']
  54. signals.forEach(signal => {
  55. process.on(signal, () => triggerGracefulShutdown(server, signal))
  56. })
  57. return server
  58. }
  59. // Run this if we're called directly
  60. if (process.argv[1] === fileURLToPath(import.meta.url)) {
  61. const PORT = parseInt(process.env.PORT || '3103', 10)
  62. await startApp(PORT)
  63. }