@sentio/runtime 2.62.0-rc.4 → 2.62.0-rc.5

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.
@@ -10,7 +10,7 @@ import {
10
10
  require_cjs,
11
11
  require_lib3 as require_lib,
12
12
  require_lib4 as require_lib2
13
- } from "./chunk-6SI5TBIR.js";
13
+ } from "./chunk-RPV67F56.js";
14
14
  import "./chunk-I5YHR3CE.js";
15
15
  import "./chunk-W3VN25ER.js";
16
16
  import {
@@ -1,4 +1,4 @@
1
- import { P as Plugin, c as DataBinding, d as ProcessResult, H as HandlerType } from './processor-KRKdS8v-.js';
1
+ import { P as Plugin, D as DataBinding, a as ProcessResult, H as HandlerType } from './processor-HNY62jHs.js';
2
2
  import { ProcessStreamResponse_Partitions, InitResponse, ProcessConfigResponse } from '@sentio/protos';
3
3
  import 'rxjs';
4
4
  import 'node:async_hooks';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentio/runtime",
3
- "version": "2.62.0-rc.4",
3
+ "version": "2.62.0-rc.5",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -18,8 +18,6 @@
18
18
  "piscina": "5.1.3"
19
19
  },
20
20
  "devDependencies": {
21
- "@types/command-line-args": "^5.2.3",
22
- "@types/command-line-usage": "^5.0.4",
23
21
  "@types/fs-extra": "^11.0.4"
24
22
  },
25
23
  "engines": {
@@ -3,7 +3,7 @@
3
3
  import fs from 'fs-extra'
4
4
 
5
5
  import { compressionAlgorithms } from '@grpc/grpc-js'
6
- import commandLineArgs from 'command-line-args'
6
+ import { Command, InvalidArgumentError } from 'commander'
7
7
  import { createServer } from 'nice-grpc'
8
8
  import { errorDetailsServerMiddleware } from 'nice-grpc-error-details'
9
9
  // import { registry as niceGrpcRegistry } from 'nice-grpc-prometheus'
@@ -33,189 +33,213 @@ try {
33
33
  } catch (e) {
34
34
  console.error('Failed to parse worker number', e)
35
35
  }
36
- export const optionDefinitions = [
37
- { name: 'target', type: String, defaultOption: true },
38
- { name: 'port', alias: 'p', type: String, defaultValue: '4000' },
39
- { name: 'concurrency', type: Number, defaultValue: 4 },
40
- { name: 'batch-count', type: Number, defaultValue: 1 },
41
- // { name: 'use-chainserver', type: Boolean, defaultValue: false },
42
- {
43
- name: 'chains-config',
44
- alias: 'c',
45
- type: String,
46
- defaultValue: 'chains-config.json'
47
- },
48
- { name: 'chainquery-server', type: String, defaultValue: '' },
49
- { name: 'pricefeed-server', type: String, defaultValue: '' },
50
- { name: 'log-format', type: String, defaultValue: 'console' },
51
- { name: 'debug', type: Boolean, defaultValue: false },
52
- { name: 'otlp-debug', type: Boolean, defaultValue: false },
53
- { name: 'start-action-server', type: Boolean, defaultValue: false },
54
- { name: 'worker', type: Number, defaultValue: workerNum },
55
- { name: 'process-timeout', type: Number, defaultValue: 60 },
56
- { name: 'worker-timeout', type: Number, defaultValue: parseInt(process.env['WORKER_TIMEOUT_SECONDS'] || '60') },
57
- {
58
- name: 'enable-partition',
59
- type: Boolean,
60
- defaultValue: process.env['SENTIO_ENABLE_BINDING_DATA_PARTITION'] === 'true'
36
+
37
+ function myParseInt(value: string, dummyPrevious: unknown): number {
38
+ // parseInt takes a string and a radix
39
+ const parsedValue = parseInt(value, 10)
40
+ if (isNaN(parsedValue)) {
41
+ throw new InvalidArgumentError('Not a number.')
61
42
  }
62
- ]
43
+ return parsedValue
44
+ }
63
45
 
64
- const options = commandLineArgs(optionDefinitions, { partial: true })
46
+ // Create Commander.js program
47
+ const program = new Command()
65
48
 
66
- const logLevel = process.env['LOG_LEVEL']?.toLowerCase()
49
+ program
50
+ .name('processor-runner')
51
+ .description('Sentio Processor Runtime')
52
+ .version('2.0.0-development')
53
+ .option('--target <path>', 'Path to the processor module to load')
54
+ .option('-p, --port <port>', 'Port to listen on', '4000')
55
+ .option('--concurrency <number>', 'Number of concurrent workers', myParseInt, 4)
56
+ .option('--batch-count <number>', 'Batch count for processing', myParseInt, 1)
57
+ .option('-c, --chains-config <path>', 'Path to chains configuration file', 'chains-config.json')
58
+ .option('--chainquery-server <url>', 'Chain query server URL', '')
59
+ .option('--pricefeed-server <url>', 'Price feed server URL', '')
60
+ .option('--log-format <format>', 'Log format (console|json)', 'console')
61
+ .option('--debug', 'Enable debug mode', false)
62
+ .option('--otlp-debug', 'Enable OTLP debug mode', false)
63
+ .option('--start-action-server', 'Start action server instead of processor server', false)
64
+ .option('--worker <number>', 'Number of worker threads', myParseInt, workerNum)
65
+ .option('--process-timeout <seconds>', 'Process timeout in seconds', myParseInt, 60)
66
+ .option(
67
+ '--worker-timeout <seconds>',
68
+ 'Worker timeout in seconds',
69
+ myParseInt,
70
+ parseInt(process.env['WORKER_TIMEOUT_SECONDS'] || '60')
71
+ )
72
+ .option(
73
+ '--enable-partition',
74
+ 'Enable binding data partition',
75
+ process.env['SENTIO_ENABLE_BINDING_DATA_PARTITION'] === 'true'
76
+ )
77
+ .action(async (options: any) => {
78
+ try {
79
+ await startServer(options)
80
+ } catch (error) {
81
+ console.error('Failed to start server:', error)
82
+ process.exit(1)
83
+ }
84
+ })
67
85
 
68
- setupLogger(options['log-format'] === 'json', logLevel === 'debug' ? true : options.debug)
69
- console.debug('Starting with', options.target)
86
+ // Parse arguments
87
+ program.parse()
70
88
 
71
- await setupOTLP(options['otlp-debug'])
89
+ async function startServer(options: any): Promise<void> {
90
+ const logLevel = process.env['LOG_LEVEL']?.toLowerCase()
72
91
 
73
- Error.stackTraceLimit = 20
92
+ setupLogger(options['log-format'] === 'json', logLevel === 'debug' ? true : options.debug)
93
+ console.debug('Starting with', options.target)
74
94
 
75
- configureEndpoints(options)
95
+ await setupOTLP(options['otlp-debug'])
76
96
 
77
- console.debug('Starting Server', options)
97
+ Error.stackTraceLimit = 20
78
98
 
79
- let server: any
80
- let baseService: ProcessorServiceImpl | ServiceManager
81
- const loader = async () => {
82
- const m = await import(options.target)
83
- console.debug('Module loaded', m)
84
- return m
85
- }
86
- if (options['start-action-server']) {
87
- server = new ActionServer(loader)
88
- server.listen(options.port)
89
- } else {
90
- server = createServer({
91
- 'grpc.max_send_message_length': 768 * 1024 * 1024,
92
- 'grpc.max_receive_message_length': 768 * 1024 * 1024,
93
- 'grpc.default_compression_algorithm': compressionAlgorithms.gzip
94
- })
95
- // .use(prometheusServerMiddleware())
96
- .use(openTelemetryServerMiddleware())
97
- .use(errorDetailsServerMiddleware)
99
+ configureEndpoints(options)
98
100
 
99
- if (options.worker > 1) {
100
- baseService = new ServiceManager(loader, options, server.shutdown)
101
- } else {
102
- baseService = new ProcessorServiceImpl(loader, options, server.shutdown)
101
+ console.debug('Starting Server', options)
102
+
103
+ let server: any
104
+ let baseService: ProcessorServiceImpl | ServiceManager
105
+ const loader = async () => {
106
+ const m = await import(options.target)
107
+ console.debug('Module loaded', m)
108
+ return m
103
109
  }
110
+ if (options['start-action-server']) {
111
+ server = new ActionServer(loader)
112
+ server.listen(options.port)
113
+ } else {
114
+ server = createServer({
115
+ 'grpc.max_send_message_length': 768 * 1024 * 1024,
116
+ 'grpc.max_receive_message_length': 768 * 1024 * 1024,
117
+ 'grpc.default_compression_algorithm': compressionAlgorithms.gzip
118
+ })
119
+ // .use(prometheusServerMiddleware())
120
+ .use(openTelemetryServerMiddleware())
121
+ .use(errorDetailsServerMiddleware)
104
122
 
105
- const service = new FullProcessorServiceImpl(baseService)
123
+ if (options.worker > 1) {
124
+ baseService = new ServiceManager(loader, options, server.shutdown)
125
+ } else {
126
+ baseService = new ProcessorServiceImpl(loader, options, server.shutdown)
127
+ }
106
128
 
107
- server.add(ProcessorDefinition, service)
108
- server.add(
109
- ProcessorV3Definition,
110
- new FullProcessorServiceV3Impl(new ProcessorServiceImplV3(loader, options, server.shutdown))
111
- )
112
- server.listen('0.0.0.0:' + options.port)
129
+ const service = new FullProcessorServiceImpl(baseService)
113
130
 
114
- console.log('Processor Server Started at:', options.port)
115
- }
131
+ server.add(ProcessorDefinition, service)
132
+ server.add(
133
+ ProcessorV3Definition,
134
+ new FullProcessorServiceV3Impl(new ProcessorServiceImplV3(loader, options, server.shutdown))
135
+ )
116
136
 
117
- const metricsPort = 4040
118
-
119
- const httpServer = http
120
- .createServer(async function (req, res) {
121
- if (req.url) {
122
- const reqUrl = new URL(req.url, `http://${req.headers.host}`)
123
- const queries = reqUrl.searchParams
124
- switch (reqUrl.pathname) {
125
- // case '/metrics':
126
- // const metrics = await mergedRegistry.metrics()
127
- // res.write(metrics)
128
- // break
129
- case '/heap': {
130
- try {
131
- const file = '/tmp/' + Date.now() + '.heapsnapshot'
132
- await dumpHeap(file)
133
- // send the file
134
- const readStream = fs.createReadStream(file)
135
- res.writeHead(200, { 'Content-Type': 'application/json' })
136
- readStream.pipe(res)
137
- res.end()
138
- } catch {
139
- res.writeHead(500)
140
- res.end()
137
+ server.listen('0.0.0.0:' + options.port)
138
+ console.log('Processor Server Started at:', options.port)
139
+ }
140
+ const metricsPort = 4040
141
+
142
+ const httpServer = http
143
+ .createServer(async function (req, res) {
144
+ if (req.url) {
145
+ const reqUrl = new URL(req.url, `http://${req.headers.host}`)
146
+ const queries = reqUrl.searchParams
147
+ switch (reqUrl.pathname) {
148
+ // case '/metrics':
149
+ // const metrics = await mergedRegistry.metrics()
150
+ // res.write(metrics)
151
+ // break
152
+ case '/heap': {
153
+ try {
154
+ const file = '/tmp/' + Date.now() + '.heapsnapshot'
155
+ await dumpHeap(file)
156
+ // send the file
157
+ const readStream = fs.createReadStream(file)
158
+ res.writeHead(200, { 'Content-Type': 'application/json' })
159
+ readStream.pipe(res)
160
+ res.end()
161
+ } catch {
162
+ res.writeHead(500)
163
+ res.end()
164
+ }
165
+ break
141
166
  }
142
- break
143
- }
144
- case '/profile': {
145
- try {
146
- const profileTime = parseInt(queries.get('t') || '1000', 10) || 1000
147
- const session = new Session()
148
- session.connect()
149
-
150
- await session.post('Profiler.enable')
151
- await session.post('Profiler.start')
152
-
153
- await new Promise((resolve) => setTimeout(resolve, profileTime))
154
- const { profile } = await session.post('Profiler.stop')
155
-
156
- res.writeHead(200, { 'Content-Type': 'application/json' })
157
- res.write(JSON.stringify(profile))
158
- session.disconnect()
159
- } catch {
160
- res.writeHead(500)
167
+ case '/profile': {
168
+ try {
169
+ const profileTime = parseInt(queries.get('t') || '1000', 10) || 1000
170
+ const session = new Session()
171
+ session.connect()
172
+
173
+ await session.post('Profiler.enable')
174
+ await session.post('Profiler.start')
175
+
176
+ await new Promise((resolve) => setTimeout(resolve, profileTime))
177
+ const { profile } = await session.post('Profiler.stop')
178
+
179
+ res.writeHead(200, { 'Content-Type': 'application/json' })
180
+ res.write(JSON.stringify(profile))
181
+ session.disconnect()
182
+ } catch {
183
+ res.writeHead(500)
184
+ }
185
+ break
161
186
  }
162
- break
187
+ default:
188
+ res.writeHead(404)
163
189
  }
164
- default:
165
- res.writeHead(404)
190
+ } else {
191
+ res.writeHead(404)
166
192
  }
167
- } else {
168
- res.writeHead(404)
169
- }
170
- res.end()
171
- })
172
- .listen(metricsPort)
193
+ res.end()
194
+ })
195
+ .listen(metricsPort)
173
196
 
174
- console.log('Metric Server Started at:', metricsPort)
197
+ console.log('Metric Server Started at:', metricsPort)
175
198
 
176
- process
177
- .on('SIGINT', function () {
178
- shutdownServers(0)
179
- })
180
- .on('uncaughtException', (err) => {
181
- console.error('Uncaught Exception, please checking if await is properly used', err)
182
- if (baseService) {
183
- baseService.unhandled = err
184
- }
185
- // shutdownServers(1)
186
- })
187
- .on('unhandledRejection', (reason, p) => {
188
- // @ts-ignore ignore invalid ens error
189
- if (reason?.message.startsWith('invalid ENS name (disallowed character: "*"')) {
190
- return
191
- }
192
- console.error('Unhandled Rejection, please checking if await is properly', reason)
193
- if (baseService) {
194
- baseService.unhandled = reason as Error
195
- }
196
- // shutdownServers(1)
197
- })
199
+ process
200
+ .on('SIGINT', function () {
201
+ shutdownServers(server, httpServer, 0)
202
+ })
203
+ .on('uncaughtException', (err) => {
204
+ console.error('Uncaught Exception, please checking if await is properly used', err)
205
+ if (baseService) {
206
+ baseService.unhandled = err
207
+ }
208
+ // shutdownServers(1)
209
+ })
210
+ .on('unhandledRejection', (reason, p) => {
211
+ // @ts-ignore ignore invalid ens error
212
+ if (reason?.message.startsWith('invalid ENS name (disallowed character: "*"')) {
213
+ return
214
+ }
215
+ console.error('Unhandled Rejection, please checking if await is properly', reason)
216
+ if (baseService) {
217
+ baseService.unhandled = reason as Error
218
+ }
219
+ // shutdownServers(1)
220
+ })
198
221
 
199
- if (process.env['OOM_DUMP_MEMORY_SIZE_GB']) {
200
- let dumping = false
201
- const memorySize = parseFloat(process.env['OOM_DUMP_MEMORY_SIZE_GB'])
202
- console.log('heap dumping is enabled, limit set to ', memorySize, 'gb')
203
- const dir = process.env['OOM_DUMP_DIR'] || '/tmp'
204
- setInterval(async () => {
205
- const mem = process.memoryUsage()
206
- console.log('Current Memory Usage', mem)
207
- // if memory usage is greater this size, dump heap and exit
208
- if (mem.heapTotal > memorySize * 1024 * 1024 * 1024 && !dumping) {
209
- const file = path.join(dir, `${Date.now()}.heapsnapshot`)
210
- dumping = true
211
- await dumpHeap(file)
212
- // force exit and keep pod running
213
- process.exit(11)
214
- }
215
- }, 1000 * 60)
222
+ if (process.env['OOM_DUMP_MEMORY_SIZE_GB']) {
223
+ let dumping = false
224
+ const memorySize = parseFloat(process.env['OOM_DUMP_MEMORY_SIZE_GB']!)
225
+ console.log('heap dumping is enabled, limit set to ', memorySize, 'gb')
226
+ const dir = process.env['OOM_DUMP_DIR'] || '/tmp'
227
+ setInterval(async () => {
228
+ const mem = process.memoryUsage()
229
+ console.log('Current Memory Usage', mem)
230
+ // if memory usage is greater this size, dump heap and exit
231
+ if (mem.heapTotal > memorySize * 1024 * 1024 * 1024 && !dumping) {
232
+ const file = path.join(dir, `${Date.now()}.heapsnapshot`)
233
+ dumping = true
234
+ await dumpHeap(file)
235
+ // force exit and keep pod running
236
+ process.exit(11)
237
+ }
238
+ }, 1000 * 60)
239
+ }
216
240
  }
217
241
 
218
- async function dumpHeap(file: string) {
242
+ async function dumpHeap(file: string): Promise<void> {
219
243
  console.log('Heap dumping to', file)
220
244
  const session = new Session()
221
245
  fs.mkdirSync(path.dirname(file), { recursive: true })
@@ -234,7 +258,7 @@ async function dumpHeap(file: string) {
234
258
  }
235
259
  }
236
260
 
237
- function shutdownServers(exitCode: number) {
261
+ function shutdownServers(server: any, httpServer: any, exitCode: number): void {
238
262
  server?.forceShutdown()
239
263
  console.log('RPC server shut down')
240
264
 
@@ -139,7 +139,8 @@ export class ServiceManager extends ProcessorServiceImpl {
139
139
  argv: process.argv,
140
140
  workerData: this.workerData
141
141
  })
142
- this.pool.on('message', (msg) => {
142
+ // @ts-ignore - Piscina message handling for template instance sync
143
+ this.pool.on('message', (msg: any) => {
143
144
  if (msg.event == 'add_template_instance') {
144
145
  // sync the template state from worker to the main thread
145
146
  TemplateInstanceState.INSTANCE.addValue(msg.value)