@sentio/runtime 2.40.0-rc.1 → 2.40.0-rc.10
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-LMUCLUM5.js → chunk-FFU5RYDX.js} +927 -232
- package/lib/index.d.ts +68 -5
- package/lib/index.js +3 -1
- package/lib/processor-runner.js +4 -1
- package/package.json +1 -1
- package/src/full-service.ts +5 -0
- package/src/gen/processor/protos/processor.ts +763 -173
- package/src/provider.ts +2 -0
- package/src/service.ts +98 -20
- package/src/utils.ts +11 -3
package/src/provider.ts
CHANGED
@@ -37,6 +37,8 @@ export function getProvider(chainId?: EthChainId): Provider {
|
|
37
37
|
|
38
38
|
const address = Endpoints.INSTANCE.chainServer.get(chainId)
|
39
39
|
const key = network.chainId.toString() + '-' + address
|
40
|
+
|
41
|
+
console.debug(`init provider for ${chainId}, address: ${address}`)
|
40
42
|
let provider = providers.get(key)
|
41
43
|
|
42
44
|
if (provider) {
|
package/src/service.ts
CHANGED
@@ -11,6 +11,8 @@ import {
|
|
11
11
|
HandlerType,
|
12
12
|
PreparedData,
|
13
13
|
PreprocessResult,
|
14
|
+
PreprocessStreamRequest,
|
15
|
+
PreprocessStreamResponse,
|
14
16
|
ProcessBindingResponse,
|
15
17
|
ProcessBindingsRequest,
|
16
18
|
ProcessConfigRequest,
|
@@ -23,7 +25,7 @@ import {
|
|
23
25
|
} from '@sentio/protos'
|
24
26
|
|
25
27
|
import { PluginManager } from './plugin.js'
|
26
|
-
import { errorString, mergeProcessResults } from './utils.js'
|
28
|
+
import { errorString, makeEthCallKey, mergeProcessResults } from './utils.js'
|
27
29
|
import { freezeGlobalConfig, GLOBAL_CONFIG } from './global-config.js'
|
28
30
|
|
29
31
|
import { StoreContext } from './db-context.js'
|
@@ -31,7 +33,7 @@ import { Subject } from 'rxjs'
|
|
31
33
|
import { metrics } from '@opentelemetry/api'
|
32
34
|
import { getProvider } from './provider.js'
|
33
35
|
import { EthChainId } from '@sentio/chain'
|
34
|
-
import { Provider
|
36
|
+
import { Provider } from 'ethers'
|
35
37
|
|
36
38
|
const meter = metrics.getMeter('processor_service')
|
37
39
|
const process_binding_count = meter.createCounter('process_binding_count')
|
@@ -52,6 +54,8 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
52
54
|
|
53
55
|
private readonly shutdownHandler?: () => void
|
54
56
|
|
57
|
+
private readonly preprocessedEthCalls: { [calldata: string]: any[] }
|
58
|
+
|
55
59
|
constructor(loader: () => Promise<any>, shutdownHandler?: () => void) {
|
56
60
|
this.loader = loader
|
57
61
|
this.shutdownHandler = shutdownHandler
|
@@ -124,7 +128,7 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
124
128
|
}
|
125
129
|
|
126
130
|
async processBindings(request: ProcessBindingsRequest, options?: CallContext): Promise<ProcessBindingResponse> {
|
127
|
-
const ethCallResults = await this.preprocessBindings(request, options)
|
131
|
+
const ethCallResults = await this.preprocessBindings(request.bindings, undefined, options)
|
128
132
|
|
129
133
|
const promises = []
|
130
134
|
for (const binding of request.bindings) {
|
@@ -154,12 +158,14 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
154
158
|
}
|
155
159
|
|
156
160
|
async preprocessBindings(
|
157
|
-
|
161
|
+
bindings: DataBinding[],
|
162
|
+
dbContext?: StoreContext,
|
158
163
|
options?: CallContext
|
159
|
-
): Promise<{ [
|
164
|
+
): Promise<{ [ethCallKey: string]: string }> {
|
165
|
+
console.debug(`preprocessBindings start, bindings: ${bindings.length}`)
|
160
166
|
const promises = []
|
161
|
-
for (const binding of
|
162
|
-
promises.push(this.preprocessBinding(binding, options))
|
167
|
+
for (const binding of bindings) {
|
168
|
+
promises.push(this.preprocessBinding(binding, dbContext, options))
|
163
169
|
}
|
164
170
|
let preprocessResults: PreprocessResult[]
|
165
171
|
try {
|
@@ -167,14 +173,19 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
167
173
|
} catch (e) {
|
168
174
|
throw e
|
169
175
|
}
|
176
|
+
console.debug(
|
177
|
+
'ethCallParams: ',
|
178
|
+
preprocessResults.map((r) => r.ethCallParams)
|
179
|
+
)
|
170
180
|
const groupedRequests = new Map<string, EthCallParam[]>()
|
171
181
|
const providers = new Map<string, Provider>()
|
172
182
|
for (const result of preprocessResults) {
|
173
183
|
for (const param of result.ethCallParams) {
|
174
|
-
|
175
|
-
|
184
|
+
const { chainId, address, blockTag } = param.context!
|
185
|
+
if (!providers.has(chainId)) {
|
186
|
+
providers.set(chainId, getProvider(chainId as EthChainId))
|
176
187
|
}
|
177
|
-
const key =
|
188
|
+
const key = [chainId, address, blockTag].join('|')
|
178
189
|
if (!groupedRequests.has(key)) {
|
179
190
|
groupedRequests.set(key, [])
|
180
191
|
}
|
@@ -185,27 +196,37 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
185
196
|
const start = Date.now()
|
186
197
|
const callPromises = []
|
187
198
|
for (const params of groupedRequests.values()) {
|
188
|
-
|
199
|
+
const { chainId, address, blockTag } = params[0].context!
|
200
|
+
console.log(`chain: ${chainId}, address: ${address}, blockTag: ${blockTag}, totalCalls: ${params.length}`)
|
201
|
+
// TODO multicall
|
189
202
|
for (const param of params) {
|
190
|
-
const frag = new Interface(param.signature)
|
191
|
-
const calldata = frag.encodeFunctionData(param.function, param.args)
|
192
203
|
callPromises.push(
|
193
204
|
providers
|
194
|
-
.get(
|
205
|
+
.get(chainId)!
|
195
206
|
.call({
|
196
|
-
to:
|
197
|
-
data: calldata
|
207
|
+
to: address,
|
208
|
+
data: param.calldata,
|
209
|
+
blockTag
|
198
210
|
})
|
199
|
-
.then((
|
211
|
+
.then((result) => [makeEthCallKey(param), result])
|
200
212
|
)
|
201
213
|
}
|
202
214
|
}
|
203
|
-
|
215
|
+
let results = {}
|
216
|
+
try {
|
217
|
+
results = Object.fromEntries(await Promise.all(callPromises))
|
218
|
+
} catch (e) {
|
219
|
+
console.error(`eth call error: ${e}`)
|
220
|
+
}
|
204
221
|
console.log(`${callPromises.length} calls finished, elapsed: ${Date.now() - start}ms`)
|
205
222
|
return results
|
206
223
|
}
|
207
224
|
|
208
|
-
async preprocessBinding(
|
225
|
+
async preprocessBinding(
|
226
|
+
request: DataBinding,
|
227
|
+
dbContext?: StoreContext,
|
228
|
+
options?: CallContext
|
229
|
+
): Promise<PreprocessResult> {
|
209
230
|
if (!this.started) {
|
210
231
|
throw new ServerError(Status.UNAVAILABLE, 'Service Not started.')
|
211
232
|
}
|
@@ -221,7 +242,7 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
221
242
|
]
|
222
243
|
)
|
223
244
|
}
|
224
|
-
return await PluginManager.INSTANCE.preprocessBinding(request)
|
245
|
+
return await PluginManager.INSTANCE.preprocessBinding(request, dbContext)
|
225
246
|
}
|
226
247
|
|
227
248
|
async processBinding(
|
@@ -266,6 +287,63 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
266
287
|
yield* from(subject).pipe(withAbort(context.signal))
|
267
288
|
}
|
268
289
|
|
290
|
+
async handlePreprocessRequests(
|
291
|
+
requests: AsyncIterable<PreprocessStreamRequest>,
|
292
|
+
subject: Subject<DeepPartial<PreprocessStreamResponse>>
|
293
|
+
) {
|
294
|
+
const contexts = new Contexts()
|
295
|
+
|
296
|
+
for await (const request of requests) {
|
297
|
+
try {
|
298
|
+
console.debug('received request:', request)
|
299
|
+
if (request.bindings) {
|
300
|
+
const bindings = request.bindings.bindings
|
301
|
+
const dbContext = contexts.new(request.processId, subject)
|
302
|
+
const start = Date.now()
|
303
|
+
this.preprocessBindings(bindings, dbContext)
|
304
|
+
.then(() => {
|
305
|
+
subject.next({
|
306
|
+
processId: request.processId
|
307
|
+
})
|
308
|
+
})
|
309
|
+
.catch((e) => {
|
310
|
+
console.debug(e)
|
311
|
+
dbContext.error(request.processId, e)
|
312
|
+
})
|
313
|
+
.finally(() => {
|
314
|
+
const cost = Date.now() - start
|
315
|
+
console.debug('preprocessBinding', request.processId, ' took', cost, 'ms')
|
316
|
+
contexts.delete(request.processId)
|
317
|
+
})
|
318
|
+
}
|
319
|
+
if (request.dbResult) {
|
320
|
+
const dbContext = contexts.get(request.processId)
|
321
|
+
dbContext?.result(request.dbResult)
|
322
|
+
}
|
323
|
+
} catch (e) {
|
324
|
+
// should not happen
|
325
|
+
console.error('unexpect error during handle loop', e)
|
326
|
+
}
|
327
|
+
}
|
328
|
+
}
|
329
|
+
|
330
|
+
async *preprocessBindingsStream(requests: AsyncIterable<PreprocessStreamRequest>, context: CallContext) {
|
331
|
+
if (!this.started) {
|
332
|
+
throw new ServerError(Status.UNAVAILABLE, 'Service Not started.')
|
333
|
+
}
|
334
|
+
|
335
|
+
const subject = new Subject<DeepPartial<PreprocessStreamResponse>>()
|
336
|
+
this.handlePreprocessRequests(requests, subject)
|
337
|
+
.then(() => {
|
338
|
+
subject.complete()
|
339
|
+
})
|
340
|
+
.catch((e) => {
|
341
|
+
console.error(e)
|
342
|
+
subject.error(e)
|
343
|
+
})
|
344
|
+
yield* from(subject).pipe(withAbort(context.signal))
|
345
|
+
}
|
346
|
+
|
269
347
|
private async handleRequests(
|
270
348
|
requests: AsyncIterable<ProcessStreamRequest>,
|
271
349
|
subject: Subject<DeepPartial<ProcessStreamResponse>>
|
package/src/utils.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { ProcessResult } from '@sentio/protos'
|
1
|
+
import { EthCallParam, ProcessResult } from '@sentio/protos'
|
2
2
|
|
3
3
|
// TODO better handling this, because old proto doesn't have this
|
4
4
|
import { StateResult, ProcessResult as ProcessResultFull } from './gen/processor/protos/processor.js'
|
@@ -8,7 +8,7 @@ import { Required } from 'utility-types'
|
|
8
8
|
export function mergeProcessResults(results: ProcessResult[]): Required<ProcessResult, 'states'> {
|
9
9
|
const res = {
|
10
10
|
...ProcessResultFull.create(),
|
11
|
-
states: StateResult.create()
|
11
|
+
states: StateResult.create()
|
12
12
|
}
|
13
13
|
|
14
14
|
for (const r of results) {
|
@@ -17,7 +17,7 @@ export function mergeProcessResults(results: ProcessResult[]): Required<ProcessR
|
|
17
17
|
res.events = res.events.concat(r.events)
|
18
18
|
res.exports = res.exports.concat(r.exports)
|
19
19
|
res.states = {
|
20
|
-
configUpdated: res.states?.configUpdated || r.states?.configUpdated || false
|
20
|
+
configUpdated: res.states?.configUpdated || r.states?.configUpdated || false
|
21
21
|
}
|
22
22
|
}
|
23
23
|
return res
|
@@ -28,3 +28,11 @@ export function errorString(e: Error): string {
|
|
28
28
|
}
|
29
29
|
|
30
30
|
export const USER_PROCESSOR = 'user_processor'
|
31
|
+
|
32
|
+
export function makeEthCallKey(param: EthCallParam) {
|
33
|
+
if (!param.context) {
|
34
|
+
throw new Error('null context for eth call')
|
35
|
+
}
|
36
|
+
const { chainId, address, blockTag } = param.context
|
37
|
+
return `${chainId}|${address}|${blockTag}|${param.calldata}`
|
38
|
+
}
|