@sentio/runtime 2.40.0-rc.9 → 2.40.0
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/chunk-N7A3MJFE.js +131 -0
- package/lib/chunk-N7A3MJFE.js.map +1 -0
- package/lib/index.d.ts +22 -9
- package/lib/index.js +2 -93
- package/lib/index.js.map +1 -0
- package/lib/processor-runner.d.ts +3 -0
- package/lib/processor-runner.js +58 -51468
- package/lib/processor-runner.js.map +1 -0
- package/package.json +2 -2
- package/src/db-context.ts +51 -44
- package/src/index.ts +1 -0
- package/src/metrics.ts +138 -0
- package/src/multicall.ts +1615 -0
- package/src/otlp.ts +50 -0
- package/src/plugin.ts +7 -3
- package/src/processor-runner.ts +64 -21
- package/src/provider.ts +3 -9
- package/src/service.ts +98 -37
- package/src/tsup.config.ts +2 -0
- package/src/utils.ts +1 -1
- package/lib/chunk-FFU5RYDX.js +0 -78856
package/src/otlp.ts
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
import { envDetector } from '@opentelemetry/resources'
|
2
|
+
import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'
|
3
|
+
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc'
|
4
|
+
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus'
|
5
|
+
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'
|
6
|
+
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc'
|
7
|
+
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'
|
8
|
+
import { metrics, trace } from '@opentelemetry/api'
|
9
|
+
|
10
|
+
export async function setupOTLP() {
|
11
|
+
const resource = await envDetector.detect()
|
12
|
+
|
13
|
+
const meterProvider = new MeterProvider({
|
14
|
+
resource,
|
15
|
+
readers: [
|
16
|
+
new PeriodicExportingMetricReader({
|
17
|
+
exporter: new OTLPMetricExporter()
|
18
|
+
}),
|
19
|
+
new PrometheusExporter({
|
20
|
+
// http://localhost:4041/metrics
|
21
|
+
port: 4041
|
22
|
+
})
|
23
|
+
]
|
24
|
+
})
|
25
|
+
|
26
|
+
const traceProvider = new NodeTracerProvider({
|
27
|
+
resource: resource
|
28
|
+
})
|
29
|
+
const exporter = new OTLPTraceExporter() // new ConsoleSpanExporter();
|
30
|
+
const processor = new BatchSpanProcessor(exporter)
|
31
|
+
traceProvider.addSpanProcessor(processor)
|
32
|
+
traceProvider.register()
|
33
|
+
|
34
|
+
metrics.setGlobalMeterProvider(meterProvider)
|
35
|
+
trace.setGlobalTracerProvider(traceProvider)
|
36
|
+
;['SIGINT', 'SIGTERM'].forEach((signal) => {
|
37
|
+
process.on(signal as any, () => shutdownProvider())
|
38
|
+
})
|
39
|
+
}
|
40
|
+
|
41
|
+
export async function shutdownProvider() {
|
42
|
+
const traceProvider = trace.getTracerProvider()
|
43
|
+
if (traceProvider instanceof NodeTracerProvider) {
|
44
|
+
traceProvider.shutdown().catch(console.error)
|
45
|
+
}
|
46
|
+
const meterProvider = metrics.getMeterProvider()
|
47
|
+
if (meterProvider instanceof MeterProvider) {
|
48
|
+
meterProvider.shutdown().catch(console.error)
|
49
|
+
}
|
50
|
+
}
|
package/src/plugin.ts
CHANGED
@@ -28,7 +28,7 @@ export abstract class Plugin {
|
|
28
28
|
return ProcessResult.create()
|
29
29
|
}
|
30
30
|
|
31
|
-
async preprocessBinding(request: DataBinding): Promise<PreprocessResult> {
|
31
|
+
async preprocessBinding(request: DataBinding, preprocessStore: { [k: string]: any }): Promise<PreprocessResult> {
|
32
32
|
return PreprocessResult.create()
|
33
33
|
}
|
34
34
|
}
|
@@ -84,13 +84,17 @@ export class PluginManager {
|
|
84
84
|
})
|
85
85
|
}
|
86
86
|
|
87
|
-
preprocessBinding(
|
87
|
+
preprocessBinding(
|
88
|
+
request: DataBinding,
|
89
|
+
preprocessStore: { [k: string]: any },
|
90
|
+
dbContext?: StoreContext
|
91
|
+
): Promise<PreprocessResult> {
|
88
92
|
const plugin = this.typesToPlugin.get(request.handlerType)
|
89
93
|
if (!plugin) {
|
90
94
|
throw new Error(`No plugin for ${request.handlerType}`)
|
91
95
|
}
|
92
96
|
return this.dbContextLocalStorage.run(dbContext, () => {
|
93
|
-
return plugin.preprocessBinding(request)
|
97
|
+
return plugin.preprocessBinding(request, preprocessStore)
|
94
98
|
})
|
95
99
|
}
|
96
100
|
}
|
package/src/processor-runner.ts
CHANGED
@@ -7,9 +7,9 @@ import { compressionAlgorithms } from '@grpc/grpc-js'
|
|
7
7
|
import commandLineArgs from 'command-line-args'
|
8
8
|
import { createServer } from 'nice-grpc'
|
9
9
|
import { errorDetailsServerMiddleware } from 'nice-grpc-error-details'
|
10
|
-
import { registry as niceGrpcRegistry
|
10
|
+
// import { registry as niceGrpcRegistry } from 'nice-grpc-prometheus'
|
11
11
|
import { openTelemetryServerMiddleware } from 'nice-grpc-opentelemetry'
|
12
|
-
import { register as globalRegistry, Registry } from 'prom-client'
|
12
|
+
// import { register as globalRegistry, Registry } from 'prom-client'
|
13
13
|
import http from 'http'
|
14
14
|
// @ts-ignore inspector promises is not included in @type/node
|
15
15
|
import { Session } from 'node:inspector/promises'
|
@@ -21,22 +21,17 @@ import { FullProcessorServiceImpl } from './full-service.js'
|
|
21
21
|
import { ChainConfig } from './chain-config.js'
|
22
22
|
import { setupLogger } from './logger.js'
|
23
23
|
|
24
|
-
import { NodeSDK } from '@opentelemetry/sdk-node'
|
24
|
+
// import { NodeSDK } from '@opentelemetry/sdk-node'
|
25
|
+
import { envDetector } from '@opentelemetry/resources'
|
25
26
|
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc'
|
26
27
|
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc'
|
27
|
-
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'
|
28
|
+
import { PeriodicExportingMetricReader, MeterProvider } from '@opentelemetry/sdk-metrics'
|
29
|
+
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'
|
30
|
+
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'
|
31
|
+
import { diag, DiagConsoleLogger, DiagLogLevel, metrics, trace } from '@opentelemetry/api'
|
32
|
+
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus'
|
28
33
|
|
29
|
-
const
|
30
|
-
traceExporter: new OTLPTraceExporter(),
|
31
|
-
metricReader: new PeriodicExportingMetricReader({
|
32
|
-
exporter: new OTLPMetricExporter()
|
33
|
-
})
|
34
|
-
// instrumentations: [getNodeAutoInstrumentations()],
|
35
|
-
})
|
36
|
-
|
37
|
-
sdk.start()
|
38
|
-
|
39
|
-
const mergedRegistry = Registry.merge([globalRegistry, niceGrpcRegistry])
|
34
|
+
// const mergedRegistry = Registry.merge([globalRegistry, niceGrpcRegistry])
|
40
35
|
|
41
36
|
const optionDefinitions = [
|
42
37
|
{ name: 'target', type: String, defaultOption: true },
|
@@ -58,9 +53,57 @@ const optionDefinitions = [
|
|
58
53
|
|
59
54
|
const options = commandLineArgs(optionDefinitions, { partial: true })
|
60
55
|
|
61
|
-
|
56
|
+
const logLevel = process.env['LOG_LEVEL']?.toUpperCase()
|
57
|
+
|
58
|
+
setupLogger(options['log-format'] === 'json', logLevel === 'debug' ? true : options.debug)
|
62
59
|
console.debug('Starting with', options.target)
|
63
60
|
|
61
|
+
if (options.debug) {
|
62
|
+
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG)
|
63
|
+
}
|
64
|
+
|
65
|
+
const resource = await envDetector.detect()
|
66
|
+
|
67
|
+
const meterProvider = new MeterProvider({
|
68
|
+
resource,
|
69
|
+
readers: [
|
70
|
+
new PeriodicExportingMetricReader({
|
71
|
+
exporter: new OTLPMetricExporter()
|
72
|
+
}),
|
73
|
+
new PrometheusExporter({
|
74
|
+
// http://localhost:4041/metrics
|
75
|
+
port: 4041
|
76
|
+
})
|
77
|
+
]
|
78
|
+
})
|
79
|
+
|
80
|
+
const traceProvider = new NodeTracerProvider({
|
81
|
+
resource: resource
|
82
|
+
})
|
83
|
+
const exporter = new OTLPTraceExporter() // new ConsoleSpanExporter();
|
84
|
+
const processor = new BatchSpanProcessor(exporter)
|
85
|
+
traceProvider.addSpanProcessor(processor)
|
86
|
+
traceProvider.register()
|
87
|
+
|
88
|
+
metrics.setGlobalMeterProvider(meterProvider)
|
89
|
+
trace.setGlobalTracerProvider(traceProvider)
|
90
|
+
;['SIGINT', 'SIGTERM'].forEach((signal) => {
|
91
|
+
process.on(signal as any, () => shutdownProvider())
|
92
|
+
})
|
93
|
+
|
94
|
+
export async function shutdownProvider() {
|
95
|
+
const traceProvider = trace.getTracerProvider()
|
96
|
+
if (traceProvider instanceof NodeTracerProvider) {
|
97
|
+
traceProvider.shutdown().catch(console.error)
|
98
|
+
}
|
99
|
+
const meterProvider = metrics.getMeterProvider()
|
100
|
+
if (meterProvider instanceof MeterProvider) {
|
101
|
+
meterProvider.shutdown().catch(console.error)
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
metrics.getMeter('processor').createGauge('up').record(1)
|
106
|
+
|
64
107
|
Error.stackTraceLimit = 20
|
65
108
|
|
66
109
|
const fullPath = path.resolve(options['chains-config'])
|
@@ -99,7 +142,7 @@ const server = createServer({
|
|
99
142
|
'grpc.max_receive_message_length': 384 * 1024 * 1024,
|
100
143
|
'grpc.default_compression_algorithm': compressionAlgorithms.gzip
|
101
144
|
})
|
102
|
-
.use(prometheusServerMiddleware())
|
145
|
+
// .use(prometheusServerMiddleware())
|
103
146
|
.use(openTelemetryServerMiddleware())
|
104
147
|
.use(errorDetailsServerMiddleware)
|
105
148
|
const baseService = new ProcessorServiceImpl(async () => {
|
@@ -122,10 +165,10 @@ const httpServer = http
|
|
122
165
|
const reqUrl = new URL(req.url, `http://${req.headers.host}`)
|
123
166
|
const queries = reqUrl.searchParams
|
124
167
|
switch (reqUrl.pathname) {
|
125
|
-
case '/metrics':
|
126
|
-
|
127
|
-
|
128
|
-
|
168
|
+
// case '/metrics':
|
169
|
+
// const metrics = await mergedRegistry.metrics()
|
170
|
+
// res.write(metrics)
|
171
|
+
// break
|
129
172
|
case '/profile': {
|
130
173
|
try {
|
131
174
|
const profileTime = parseInt(queries.get('t') || '1000', 10) || 1000
|
package/src/provider.ts
CHANGED
@@ -4,17 +4,11 @@ import PQueue from 'p-queue'
|
|
4
4
|
import { Endpoints } from './endpoints.js'
|
5
5
|
import { EthChainId } from '@sentio/chain'
|
6
6
|
import { LRUCache } from 'lru-cache'
|
7
|
-
import {
|
7
|
+
import { providerMetrics } from './metrics.js'
|
8
|
+
const { miss_count, hit_count, total_duration, total_queued, queue_size } = providerMetrics
|
8
9
|
|
9
10
|
export const DummyProvider = new JsonRpcProvider('', Network.from(1))
|
10
11
|
|
11
|
-
const meter = metrics.getMeter('processor_provider')
|
12
|
-
const hit_count = meter.createCounter('provider_hit_count')
|
13
|
-
const miss_count = meter.createCounter('provider_miss_count')
|
14
|
-
const queue_size = meter.createGauge('provider_queue_size')
|
15
|
-
const total_duration = meter.createCounter('provider_total_duration')
|
16
|
-
const total_queued = meter.createCounter('provider_total_queued')
|
17
|
-
|
18
12
|
const providers = new Map<string, JsonRpcProvider>()
|
19
13
|
|
20
14
|
// export function getEthChainId(networkish?: EthContext | EthChainId): EthChainId {
|
@@ -38,7 +32,7 @@ export function getProvider(chainId?: EthChainId): Provider {
|
|
38
32
|
const address = Endpoints.INSTANCE.chainServer.get(chainId)
|
39
33
|
const key = network.chainId.toString() + '-' + address
|
40
34
|
|
41
|
-
console.debug(`init provider for ${chainId}, address: ${address}`)
|
35
|
+
// console.debug(`init provider for ${chainId}, address: ${address}`)
|
42
36
|
let provider = providers.get(key)
|
43
37
|
|
44
38
|
if (provider) {
|
package/src/service.ts
CHANGED
@@ -30,15 +30,13 @@ import { freezeGlobalConfig, GLOBAL_CONFIG } from './global-config.js'
|
|
30
30
|
|
31
31
|
import { StoreContext } from './db-context.js'
|
32
32
|
import { Subject } from 'rxjs'
|
33
|
-
import { metrics } from '@opentelemetry/api'
|
34
33
|
import { getProvider } from './provider.js'
|
35
34
|
import { EthChainId } from '@sentio/chain'
|
36
35
|
import { Provider } from 'ethers'
|
36
|
+
import { decodeMulticallResult, encodeMulticallData, getMulticallAddress, Multicall3Call } from './multicall.js'
|
37
37
|
|
38
|
-
|
39
|
-
const process_binding_count =
|
40
|
-
const process_binding_time = meter.createCounter('process_binding_time')
|
41
|
-
const process_binding_error = meter.createCounter('process_binding_error')
|
38
|
+
import { processMetrics, providerMetrics, dbMetrics } from './metrics.js'
|
39
|
+
const { process_binding_count, process_binding_time, process_binding_error } = processMetrics
|
42
40
|
|
43
41
|
;(BigInt.prototype as any).toJSON = function () {
|
44
42
|
return this.toString()
|
@@ -54,7 +52,7 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
54
52
|
|
55
53
|
private readonly shutdownHandler?: () => void
|
56
54
|
|
57
|
-
private
|
55
|
+
private preparedData: PreparedData | undefined
|
58
56
|
|
59
57
|
constructor(loader: () => Promise<any>, shutdownHandler?: () => void) {
|
60
58
|
this.loader = loader
|
@@ -128,11 +126,11 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
128
126
|
}
|
129
127
|
|
130
128
|
async processBindings(request: ProcessBindingsRequest, options?: CallContext): Promise<ProcessBindingResponse> {
|
131
|
-
const
|
129
|
+
const preparedData = await this.preprocessBindings(request.bindings, {}, undefined, options)
|
132
130
|
|
133
131
|
const promises = []
|
134
132
|
for (const binding of request.bindings) {
|
135
|
-
const promise = this.processBinding(binding,
|
133
|
+
const promise = this.processBinding(binding, preparedData)
|
136
134
|
if (GLOBAL_CONFIG.execution.sequential) {
|
137
135
|
await promise
|
138
136
|
}
|
@@ -141,7 +139,9 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
141
139
|
let promise
|
142
140
|
try {
|
143
141
|
promise = await Promise.all(promises)
|
142
|
+
processMetrics.process_binding_count.add(request.bindings.length)
|
144
143
|
} catch (e) {
|
144
|
+
processMetrics.process_binding_error.add(request.bindings.length)
|
145
145
|
throw e
|
146
146
|
}
|
147
147
|
const result = mergeProcessResults(promise)
|
@@ -159,13 +159,14 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
159
159
|
|
160
160
|
async preprocessBindings(
|
161
161
|
bindings: DataBinding[],
|
162
|
+
preprocessStore: { [k: string]: any },
|
162
163
|
dbContext?: StoreContext,
|
163
164
|
options?: CallContext
|
164
|
-
): Promise<
|
165
|
-
console.debug(`preprocessBindings start, bindings: ${bindings.length}`)
|
165
|
+
): Promise<PreparedData> {
|
166
|
+
// console.debug(`preprocessBindings start, bindings: ${bindings.length}`)
|
166
167
|
const promises = []
|
167
168
|
for (const binding of bindings) {
|
168
|
-
promises.push(this.preprocessBinding(binding, dbContext, options))
|
169
|
+
promises.push(this.preprocessBinding(binding, preprocessStore, dbContext, options))
|
169
170
|
}
|
170
171
|
let preprocessResults: PreprocessResult[]
|
171
172
|
try {
|
@@ -173,19 +174,15 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
173
174
|
} catch (e) {
|
174
175
|
throw e
|
175
176
|
}
|
176
|
-
console.debug(
|
177
|
-
'ethCallParams: ',
|
178
|
-
preprocessResults.map((r) => r.ethCallParams)
|
179
|
-
)
|
180
177
|
const groupedRequests = new Map<string, EthCallParam[]>()
|
181
178
|
const providers = new Map<string, Provider>()
|
182
179
|
for (const result of preprocessResults) {
|
183
180
|
for (const param of result.ethCallParams) {
|
184
|
-
const { chainId,
|
181
|
+
const { chainId, blockTag } = param.context!
|
185
182
|
if (!providers.has(chainId)) {
|
186
183
|
providers.set(chainId, getProvider(chainId as EthChainId))
|
187
184
|
}
|
188
|
-
const key = [chainId,
|
185
|
+
const key = [chainId, blockTag].join('|')
|
189
186
|
if (!groupedRequests.has(key)) {
|
190
187
|
groupedRequests.set(key, [])
|
191
188
|
}
|
@@ -194,36 +191,84 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
194
191
|
}
|
195
192
|
|
196
193
|
const start = Date.now()
|
197
|
-
const
|
194
|
+
const MULTICALL_THRESHOLD = 1
|
195
|
+
const callPromises: Promise<[string, string]>[] = []
|
196
|
+
const multicallPromises: Promise<[string, string][]>[] = []
|
197
|
+
|
198
198
|
for (const params of groupedRequests.values()) {
|
199
|
-
const { chainId,
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
199
|
+
const { chainId, blockTag } = params[0].context!
|
200
|
+
const multicallAddress = getMulticallAddress(chainId as EthChainId)
|
201
|
+
if (params.length <= MULTICALL_THRESHOLD || !multicallAddress) {
|
202
|
+
for (const param of params) {
|
203
|
+
callPromises.push(
|
204
|
+
providers
|
205
|
+
.get(chainId)!
|
206
|
+
.call({
|
207
|
+
to: param.context!.address,
|
208
|
+
data: param.calldata,
|
209
|
+
blockTag
|
210
|
+
})
|
211
|
+
.then((result) => [makeEthCallKey(param), result])
|
212
|
+
)
|
213
|
+
}
|
214
|
+
continue
|
215
|
+
}
|
216
|
+
|
217
|
+
// construct multicalls
|
218
|
+
const CHUNK_SIZE = 128
|
219
|
+
for (let i = 0; i < params.length; i += CHUNK_SIZE) {
|
220
|
+
const chunk = params.slice(i, i + CHUNK_SIZE)
|
221
|
+
const calls: Multicall3Call[] = chunk.map((param) => ({
|
222
|
+
target: param.context!.address,
|
223
|
+
callData: param.calldata
|
224
|
+
}))
|
225
|
+
const data = encodeMulticallData(calls)
|
226
|
+
multicallPromises.push(
|
204
227
|
providers
|
205
228
|
.get(chainId)!
|
206
229
|
.call({
|
207
|
-
to:
|
208
|
-
data:
|
230
|
+
to: multicallAddress,
|
231
|
+
data: data,
|
209
232
|
blockTag
|
210
233
|
})
|
211
|
-
.then((
|
234
|
+
.then((raw) => {
|
235
|
+
const result = decodeMulticallResult(raw).returnData
|
236
|
+
if (result.length != chunk.length) {
|
237
|
+
throw new Error(`multicall result length mismatch, params: ${chunk.length}, result: ${result.length}`)
|
238
|
+
}
|
239
|
+
const ret: [string, string][] = []
|
240
|
+
for (let i = 0; i < chunk.length; i++) {
|
241
|
+
ret.push([makeEthCallKey(chunk[i]), result[i]])
|
242
|
+
}
|
243
|
+
return ret
|
244
|
+
})
|
212
245
|
)
|
213
246
|
}
|
214
247
|
}
|
215
|
-
|
248
|
+
|
249
|
+
let results: { [p: string]: string } = {}
|
216
250
|
try {
|
217
251
|
results = Object.fromEntries(await Promise.all(callPromises))
|
252
|
+
for (const multicallResult of await Promise.all(multicallPromises)) {
|
253
|
+
results = {
|
254
|
+
...results,
|
255
|
+
...Object.fromEntries(multicallResult)
|
256
|
+
}
|
257
|
+
}
|
218
258
|
} catch (e) {
|
219
259
|
console.error(`eth call error: ${e}`)
|
220
260
|
}
|
221
|
-
console.
|
222
|
-
|
261
|
+
// console.debug(
|
262
|
+
// `${Object.keys(results).length} calls finished, actual calls: ${callPromises.length + multicallPromises.length}, elapsed: ${Date.now() - start}ms`
|
263
|
+
// )
|
264
|
+
return {
|
265
|
+
ethCallResults: results
|
266
|
+
}
|
223
267
|
}
|
224
268
|
|
225
269
|
async preprocessBinding(
|
226
270
|
request: DataBinding,
|
271
|
+
preprocessStore: { [k: string]: any },
|
227
272
|
dbContext?: StoreContext,
|
228
273
|
options?: CallContext
|
229
274
|
): Promise<PreprocessResult> {
|
@@ -242,7 +287,7 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
242
287
|
]
|
243
288
|
)
|
244
289
|
}
|
245
|
-
return await PluginManager.INSTANCE.preprocessBinding(request, dbContext)
|
290
|
+
return await PluginManager.INSTANCE.preprocessBinding(request, preprocessStore, dbContext)
|
246
291
|
}
|
247
292
|
|
248
293
|
async processBinding(
|
@@ -278,6 +323,7 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
278
323
|
const subject = new Subject<DeepPartial<ProcessStreamResponse>>()
|
279
324
|
this.handleRequests(requests, subject)
|
280
325
|
.then(() => {
|
326
|
+
this.preparedData = { ethCallResults: {} }
|
281
327
|
subject.complete()
|
282
328
|
})
|
283
329
|
.catch((e) => {
|
@@ -292,16 +338,23 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
292
338
|
subject: Subject<DeepPartial<PreprocessStreamResponse>>
|
293
339
|
) {
|
294
340
|
const contexts = new Contexts()
|
341
|
+
const preprocessStore: { [k: string]: any } = {}
|
295
342
|
|
296
343
|
for await (const request of requests) {
|
297
344
|
try {
|
298
|
-
console.debug('received request:', request)
|
299
345
|
if (request.bindings) {
|
300
346
|
const bindings = request.bindings.bindings
|
301
347
|
const dbContext = contexts.new(request.processId, subject)
|
302
348
|
const start = Date.now()
|
303
|
-
this.preprocessBindings(bindings, dbContext)
|
304
|
-
.then(() => {
|
349
|
+
this.preprocessBindings(bindings, preprocessStore, dbContext, undefined)
|
350
|
+
.then((preparedData) => {
|
351
|
+
// TODO maybe not proper to pass data in this way
|
352
|
+
this.preparedData = {
|
353
|
+
ethCallResults: {
|
354
|
+
...this.preparedData?.ethCallResults,
|
355
|
+
...preparedData.ethCallResults
|
356
|
+
}
|
357
|
+
}
|
305
358
|
subject.next({
|
306
359
|
processId: request.processId
|
307
360
|
})
|
@@ -352,14 +405,16 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
352
405
|
|
353
406
|
for await (const request of requests) {
|
354
407
|
try {
|
355
|
-
console.debug('received request:', request)
|
408
|
+
// console.debug('received request:', request)
|
356
409
|
if (request.binding) {
|
357
410
|
process_binding_count.add(1)
|
358
411
|
const binding = request.binding
|
359
412
|
const dbContext = contexts.new(request.processId, subject)
|
360
413
|
const start = Date.now()
|
361
|
-
PluginManager.INSTANCE.processBinding(binding,
|
362
|
-
.then((result) => {
|
414
|
+
PluginManager.INSTANCE.processBinding(binding, this.preparedData, dbContext)
|
415
|
+
.then(async (result) => {
|
416
|
+
// await all pending db requests
|
417
|
+
await dbContext.awaitPendings()
|
363
418
|
subject.next({
|
364
419
|
result,
|
365
420
|
processId: request.processId
|
@@ -376,11 +431,17 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
376
431
|
console.debug('processBinding', request.processId, ' took', cost, 'ms')
|
377
432
|
process_binding_time.add(cost)
|
378
433
|
contexts.delete(request.processId)
|
434
|
+
console.debug('db stats', JSON.stringify(dbMetrics.stats()))
|
435
|
+
console.debug('provider stats', JSON.stringify(providerMetrics.stats()))
|
379
436
|
})
|
380
437
|
}
|
381
438
|
if (request.dbResult) {
|
382
439
|
const dbContext = contexts.get(request.processId)
|
383
|
-
|
440
|
+
try {
|
441
|
+
dbContext?.result(request.dbResult)
|
442
|
+
} catch (e) {
|
443
|
+
subject.error(new Error('db result error, process should stop'))
|
444
|
+
}
|
384
445
|
}
|
385
446
|
} catch (e) {
|
386
447
|
// should not happen
|
package/src/tsup.config.ts
CHANGED
package/src/utils.ts
CHANGED
@@ -34,5 +34,5 @@ export function makeEthCallKey(param: EthCallParam) {
|
|
34
34
|
throw new Error('null context for eth call')
|
35
35
|
}
|
36
36
|
const { chainId, address, blockTag } = param.context
|
37
|
-
return `${chainId}|${address}|${blockTag}|${param.calldata}
|
37
|
+
return `${chainId}|${address}|${blockTag}|${param.calldata}`.toLowerCase()
|
38
38
|
}
|