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

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

Comments

Loading...