@sentio/runtime 2.62.0-rc.7 → 2.62.0-rc.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/processor-runner.js +681 -689
- package/lib/processor-runner.js.map +1 -1
- package/package.json +2 -2
- package/src/processor-runner.ts +140 -148
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@sentio/runtime",
|
3
|
-
"version": "2.62.0-rc.
|
3
|
+
"version": "2.62.0-rc.8",
|
4
4
|
"license": "Apache-2.0",
|
5
5
|
"type": "module",
|
6
6
|
"exports": {
|
@@ -31,7 +31,7 @@
|
|
31
31
|
"run": "tsx src/processor-runner.ts --log-format=json",
|
32
32
|
"run-benchmark": "tsx src/decode-benchmark.ts",
|
33
33
|
"start_js": "tsx ./lib/processor-runner.js $PWD/../../debug/dist/lib.js",
|
34
|
-
"start_ts": "tsx
|
34
|
+
"start_ts": "tsx src/processor-runner.ts --log-format=json $PWD/../../examples/x2y2/src/processor.ts",
|
35
35
|
"test": "glob -c 'tsx --test' '**/*.test.ts'"
|
36
36
|
}
|
37
37
|
}
|
package/src/processor-runner.ts
CHANGED
@@ -55,11 +55,11 @@ const program = new Command()
|
|
55
55
|
|
56
56
|
program
|
57
57
|
.allowUnknownOption()
|
58
|
-
.allowExcessArguments()
|
58
|
+
// .allowExcessArguments()
|
59
59
|
.name('processor-runner')
|
60
60
|
.description('Sentio Processor Runtime')
|
61
61
|
.version(packageJson.version)
|
62
|
-
.
|
62
|
+
.argument('<target>', 'Path to the processor module to load')
|
63
63
|
.option('-p, --port <port>', 'Port to listen on', '4000')
|
64
64
|
.option('--concurrency <number>', 'Number of concurrent workers', myParseInt, 4)
|
65
65
|
.option('--batch-count <number>', 'Batch count for processing', myParseInt, 1)
|
@@ -83,170 +83,162 @@ program
|
|
83
83
|
'Enable binding data partition',
|
84
84
|
process.env['SENTIO_ENABLE_BINDING_DATA_PARTITION'] === 'true'
|
85
85
|
)
|
86
|
-
.
|
87
|
-
try {
|
88
|
-
await startServer(options)
|
89
|
-
} catch (error) {
|
90
|
-
console.error('Failed to start server:', error)
|
91
|
-
process.exit(1)
|
92
|
-
}
|
93
|
-
})
|
86
|
+
.parse()
|
94
87
|
|
95
|
-
|
96
|
-
program.
|
88
|
+
const options = program.opts()
|
89
|
+
options.target = program.processedArgs[0]
|
97
90
|
|
98
|
-
|
99
|
-
const logLevel = process.env['LOG_LEVEL']?.toLowerCase()
|
91
|
+
const logLevel = process.env['LOG_LEVEL']?.toLowerCase()
|
100
92
|
|
101
|
-
|
102
|
-
|
93
|
+
setupLogger(options.logFormat === 'json', logLevel === 'debug' ? true : options.debug)
|
94
|
+
console.debug('Starting with', options.target)
|
103
95
|
|
104
|
-
|
96
|
+
await setupOTLP(options.otlpDebug)
|
105
97
|
|
106
|
-
|
98
|
+
Error.stackTraceLimit = 20
|
107
99
|
|
108
|
-
|
100
|
+
configureEndpoints(options)
|
109
101
|
|
110
|
-
|
102
|
+
console.debug('Starting Server', options)
|
111
103
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
104
|
+
let server: any
|
105
|
+
let baseService: ProcessorServiceImpl | ServiceManager
|
106
|
+
const loader = async () => {
|
107
|
+
const m = await import(options.target)
|
108
|
+
console.debug('Module loaded', m)
|
109
|
+
return m
|
110
|
+
}
|
111
|
+
if (options.startActionServer) {
|
112
|
+
server = new ActionServer(loader)
|
113
|
+
server.listen(options.port)
|
114
|
+
} else {
|
115
|
+
server = createServer({
|
116
|
+
'grpc.max_send_message_length': 768 * 1024 * 1024,
|
117
|
+
'grpc.max_receive_message_length': 768 * 1024 * 1024,
|
118
|
+
'grpc.default_compression_algorithm': compressionAlgorithms.gzip
|
119
|
+
})
|
120
|
+
// .use(prometheusServerMiddleware())
|
121
|
+
.use(openTelemetryServerMiddleware())
|
122
|
+
.use(errorDetailsServerMiddleware)
|
131
123
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
124
|
+
if (options.worker > 1) {
|
125
|
+
baseService = new ServiceManager(loader, options, server.shutdown)
|
126
|
+
} else {
|
127
|
+
baseService = new ProcessorServiceImpl(loader, options, server.shutdown)
|
128
|
+
}
|
137
129
|
|
138
|
-
|
130
|
+
const service = new FullProcessorServiceImpl(baseService)
|
139
131
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
132
|
+
server.add(ProcessorDefinition, service)
|
133
|
+
server.add(
|
134
|
+
ProcessorV3Definition,
|
135
|
+
new FullProcessorServiceV3Impl(new ProcessorServiceImplV3(loader, options, server.shutdown))
|
136
|
+
)
|
145
137
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
}
|
174
|
-
break
|
138
|
+
server.listen('0.0.0.0:' + options.port)
|
139
|
+
console.log('Processor Server Started at:', options.port)
|
140
|
+
}
|
141
|
+
const metricsPort = 4040
|
142
|
+
|
143
|
+
const httpServer = http
|
144
|
+
.createServer(async function (req, res) {
|
145
|
+
if (req.url) {
|
146
|
+
const reqUrl = new URL(req.url, `http://${req.headers.host}`)
|
147
|
+
const queries = reqUrl.searchParams
|
148
|
+
switch (reqUrl.pathname) {
|
149
|
+
// case '/metrics':
|
150
|
+
// const metrics = await mergedRegistry.metrics()
|
151
|
+
// res.write(metrics)
|
152
|
+
// break
|
153
|
+
case '/heap': {
|
154
|
+
try {
|
155
|
+
const file = '/tmp/' + Date.now() + '.heapsnapshot'
|
156
|
+
await dumpHeap(file)
|
157
|
+
// send the file
|
158
|
+
const readStream = fs.createReadStream(file)
|
159
|
+
res.writeHead(200, { 'Content-Type': 'application/json' })
|
160
|
+
readStream.pipe(res)
|
161
|
+
res.end()
|
162
|
+
} catch {
|
163
|
+
res.writeHead(500)
|
164
|
+
res.end()
|
175
165
|
}
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
166
|
+
break
|
167
|
+
}
|
168
|
+
case '/profile': {
|
169
|
+
try {
|
170
|
+
const profileTime = parseInt(queries.get('t') || '1000', 10) || 1000
|
171
|
+
const session = new Session()
|
172
|
+
session.connect()
|
173
|
+
|
174
|
+
await session.post('Profiler.enable')
|
175
|
+
await session.post('Profiler.start')
|
176
|
+
|
177
|
+
await new Promise((resolve) => setTimeout(resolve, profileTime))
|
178
|
+
const { profile } = await session.post('Profiler.stop')
|
179
|
+
|
180
|
+
res.writeHead(200, { 'Content-Type': 'application/json' })
|
181
|
+
res.write(JSON.stringify(profile))
|
182
|
+
session.disconnect()
|
183
|
+
} catch {
|
184
|
+
res.writeHead(500)
|
195
185
|
}
|
196
|
-
|
197
|
-
res.writeHead(404)
|
186
|
+
break
|
198
187
|
}
|
199
|
-
|
200
|
-
|
188
|
+
default:
|
189
|
+
res.writeHead(404)
|
201
190
|
}
|
202
|
-
|
203
|
-
|
204
|
-
|
191
|
+
} else {
|
192
|
+
res.writeHead(404)
|
193
|
+
}
|
194
|
+
res.end()
|
195
|
+
})
|
196
|
+
.listen(metricsPort)
|
205
197
|
|
206
|
-
|
198
|
+
console.log('Metric Server Started at:', metricsPort)
|
207
199
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
200
|
+
process
|
201
|
+
.on('SIGINT', function () {
|
202
|
+
shutdownServers(0)
|
203
|
+
})
|
204
|
+
.on('uncaughtException', (err) => {
|
205
|
+
console.error('Uncaught Exception, please checking if await is properly used', err)
|
206
|
+
if (baseService) {
|
207
|
+
baseService.unhandled = err
|
208
|
+
}
|
209
|
+
// shutdownServers(1)
|
210
|
+
})
|
211
|
+
.on('unhandledRejection', (reason, p) => {
|
212
|
+
// @ts-ignore ignore invalid ens error
|
213
|
+
if (reason?.message.startsWith('invalid ENS name (disallowed character: "*"')) {
|
214
|
+
return
|
215
|
+
}
|
216
|
+
console.error('Unhandled Rejection, please checking if await is properly', reason)
|
217
|
+
if (baseService) {
|
218
|
+
baseService.unhandled = reason as Error
|
219
|
+
}
|
220
|
+
// shutdownServers(1)
|
221
|
+
})
|
230
222
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
}
|
223
|
+
if (process.env['OOM_DUMP_MEMORY_SIZE_GB']) {
|
224
|
+
let dumping = false
|
225
|
+
const memorySize = parseFloat(process.env['OOM_DUMP_MEMORY_SIZE_GB']!)
|
226
|
+
console.log('heap dumping is enabled, limit set to ', memorySize, 'gb')
|
227
|
+
const dir = process.env['OOM_DUMP_DIR'] || '/tmp'
|
228
|
+
setInterval(async () => {
|
229
|
+
const mem = process.memoryUsage()
|
230
|
+
console.log('Current Memory Usage', mem)
|
231
|
+
// if memory usage is greater this size, dump heap and exit
|
232
|
+
if (mem.heapTotal > memorySize * 1024 * 1024 * 1024 && !dumping) {
|
233
|
+
const file = path.join(dir, `${Date.now()}.heapsnapshot`)
|
234
|
+
dumping = true
|
235
|
+
await dumpHeap(file)
|
236
|
+
// force exit and keep pod running
|
237
|
+
process.exit(11)
|
238
|
+
}
|
239
|
+
}, 1000 * 60)
|
249
240
|
}
|
241
|
+
// }
|
250
242
|
|
251
243
|
async function dumpHeap(file: string): Promise<void> {
|
252
244
|
console.log('Heap dumping to', file)
|
@@ -267,8 +259,8 @@ async function dumpHeap(file: string): Promise<void> {
|
|
267
259
|
}
|
268
260
|
}
|
269
261
|
|
270
|
-
function shutdownServers(
|
271
|
-
server
|
262
|
+
function shutdownServers(exitCode: number): void {
|
263
|
+
server.forceShutdown()
|
272
264
|
console.log('RPC server shut down')
|
273
265
|
|
274
266
|
httpServer.close(function () {
|