@sentio/runtime 2.39.7-rc.9 → 2.40.0-rc.2

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.
Files changed (97) hide show
  1. package/lib/chunk-WDKQZPD5.js +78804 -0
  2. package/lib/index.d.ts +369 -9
  3. package/lib/index.js +92 -9
  4. package/lib/processor-runner.d.ts +0 -2
  5. package/lib/processor-runner.js +51460 -129
  6. package/package.json +5 -25
  7. package/src/db-context.ts +157 -7
  8. package/src/full-service.ts +5 -0
  9. package/src/gen/processor/protos/processor.ts +995 -90
  10. package/src/plugin.ts +30 -4
  11. package/src/processor-runner.ts +26 -2
  12. package/src/provider.ts +166 -0
  13. package/src/service.ts +197 -27
  14. package/src/tsup.config.ts +14 -0
  15. package/lib/chain-config.d.ts +0 -6
  16. package/lib/chain-config.d.ts.map +0 -1
  17. package/lib/chain-config.js +0 -2
  18. package/lib/chain-config.js.map +0 -1
  19. package/lib/db-context.d.ts +0 -17
  20. package/lib/db-context.d.ts.map +0 -1
  21. package/lib/db-context.js +0 -63
  22. package/lib/db-context.js.map +0 -1
  23. package/lib/decode-benchmark.d.ts +0 -3
  24. package/lib/decode-benchmark.d.ts.map +0 -1
  25. package/lib/decode-benchmark.js +0 -20
  26. package/lib/decode-benchmark.js.map +0 -1
  27. package/lib/endpoints.d.ts +0 -9
  28. package/lib/endpoints.d.ts.map +0 -1
  29. package/lib/endpoints.js +0 -9
  30. package/lib/endpoints.js.map +0 -1
  31. package/lib/full-service.d.ts +0 -655
  32. package/lib/full-service.d.ts.map +0 -1
  33. package/lib/full-service.js +0 -137
  34. package/lib/full-service.js.map +0 -1
  35. package/lib/gen/google/protobuf/empty.d.ts +0 -17
  36. package/lib/gen/google/protobuf/empty.d.ts.map +0 -1
  37. package/lib/gen/google/protobuf/empty.js +0 -40
  38. package/lib/gen/google/protobuf/empty.js.map +0 -1
  39. package/lib/gen/google/protobuf/struct.d.ts +0 -77
  40. package/lib/gen/google/protobuf/struct.d.ts.map +0 -1
  41. package/lib/gen/google/protobuf/struct.js +0 -429
  42. package/lib/gen/google/protobuf/struct.js.map +0 -1
  43. package/lib/gen/google/protobuf/timestamp.d.ts +0 -19
  44. package/lib/gen/google/protobuf/timestamp.d.ts.map +0 -1
  45. package/lib/gen/google/protobuf/timestamp.js +0 -83
  46. package/lib/gen/google/protobuf/timestamp.js.map +0 -1
  47. package/lib/gen/processor/protos/processor.d.ts +0 -1470
  48. package/lib/gen/processor/protos/processor.d.ts.map +0 -1
  49. package/lib/gen/processor/protos/processor.js +0 -8512
  50. package/lib/gen/processor/protos/processor.js.map +0 -1
  51. package/lib/gen/service/common/protos/common.d.ts +0 -1698
  52. package/lib/gen/service/common/protos/common.d.ts.map +0 -1
  53. package/lib/gen/service/common/protos/common.js +0 -11383
  54. package/lib/gen/service/common/protos/common.js.map +0 -1
  55. package/lib/global-config.d.ts +0 -8
  56. package/lib/global-config.d.ts.map +0 -1
  57. package/lib/global-config.js +0 -23
  58. package/lib/global-config.js.map +0 -1
  59. package/lib/global-config.test.d.ts +0 -2
  60. package/lib/global-config.test.d.ts.map +0 -1
  61. package/lib/global-config.test.js.map +0 -1
  62. package/lib/index.d.ts.map +0 -1
  63. package/lib/index.js.map +0 -1
  64. package/lib/logger.d.ts +0 -2
  65. package/lib/logger.d.ts.map +0 -1
  66. package/lib/logger.js +0 -39
  67. package/lib/logger.js.map +0 -1
  68. package/lib/logger.test.d.ts +0 -2
  69. package/lib/logger.test.d.ts.map +0 -1
  70. package/lib/logger.test.js.map +0 -1
  71. package/lib/plugin.d.ts +0 -29
  72. package/lib/plugin.d.ts.map +0 -1
  73. package/lib/plugin.js +0 -58
  74. package/lib/plugin.js.map +0 -1
  75. package/lib/processor-runner.d.ts.map +0 -1
  76. package/lib/processor-runner.js.map +0 -1
  77. package/lib/seq-mode.test.d.ts +0 -3
  78. package/lib/seq-mode.test.d.ts.map +0 -1
  79. package/lib/seq-mode.test.js.map +0 -1
  80. package/lib/service.d.ts +0 -179
  81. package/lib/service.d.ts.map +0 -1
  82. package/lib/service.js +0 -194
  83. package/lib/service.js.map +0 -1
  84. package/lib/service.test.d.ts +0 -3
  85. package/lib/service.test.d.ts.map +0 -1
  86. package/lib/service.test.js.map +0 -1
  87. package/lib/state-storage.test.d.ts +0 -2
  88. package/lib/state-storage.test.d.ts.map +0 -1
  89. package/lib/state-storage.test.js.map +0 -1
  90. package/lib/state.d.ts +0 -23
  91. package/lib/state.d.ts.map +0 -1
  92. package/lib/state.js +0 -61
  93. package/lib/state.js.map +0 -1
  94. package/lib/utils.d.ts +0 -6
  95. package/lib/utils.d.ts.map +0 -1
  96. package/lib/utils.js +0 -23
  97. package/lib/utils.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentio/runtime",
3
- "version": "2.39.7-rc.9",
3
+ "version": "2.40.0-rc.2",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -14,46 +14,26 @@
14
14
  "!**/*.test.{js,ts}",
15
15
  "!{lib,src}/tests"
16
16
  ],
17
- "dependencies": {
18
- "@grpc/grpc-js": "^1.9.14",
19
- "command-line-args": "^5.2.1",
20
- "command-line-usage": "^7.0.1",
21
- "fs-extra": "^11.2.0",
22
- "google-protobuf": "^3.21.2",
23
- "ix": "^5.0.0",
24
- "long": "^5.2.3",
25
- "nice-grpc": "^2.1.7",
26
- "nice-grpc-client-middleware-retry": "^3.1.6",
27
- "nice-grpc-common": "^2.0.2",
28
- "nice-grpc-error-details": "^0.2.4",
29
- "nice-grpc-prometheus": "^0.2.2",
30
- "prom-client": "^14.2.0",
31
- "protobufjs": "^7.2.6",
32
- "rxjs": "^7.8.1",
33
- "utility-types": "^3.11.0",
34
- "winston": "^3.11.0",
35
- "@sentio/protos": "2.39.7-rc.9"
36
- },
17
+ "dependencies": {},
37
18
  "devDependencies": {
38
19
  "@types/command-line-args": "^5.2.3",
39
20
  "@types/command-line-usage": "^5.0.4",
40
21
  "@types/fs-extra": "^11.0.4",
41
22
  "@types/google-protobuf": "^3.15.12",
42
- "jest": "^29.7.0",
43
- "ts-node": "^10.9.2",
44
23
  "tslib": "^2.6.2"
45
24
  },
46
25
  "engines": {
47
26
  "node": ">=16"
48
27
  },
49
28
  "scripts": {
50
- "build": "pnpm compile",
29
+ "build": "pnpm bundle",
51
30
  "build:all": "pnpm --filter=$(node -p \"require('./package.json').name\")... build",
31
+ "bundle": "tsup --config src/tsup.config.ts",
52
32
  "compile": "tsc",
53
33
  "run": "tsx src/processor-runner.ts --log-format=json",
54
34
  "run-benchmark": "tsx src/decode-benchmark.ts",
55
35
  "start_js": "tsx ./lib/processor-runner.js $PWD/../../debug/dist/lib.js",
56
36
  "start_ts": "tsx ./lib/processor-runner.js --log-format=json $PWD/../../debug/src/processor.ts",
57
- "test": "NODE_OPTIONS=--experimental-vm-modules pnpm jest"
37
+ "test": "glob -c 'tsx --test' '**/*.test.ts'"
58
38
  }
59
39
  }
package/src/db-context.ts CHANGED
@@ -1,28 +1,94 @@
1
1
  import { Subject } from 'rxjs'
2
- import { DBRequest, DBResponse, DeepPartial, ProcessResult, ProcessStreamResponse } from '@sentio/protos'
2
+ import {
3
+ DBRequest,
4
+ DBRequest_DBUpsert,
5
+ DBResponse,
6
+ DeepPartial,
7
+ ProcessResult,
8
+ ProcessStreamResponse
9
+ } from '@sentio/protos'
10
+ import * as process from 'node:process'
11
+ import { Attributes, Counter, metrics } from '@opentelemetry/api'
12
+
13
+ const STORE_BATCH_IDLE = process.env['STORE_BATCH_MAX_IDLE'] ? parseInt(process.env['STORE_BATCH_MAX_IDLE']) : 1
14
+ const STORE_BATCH_SIZE = process.env['STORE_BATCH_SIZE'] ? parseInt(process.env['STORE_BATCH_SIZE']) : 10
3
15
 
4
16
  type Request = Omit<DBRequest, 'opId'>
17
+ type RequestType = keyof Request
18
+
19
+ const meter = metrics.getMeter('processor_store')
20
+ const send_counts: Record<RequestType, Counter<Attributes>> = {
21
+ get: meter.createCounter('store_get_count'),
22
+ upsert: meter.createCounter('store_upsert_count'),
23
+ list: meter.createCounter('store_list_count'),
24
+ delete: meter.createCounter('store_delete_count')
25
+ }
26
+ const recv_counts: Record<RequestType, Counter<Attributes>> = {
27
+ get: meter.createCounter('store_get_count'),
28
+ upsert: meter.createCounter('store_upsert_count'),
29
+ list: meter.createCounter('store_list_count'),
30
+ delete: meter.createCounter('store_delete_count')
31
+ }
32
+ const request_times: Record<RequestType, Counter<Attributes>> = {
33
+ get: meter.createCounter('store_get_time'),
34
+ upsert: meter.createCounter('store_upsert_time'),
35
+ list: meter.createCounter('store_list_time'),
36
+ delete: meter.createCounter('store_delete_time')
37
+ }
38
+ const request_errors: Record<RequestType, Counter<Attributes>> = {
39
+ get: meter.createCounter('store_get_error'),
40
+ upsert: meter.createCounter('store_upsert_error'),
41
+ list: meter.createCounter('store_list_error'),
42
+ delete: meter.createCounter('store_delete_error')
43
+ }
44
+
45
+ const batched_total_count = meter.createCounter('batched_total_count')
46
+ const batched_request_count = meter.createCounter('batched_request_count')
47
+
48
+ const unsolved_requests = meter.createGauge('store_unsolved_requests')
49
+
50
+ export const timeoutError = Symbol()
5
51
 
6
52
  export class StoreContext {
7
53
  private static opCounter = 0n
8
54
 
9
- private defers = new Map<bigint, { resolve: (value: any) => void; reject: (reason?: any) => void }>()
55
+ private defers = new Map<
56
+ bigint,
57
+ { resolve: (value: any) => void; reject: (reason?: any) => void; requestType?: RequestType }
58
+ >()
59
+ private statsInterval: NodeJS.Timeout | undefined
10
60
 
11
61
  constructor(
12
62
  readonly subject: Subject<DeepPartial<ProcessStreamResponse>>,
13
63
  readonly processId: number
14
64
  ) {}
15
65
 
16
- newPromise<T>(opId: bigint) {
66
+ newPromise<T>(opId: bigint, requestType?: RequestType) {
17
67
  return new Promise<T>((resolve, reject) => {
18
- this.defers.set(opId, { resolve, reject })
68
+ this.defers.set(opId, { resolve, reject, requestType })
69
+ unsolved_requests.record(this.defers.size, { processId: this.processId })
19
70
  })
20
71
  }
21
72
 
22
- sendRequest(request: DeepPartial<Request>) {
73
+ sendRequest(request: DeepPartial<Request>, timeoutSecs?: number): Promise<DBResponse> {
74
+ if (STORE_BATCH_IDLE > 0 && STORE_BATCH_SIZE > 1 && request.upsert) {
75
+ // batch upsert if possible
76
+ return this.sendUpsertInBatch(request.upsert as DBRequest_DBUpsert)
77
+ }
78
+
79
+ const requestType = Object.keys(request)[0] as RequestType
23
80
  const opId = StoreContext.opCounter++
24
- const promise = this.newPromise(opId)
81
+ const promise = this.newPromise(opId, requestType)
82
+
83
+ const start = Date.now()
84
+ const promises = [promise]
25
85
  console.debug('sending db request ', opId, request)
86
+ let timer: NodeJS.Timeout | undefined
87
+ if (timeoutSecs) {
88
+ const timeoutPromise = new Promise((_r, rej) => (timer = setTimeout(rej, timeoutSecs * 1000, timeoutError)))
89
+ promises.push(timeoutPromise)
90
+ }
91
+
26
92
  this.subject.next({
27
93
  dbRequest: {
28
94
  ...request,
@@ -30,7 +96,27 @@ export class StoreContext {
30
96
  },
31
97
  processId: this.processId
32
98
  })
33
- return promise
99
+
100
+ send_counts[requestType]?.add(1)
101
+
102
+ return Promise.race(promises)
103
+ .then((result: DBResponse) => {
104
+ console.debug('db request', requestType, 'op', opId, ' took', Date.now() - start, 'ms')
105
+ request_times[requestType]?.add(Date.now() - start)
106
+ return result
107
+ })
108
+ .catch((e) => {
109
+ if (e === timeoutError) {
110
+ console.error('db request', requestType, 'op:', opId, ' timeout')
111
+ }
112
+ request_errors[requestType]?.add(1)
113
+ throw e
114
+ })
115
+ .finally(() => {
116
+ if (timer) {
117
+ clearTimeout(timer)
118
+ }
119
+ })
34
120
  }
35
121
 
36
122
  result(dbResult: DBResponse) {
@@ -38,6 +124,9 @@ export class StoreContext {
38
124
  const defer = this.defers.get(opId)
39
125
  console.debug('received db result ', opId, dbResult)
40
126
  if (defer) {
127
+ if (defer.requestType) {
128
+ recv_counts[defer.requestType]?.add(1)
129
+ }
41
130
  if (dbResult.error) {
42
131
  defer.reject(new Error(dbResult.error))
43
132
  } else {
@@ -45,6 +134,7 @@ export class StoreContext {
45
134
  }
46
135
  this.defers.delete(opId)
47
136
  }
137
+ unsolved_requests.record(this.defers.size, { processId: this.processId })
48
138
  }
49
139
 
50
140
  error(processId: number, e: any) {
@@ -66,5 +156,65 @@ export class StoreContext {
66
156
  defer.reject(new Error('context closed'))
67
157
  }
68
158
  this.defers.clear()
159
+ if (this.statsInterval) {
160
+ clearInterval(this.statsInterval)
161
+ }
162
+ }
163
+
164
+ upsertBatch:
165
+ | {
166
+ opId: bigint
167
+ request: DBRequest_DBUpsert
168
+ promise: Promise<DBResponse>
169
+ timer: NodeJS.Timeout
170
+ }
171
+ | undefined = undefined
172
+
173
+ private async sendUpsertInBatch(req: DBRequest_DBUpsert): Promise<DBResponse> {
174
+ if (this.upsertBatch) {
175
+ // merge the upserts
176
+ const { request, promise } = this.upsertBatch
177
+ request.entity = this.upsertBatch.request.entity.concat(req.entity)
178
+ request.entityData = this.upsertBatch.request.entityData.concat(req.entityData)
179
+ request.id = this.upsertBatch.request.id.concat(req.id)
180
+ if (request.entity.length >= STORE_BATCH_SIZE) {
181
+ this.sendBatch()
182
+ }
183
+ return promise
184
+ } else {
185
+ const opId = StoreContext.opCounter++
186
+ const promise = this.newPromise<DBResponse>(opId, 'upsert')
187
+ const timeout = setTimeout(() => {
188
+ this.sendBatch()
189
+ }, STORE_BATCH_IDLE)
190
+
191
+ this.upsertBatch = {
192
+ opId,
193
+ request: req,
194
+ promise,
195
+ timer: timeout
196
+ }
197
+
198
+ return promise
199
+ }
200
+ }
201
+
202
+ private sendBatch() {
203
+ if (this.upsertBatch) {
204
+ const { request, opId, timer } = this.upsertBatch
205
+ console.debug('sending batch upsert', opId, 'batch size', request?.entity.length)
206
+ clearTimeout(timer)
207
+ this.upsertBatch = undefined
208
+ this.subject.next({
209
+ dbRequest: {
210
+ upsert: request,
211
+ opId
212
+ },
213
+ processId: this.processId
214
+ })
215
+ send_counts['upsert']?.add(1)
216
+ batched_request_count.add(1)
217
+ batched_total_count.add(request.entity.length)
218
+ }
69
219
  }
70
220
  }
@@ -6,6 +6,7 @@ const require = createRequire(import.meta.url)
6
6
  import {
7
7
  DataBinding,
8
8
  HandlerType,
9
+ PreprocessStreamRequest,
9
10
  ProcessBindingsRequest,
10
11
  ProcessStreamRequest,
11
12
  ProcessConfigRequest,
@@ -111,6 +112,10 @@ export class FullProcessorServiceImpl implements ProcessorServiceImplementation
111
112
  yield* this.instance.processBindingsStream(requests, context)
112
113
  }
113
114
 
115
+ async *preprocessBindingsStream(requests: AsyncIterable<PreprocessStreamRequest>, context: CallContext) {
116
+ yield* this.instance.preprocessBindingsStream(requests, context)
117
+ }
118
+
114
119
  private adjustResult(res: ProcessResult): void {}
115
120
 
116
121
  private adjustDataBinding(dataBinding: DataBinding): void {