Register
Login
Resources
Docs Blog Datasets Glossary Case Studies Tutorials & Webinars
Product
Data Engine LLMs Platform Enterprise
Pricing Explore
Connect to our Discord channel

server.js 3.6 KB

You have to be logged in to leave a comment. Sign In
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  1. require('dotenv').config()
  2. const throng = require('throng')
  3. const os = require('os')
  4. const portUsed = require('port-used')
  5. const prefixStreamWrite = require('./lib/prefix-stream-write')
  6. // Intentionally require these for both cluster primary and workers
  7. require('./lib/check-node-version')
  8. require('./lib/handle-exceptions')
  9. require('./lib/feature-flags')
  10. const { PORT, NODE_ENV } = process.env
  11. const port = Number(PORT) || 4000
  12. // Start the server!
  13. if (NODE_ENV === 'production') {
  14. clusteredMain()
  15. } else {
  16. nonClusteredMain()
  17. }
  18. function clusteredMain () {
  19. // Spin up a cluster!
  20. throng({
  21. master: setupPrimary,
  22. worker: setupWorker,
  23. count: calculateWorkerCount()
  24. })
  25. }
  26. async function nonClusteredMain () {
  27. await checkPortAvailability()
  28. await startServer()
  29. }
  30. async function checkPortAvailability () {
  31. // Check that the development server is not already running
  32. const portInUse = await portUsed.check(port)
  33. if (portInUse) {
  34. console.log(`\n\n\nPort ${port} is not available. You may already have a server running.`)
  35. console.log('Try running `killall node` to shut down all your running node processes.\n\n\n')
  36. console.log('\x07') // system 'beep' sound
  37. process.exit(1)
  38. }
  39. }
  40. async function startServer () {
  41. const app = require('./lib/app')
  42. const warmServer = require('./lib/warm-server')
  43. // If in a deployed environment...
  44. if (NODE_ENV === 'production') {
  45. // If in a true production environment, wait for the cache to be fully warmed.
  46. if (process.env.HEROKU_PRODUCTION_APP || process.env.GITHUB_ACTIONS) {
  47. await warmServer()
  48. }
  49. }
  50. // Workaround for https://github.com/expressjs/express/issues/1101
  51. const server = require('http').createServer(app)
  52. server
  53. .listen(port, () => console.log(`app running on http://localhost:${port}`))
  54. .on('error', () => server.close())
  55. }
  56. // This function will only be run in the primary process
  57. async function setupPrimary () {
  58. process.on('beforeExit', () => {
  59. console.log('Shutting down primary...')
  60. console.log('Exiting!')
  61. })
  62. console.log('Starting up primary...')
  63. await checkPortAvailability()
  64. }
  65. // IMPORTANT: This function will be run in a separate worker process!
  66. async function setupWorker (id, disconnect) {
  67. let exited = false
  68. // Wrap stdout and stderr to include the worker ID as a static prefix
  69. // console.log('hi') => '[worker.1]: hi'
  70. const prefix = `[worker.${id}]: `
  71. prefixStreamWrite(process.stdout, prefix)
  72. prefixStreamWrite(process.stderr, prefix)
  73. process.on('beforeExit', () => {
  74. console.log('Exiting!')
  75. })
  76. process.on('SIGTERM', shutdown)
  77. process.on('SIGINT', shutdown)
  78. console.log('Starting up worker...')
  79. // Load the server in each worker process and share the port via sharding
  80. await startServer()
  81. function shutdown () {
  82. if (exited) return
  83. exited = true
  84. console.log('Shutting down worker...')
  85. disconnect()
  86. }
  87. }
  88. function calculateWorkerCount () {
  89. // Heroku's recommended WEB_CONCURRENCY count based on the WEB_MEMORY config,
  90. // or explicitly configured by us
  91. const { WEB_CONCURRENCY } = process.env
  92. const recommendedCount = parseInt(WEB_CONCURRENCY, 10)
  93. const cpuCount = os.cpus().length
  94. // Ensure the recommended count is AT LEAST 1 for safety
  95. let workerCount = Math.max(recommendedCount || 1, 1)
  96. // If WEB_CONCURRENCY value was configured to a valid number...
  97. if (recommendedCount > 0) {
  98. // Use the smaller value between the recommendation vs. the CPU count
  99. workerCount = Math.min(workerCount, cpuCount)
  100. } else if (NODE_ENV === 'production') {
  101. // Else if in a deployed environment, default to the CPU count
  102. workerCount = cpuCount
  103. }
  104. return workerCount
  105. }
Tip!

Press p or to see the previous file or, n or to see the next file

Comments

Loading...