@sentio/runtime 2.59.4 → 2.60.0-rc.1
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-6XHWJ2VS.js +92 -0
- package/lib/{chunk-WHWNPZZ3.js.map → chunk-6XHWJ2VS.js.map} +1 -1
- package/lib/chunk-7JPTCCHQ.js +59933 -0
- package/lib/{chunk-PEHR2WT4.js.map → chunk-7JPTCCHQ.js.map} +1 -1
- package/lib/chunk-AQYRWO7H.js +23993 -0
- package/lib/chunk-AQYRWO7H.js.map +1 -0
- package/lib/chunk-RJMWLF3Q.js +10975 -0
- package/lib/{chunk-JPHAFAK7.js.map → chunk-RJMWLF3Q.js.map} +1 -1
- package/lib/index.d.ts +22 -4
- package/lib/index.js +74 -1
- package/lib/index.js.map +1 -1
- package/lib/processor-runner.js +26614 -21
- package/lib/processor-runner.js.map +1 -1
- package/lib/service-worker.js +130 -2
- package/lib/service-worker.js.map +1 -1
- package/lib/test-processor.test.js.map +1 -1
- package/package.json +1 -1
- package/src/db-context.ts +43 -1
- package/src/gen/processor/protos/processor.ts +506 -0
- package/src/gen/service/common/protos/common.ts +195 -0
- package/src/plugin.ts +14 -3
- package/src/service-v2.ts +207 -0
- package/lib/chunk-JPHAFAK7.js +0 -38
- package/lib/chunk-PEHR2WT4.js +0 -117
- package/lib/chunk-VUN3TGG5.js +0 -26
- package/lib/chunk-VUN3TGG5.js.map +0 -1
- package/lib/chunk-WHWNPZZ3.js +0 -3
@@ -313,6 +313,17 @@ export interface UsageTracker {
|
|
313
313
|
versionField: string;
|
314
314
|
}
|
315
315
|
|
316
|
+
export interface Auth {
|
317
|
+
permission: string[];
|
318
|
+
metadata: { [key: string]: string };
|
319
|
+
allowAnonymous: boolean;
|
320
|
+
}
|
321
|
+
|
322
|
+
export interface Auth_MetadataEntry {
|
323
|
+
key: string;
|
324
|
+
value: string;
|
325
|
+
}
|
326
|
+
|
316
327
|
export interface AccessMeta {
|
317
328
|
projectIdField: string;
|
318
329
|
projectSlugField: string;
|
@@ -2183,6 +2194,190 @@ export const UsageTracker = {
|
|
2183
2194
|
},
|
2184
2195
|
};
|
2185
2196
|
|
2197
|
+
function createBaseAuth(): Auth {
|
2198
|
+
return { permission: [], metadata: {}, allowAnonymous: false };
|
2199
|
+
}
|
2200
|
+
|
2201
|
+
export const Auth = {
|
2202
|
+
encode(message: Auth, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
2203
|
+
for (const v of message.permission) {
|
2204
|
+
writer.uint32(10).string(v!);
|
2205
|
+
}
|
2206
|
+
Object.entries(message.metadata).forEach(([key, value]) => {
|
2207
|
+
Auth_MetadataEntry.encode({ key: key as any, value }, writer.uint32(18).fork()).ldelim();
|
2208
|
+
});
|
2209
|
+
if (message.allowAnonymous !== false) {
|
2210
|
+
writer.uint32(24).bool(message.allowAnonymous);
|
2211
|
+
}
|
2212
|
+
return writer;
|
2213
|
+
},
|
2214
|
+
|
2215
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): Auth {
|
2216
|
+
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
2217
|
+
let end = length === undefined ? reader.len : reader.pos + length;
|
2218
|
+
const message = createBaseAuth();
|
2219
|
+
while (reader.pos < end) {
|
2220
|
+
const tag = reader.uint32();
|
2221
|
+
switch (tag >>> 3) {
|
2222
|
+
case 1:
|
2223
|
+
if (tag !== 10) {
|
2224
|
+
break;
|
2225
|
+
}
|
2226
|
+
|
2227
|
+
message.permission.push(reader.string());
|
2228
|
+
continue;
|
2229
|
+
case 2:
|
2230
|
+
if (tag !== 18) {
|
2231
|
+
break;
|
2232
|
+
}
|
2233
|
+
|
2234
|
+
const entry2 = Auth_MetadataEntry.decode(reader, reader.uint32());
|
2235
|
+
if (entry2.value !== undefined) {
|
2236
|
+
message.metadata[entry2.key] = entry2.value;
|
2237
|
+
}
|
2238
|
+
continue;
|
2239
|
+
case 3:
|
2240
|
+
if (tag !== 24) {
|
2241
|
+
break;
|
2242
|
+
}
|
2243
|
+
|
2244
|
+
message.allowAnonymous = reader.bool();
|
2245
|
+
continue;
|
2246
|
+
}
|
2247
|
+
if ((tag & 7) === 4 || tag === 0) {
|
2248
|
+
break;
|
2249
|
+
}
|
2250
|
+
reader.skipType(tag & 7);
|
2251
|
+
}
|
2252
|
+
return message;
|
2253
|
+
},
|
2254
|
+
|
2255
|
+
fromJSON(object: any): Auth {
|
2256
|
+
return {
|
2257
|
+
permission: globalThis.Array.isArray(object?.permission)
|
2258
|
+
? object.permission.map((e: any) => globalThis.String(e))
|
2259
|
+
: [],
|
2260
|
+
metadata: isObject(object.metadata)
|
2261
|
+
? Object.entries(object.metadata).reduce<{ [key: string]: string }>((acc, [key, value]) => {
|
2262
|
+
acc[key] = String(value);
|
2263
|
+
return acc;
|
2264
|
+
}, {})
|
2265
|
+
: {},
|
2266
|
+
allowAnonymous: isSet(object.allowAnonymous) ? globalThis.Boolean(object.allowAnonymous) : false,
|
2267
|
+
};
|
2268
|
+
},
|
2269
|
+
|
2270
|
+
toJSON(message: Auth): unknown {
|
2271
|
+
const obj: any = {};
|
2272
|
+
if (message.permission?.length) {
|
2273
|
+
obj.permission = message.permission;
|
2274
|
+
}
|
2275
|
+
if (message.metadata) {
|
2276
|
+
const entries = Object.entries(message.metadata);
|
2277
|
+
if (entries.length > 0) {
|
2278
|
+
obj.metadata = {};
|
2279
|
+
entries.forEach(([k, v]) => {
|
2280
|
+
obj.metadata[k] = v;
|
2281
|
+
});
|
2282
|
+
}
|
2283
|
+
}
|
2284
|
+
if (message.allowAnonymous !== false) {
|
2285
|
+
obj.allowAnonymous = message.allowAnonymous;
|
2286
|
+
}
|
2287
|
+
return obj;
|
2288
|
+
},
|
2289
|
+
|
2290
|
+
create(base?: DeepPartial<Auth>): Auth {
|
2291
|
+
return Auth.fromPartial(base ?? {});
|
2292
|
+
},
|
2293
|
+
fromPartial(object: DeepPartial<Auth>): Auth {
|
2294
|
+
const message = createBaseAuth();
|
2295
|
+
message.permission = object.permission?.map((e) => e) || [];
|
2296
|
+
message.metadata = Object.entries(object.metadata ?? {}).reduce<{ [key: string]: string }>((acc, [key, value]) => {
|
2297
|
+
if (value !== undefined) {
|
2298
|
+
acc[key] = globalThis.String(value);
|
2299
|
+
}
|
2300
|
+
return acc;
|
2301
|
+
}, {});
|
2302
|
+
message.allowAnonymous = object.allowAnonymous ?? false;
|
2303
|
+
return message;
|
2304
|
+
},
|
2305
|
+
};
|
2306
|
+
|
2307
|
+
function createBaseAuth_MetadataEntry(): Auth_MetadataEntry {
|
2308
|
+
return { key: "", value: "" };
|
2309
|
+
}
|
2310
|
+
|
2311
|
+
export const Auth_MetadataEntry = {
|
2312
|
+
encode(message: Auth_MetadataEntry, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
2313
|
+
if (message.key !== "") {
|
2314
|
+
writer.uint32(10).string(message.key);
|
2315
|
+
}
|
2316
|
+
if (message.value !== "") {
|
2317
|
+
writer.uint32(18).string(message.value);
|
2318
|
+
}
|
2319
|
+
return writer;
|
2320
|
+
},
|
2321
|
+
|
2322
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): Auth_MetadataEntry {
|
2323
|
+
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
2324
|
+
let end = length === undefined ? reader.len : reader.pos + length;
|
2325
|
+
const message = createBaseAuth_MetadataEntry();
|
2326
|
+
while (reader.pos < end) {
|
2327
|
+
const tag = reader.uint32();
|
2328
|
+
switch (tag >>> 3) {
|
2329
|
+
case 1:
|
2330
|
+
if (tag !== 10) {
|
2331
|
+
break;
|
2332
|
+
}
|
2333
|
+
|
2334
|
+
message.key = reader.string();
|
2335
|
+
continue;
|
2336
|
+
case 2:
|
2337
|
+
if (tag !== 18) {
|
2338
|
+
break;
|
2339
|
+
}
|
2340
|
+
|
2341
|
+
message.value = reader.string();
|
2342
|
+
continue;
|
2343
|
+
}
|
2344
|
+
if ((tag & 7) === 4 || tag === 0) {
|
2345
|
+
break;
|
2346
|
+
}
|
2347
|
+
reader.skipType(tag & 7);
|
2348
|
+
}
|
2349
|
+
return message;
|
2350
|
+
},
|
2351
|
+
|
2352
|
+
fromJSON(object: any): Auth_MetadataEntry {
|
2353
|
+
return {
|
2354
|
+
key: isSet(object.key) ? globalThis.String(object.key) : "",
|
2355
|
+
value: isSet(object.value) ? globalThis.String(object.value) : "",
|
2356
|
+
};
|
2357
|
+
},
|
2358
|
+
|
2359
|
+
toJSON(message: Auth_MetadataEntry): unknown {
|
2360
|
+
const obj: any = {};
|
2361
|
+
if (message.key !== "") {
|
2362
|
+
obj.key = message.key;
|
2363
|
+
}
|
2364
|
+
if (message.value !== "") {
|
2365
|
+
obj.value = message.value;
|
2366
|
+
}
|
2367
|
+
return obj;
|
2368
|
+
},
|
2369
|
+
|
2370
|
+
create(base?: DeepPartial<Auth_MetadataEntry>): Auth_MetadataEntry {
|
2371
|
+
return Auth_MetadataEntry.fromPartial(base ?? {});
|
2372
|
+
},
|
2373
|
+
fromPartial(object: DeepPartial<Auth_MetadataEntry>): Auth_MetadataEntry {
|
2374
|
+
const message = createBaseAuth_MetadataEntry();
|
2375
|
+
message.key = object.key ?? "";
|
2376
|
+
message.value = object.value ?? "";
|
2377
|
+
return message;
|
2378
|
+
},
|
2379
|
+
};
|
2380
|
+
|
2186
2381
|
function createBaseAccessMeta(): AccessMeta {
|
2187
2382
|
return {
|
2188
2383
|
projectIdField: "",
|
package/src/plugin.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import {
|
2
2
|
DataBinding,
|
3
3
|
HandlerType,
|
4
|
+
InitResponse,
|
4
5
|
PreparedData,
|
5
6
|
PreprocessResult,
|
6
7
|
ProcessConfigResponse,
|
@@ -16,7 +17,7 @@ export abstract class Plugin {
|
|
16
17
|
name: string
|
17
18
|
supportedHandlers: HandlerType[] = []
|
18
19
|
|
19
|
-
async configure(config: ProcessConfigResponse): Promise<void> {}
|
20
|
+
async configure(config: ProcessConfigResponse, forChainId?: string): Promise<void> {}
|
20
21
|
|
21
22
|
async start(start: StartRequest): Promise<void> {}
|
22
23
|
|
@@ -59,6 +60,12 @@ export abstract class Plugin {
|
|
59
60
|
* method used by action server only
|
60
61
|
*/
|
61
62
|
shutdownServer() {}
|
63
|
+
|
64
|
+
/**
|
65
|
+
* Initialize the plugin, for service v2.
|
66
|
+
* @param config
|
67
|
+
*/
|
68
|
+
async init(config: InitResponse): Promise<void> {}
|
62
69
|
}
|
63
70
|
|
64
71
|
export class PluginManager {
|
@@ -83,8 +90,8 @@ export class PluginManager {
|
|
83
90
|
}
|
84
91
|
}
|
85
92
|
|
86
|
-
configure(config: ProcessConfigResponse) {
|
87
|
-
|
93
|
+
async configure(config: ProcessConfigResponse, forChainId?: string): Promise<void> {
|
94
|
+
await Promise.all(this.plugins.map((plugin) => plugin.configure(config, forChainId)))
|
88
95
|
}
|
89
96
|
|
90
97
|
start(start: StartRequest, actionServerPort?: number) {
|
@@ -141,4 +148,8 @@ export class PluginManager {
|
|
141
148
|
return plugin.preprocessBinding(request, preprocessStore)
|
142
149
|
})
|
143
150
|
}
|
151
|
+
|
152
|
+
async init(resp: InitResponse) {
|
153
|
+
return Promise.all(this.plugins.map((plugin) => plugin.init(resp)))
|
154
|
+
}
|
144
155
|
}
|
@@ -0,0 +1,207 @@
|
|
1
|
+
import {
|
2
|
+
ConfigureHandlersRequest,
|
3
|
+
DataBinding,
|
4
|
+
DeepPartial,
|
5
|
+
Empty,
|
6
|
+
HandlerType,
|
7
|
+
InitResponse,
|
8
|
+
ProcessConfigResponse,
|
9
|
+
ProcessorV2ServiceImplementation,
|
10
|
+
ProcessResult,
|
11
|
+
ProcessStreamRequest,
|
12
|
+
ProcessStreamResponseV2,
|
13
|
+
StartRequest
|
14
|
+
} from '@sentio/protos'
|
15
|
+
import { CallContext } from 'nice-grpc'
|
16
|
+
import { AsyncIterable } from 'ix'
|
17
|
+
import { PluginManager } from './plugin.js'
|
18
|
+
import { Subject } from 'rxjs'
|
19
|
+
import { from } from 'ix/asynciterable'
|
20
|
+
import { withAbort } from 'ix/asynciterable/operators'
|
21
|
+
import { errorString } from './utils.js'
|
22
|
+
|
23
|
+
import { processMetrics } from './metrics.js'
|
24
|
+
import { recordRuntimeInfo } from './service.js'
|
25
|
+
import { DataBindingContext } from './db-context.js'
|
26
|
+
import { TemplateInstanceState } from './state.js'
|
27
|
+
|
28
|
+
const { process_binding_count, process_binding_time, process_binding_error } = processMetrics
|
29
|
+
|
30
|
+
export class ProcessorServiceImplV2 implements ProcessorV2ServiceImplementation {
|
31
|
+
readonly enablePartition: boolean
|
32
|
+
private readonly loader: () => Promise<any>
|
33
|
+
private readonly shutdownHandler?: () => void
|
34
|
+
|
35
|
+
constructor(loader: () => Promise<any>, options?: any, shutdownHandler?: () => void) {
|
36
|
+
this.loader = loader
|
37
|
+
this.shutdownHandler = shutdownHandler
|
38
|
+
|
39
|
+
this.enablePartition = options?.['enable-partition'] == true
|
40
|
+
}
|
41
|
+
|
42
|
+
async init(request: Empty, context: CallContext): Promise<DeepPartial<InitResponse>> {
|
43
|
+
const resp = InitResponse.fromPartial({
|
44
|
+
chainIds: []
|
45
|
+
})
|
46
|
+
await PluginManager.INSTANCE.init(resp)
|
47
|
+
resp.chainIds = Array.from(new Set(resp.chainIds))
|
48
|
+
return resp
|
49
|
+
}
|
50
|
+
|
51
|
+
async *processBindingsStream(requests: AsyncIterable<ProcessStreamRequest>, context: CallContext) {
|
52
|
+
const subject = new Subject<DeepPartial<ProcessStreamResponseV2>>()
|
53
|
+
let lastBinding: DataBinding | undefined = undefined
|
54
|
+
for await (const request of requests) {
|
55
|
+
try {
|
56
|
+
// console.log('received request:', request, 'lastBinding:', lastBinding)
|
57
|
+
if (request.binding) {
|
58
|
+
lastBinding = request.binding
|
59
|
+
}
|
60
|
+
this.handleRequest(request, lastBinding, subject)
|
61
|
+
} catch (e) {
|
62
|
+
// should not happen
|
63
|
+
console.error('unexpect error during handle loop', e)
|
64
|
+
}
|
65
|
+
}
|
66
|
+
yield* from(subject).pipe(withAbort(context.signal))
|
67
|
+
}
|
68
|
+
private contexts = new Contexts()
|
69
|
+
|
70
|
+
async handleRequest(
|
71
|
+
request: ProcessStreamRequest,
|
72
|
+
lastBinding: DataBinding | undefined,
|
73
|
+
subject: Subject<DeepPartial<ProcessStreamResponseV2>>
|
74
|
+
) {
|
75
|
+
if (request.binding) {
|
76
|
+
process_binding_count.add(1)
|
77
|
+
|
78
|
+
if (request.binding.handlerType === HandlerType.UNKNOWN) {
|
79
|
+
subject.next({
|
80
|
+
processId: request.processId,
|
81
|
+
result: ProcessResult.create()
|
82
|
+
})
|
83
|
+
return
|
84
|
+
}
|
85
|
+
|
86
|
+
if (this.enablePartition) {
|
87
|
+
try {
|
88
|
+
const partitions = await PluginManager.INSTANCE.partition(request.binding)
|
89
|
+
subject.next({
|
90
|
+
processId: request.processId,
|
91
|
+
partitions
|
92
|
+
})
|
93
|
+
} catch (e) {
|
94
|
+
console.error('Partition error:', e)
|
95
|
+
subject.error(new Error('Partition error: ' + errorString(e)))
|
96
|
+
return
|
97
|
+
}
|
98
|
+
} else {
|
99
|
+
this.startProcess(request.processId, request.binding, subject)
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
if (request.start) {
|
104
|
+
if (!lastBinding) {
|
105
|
+
console.error('start request received without binding')
|
106
|
+
subject.error(new Error('start request received without binding'))
|
107
|
+
return
|
108
|
+
}
|
109
|
+
this.startProcess(request.processId, lastBinding, subject)
|
110
|
+
}
|
111
|
+
|
112
|
+
if (request.dbResult) {
|
113
|
+
const context = this.contexts.get(request.processId)
|
114
|
+
try {
|
115
|
+
context?.result(request.dbResult)
|
116
|
+
} catch (e) {
|
117
|
+
subject.error(new Error('db result error, process should stop'))
|
118
|
+
}
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
private startProcess(
|
123
|
+
processId: number,
|
124
|
+
binding: DataBinding,
|
125
|
+
subject: Subject<DeepPartial<ProcessStreamResponseV2>>
|
126
|
+
) {
|
127
|
+
const context = this.contexts.new(processId, subject)
|
128
|
+
const start = Date.now()
|
129
|
+
PluginManager.INSTANCE.processBinding(binding, undefined, context)
|
130
|
+
.then(async (result) => {
|
131
|
+
// await all pending db requests
|
132
|
+
await context.awaitPendings()
|
133
|
+
|
134
|
+
for (const ts of result.timeseriesResult) {
|
135
|
+
subject.next({
|
136
|
+
processId,
|
137
|
+
tsRequest: {
|
138
|
+
data: [ts]
|
139
|
+
}
|
140
|
+
})
|
141
|
+
}
|
142
|
+
|
143
|
+
if (result.states?.configUpdated) {
|
144
|
+
subject.next({
|
145
|
+
processId,
|
146
|
+
tplRequest: {
|
147
|
+
templates: TemplateInstanceState.INSTANCE.getValues()
|
148
|
+
}
|
149
|
+
})
|
150
|
+
}
|
151
|
+
|
152
|
+
subject.next({
|
153
|
+
result: {
|
154
|
+
states: result.states,
|
155
|
+
exports: result.exports
|
156
|
+
},
|
157
|
+
processId: processId
|
158
|
+
})
|
159
|
+
recordRuntimeInfo(result, binding.handlerType)
|
160
|
+
})
|
161
|
+
.catch((e) => {
|
162
|
+
console.error(e, e.stack)
|
163
|
+
context.error(processId, e)
|
164
|
+
process_binding_error.add(1)
|
165
|
+
})
|
166
|
+
.finally(() => {
|
167
|
+
const cost = Date.now() - start
|
168
|
+
process_binding_time.add(cost)
|
169
|
+
this.contexts.delete(processId)
|
170
|
+
})
|
171
|
+
}
|
172
|
+
|
173
|
+
async configureHandlers(
|
174
|
+
request: ConfigureHandlersRequest,
|
175
|
+
context: CallContext
|
176
|
+
): Promise<DeepPartial<ProcessConfigResponse>> {
|
177
|
+
await PluginManager.INSTANCE.start(
|
178
|
+
StartRequest.fromPartial({
|
179
|
+
templateInstances: request.templateInstances
|
180
|
+
})
|
181
|
+
)
|
182
|
+
|
183
|
+
const newConfig = ProcessConfigResponse.fromPartial({})
|
184
|
+
await PluginManager.INSTANCE.configure(newConfig, request.chainId)
|
185
|
+
return newConfig
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
class Contexts {
|
190
|
+
private contexts: Map<number, DataBindingContext> = new Map()
|
191
|
+
|
192
|
+
get(processId: number) {
|
193
|
+
return this.contexts.get(processId)
|
194
|
+
}
|
195
|
+
|
196
|
+
new(processId: number, subject: Subject<DeepPartial<ProcessStreamResponseV2>>) {
|
197
|
+
const context = new DataBindingContext(processId, subject)
|
198
|
+
this.contexts.set(processId, context)
|
199
|
+
return context
|
200
|
+
}
|
201
|
+
|
202
|
+
delete(processId: number) {
|
203
|
+
const context = this.get(processId)
|
204
|
+
context?.close()
|
205
|
+
this.contexts.delete(processId)
|
206
|
+
}
|
207
|
+
}
|