envio 2.17.1 → 2.18.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "v2.17.1",
3
+ "version": "v2.18.0",
4
4
  "description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
5
5
  "bin": "./bin.js",
6
6
  "types": "index.d.ts",
@@ -24,15 +24,15 @@
24
24
  },
25
25
  "homepage": "https://envio.dev",
26
26
  "optionalDependencies": {
27
- "envio-linux-x64": "v2.17.1",
28
- "envio-linux-arm64": "v2.17.1",
29
- "envio-darwin-x64": "v2.17.1",
30
- "envio-darwin-arm64": "v2.17.1"
27
+ "envio-linux-x64": "v2.18.0",
28
+ "envio-linux-arm64": "v2.18.0",
29
+ "envio-darwin-x64": "v2.18.0",
30
+ "envio-darwin-arm64": "v2.18.0"
31
31
  },
32
32
  "dependencies": {
33
33
  "@envio-dev/hypersync-client": "0.6.3",
34
34
  "rescript": "11.1.3",
35
- "rescript-schema": "9.1.0",
35
+ "rescript-schema": "9.3.0",
36
36
  "viem": "2.21.0"
37
37
  },
38
38
  "files": [
@@ -0,0 +1,316 @@
1
+ let loadEntitiesDurationCounter = PromClient.Counter.makeCounter({
2
+ "name": "load_entities_processing_time_spent",
3
+ "help": "Duration spend on loading entities",
4
+ "labelNames": [],
5
+ })
6
+
7
+ let eventRouterDurationCounter = PromClient.Counter.makeCounter({
8
+ "name": "event_router_processing_time_spent",
9
+ "help": "Duration spend on event routing",
10
+ "labelNames": [],
11
+ })
12
+
13
+ let executeBatchDurationCounter = PromClient.Counter.makeCounter({
14
+ "name": "execute_batch_processing_time_spent",
15
+ "help": "Duration spend on executing batch",
16
+ "labelNames": [],
17
+ })
18
+
19
+ let eventsProcessedCounter = PromClient.Gauge.makeGauge({
20
+ "name": "events_processed",
21
+ "help": "Total number of events processed",
22
+ "labelNames": ["chainId"],
23
+ })
24
+
25
+ let reorgsDetectedCounter = PromClient.Counter.makeCounter({
26
+ "name": "reorgs_detected",
27
+ "help": "Total number of reorgs detected",
28
+ "labelNames": ["chainId"],
29
+ })
30
+
31
+ let allChainsSyncedToHead = PromClient.Gauge.makeGauge({
32
+ "name": "hyperindex_synced_to_head",
33
+ "help": "All chains fully synced",
34
+ "labelNames": [],
35
+ })
36
+
37
+ let sourceChainHeight = PromClient.Gauge.makeGauge({
38
+ "name": "chain_block_height",
39
+ "help": "Chain Height of Source Chain",
40
+ "labelNames": ["chainId"],
41
+ })
42
+
43
+ module Labels = {
44
+ let rec schemaIsString = (schema: S.t<'a>) =>
45
+ switch schema->S.classify {
46
+ | String => true
47
+ | Null(s)
48
+ | Option(s) =>
49
+ s->schemaIsString
50
+ | _ => false
51
+ }
52
+
53
+ let getLabelNames = (schema: S.t<'a>) =>
54
+ switch schema->S.classify {
55
+ | Object({items}) =>
56
+ let nonStringFields = items->Belt.Array.reduce([], (nonStringFields, item) => {
57
+ if item.schema->schemaIsString {
58
+ nonStringFields
59
+ } else {
60
+ nonStringFields->Belt.Array.concat([item.location])
61
+ }
62
+ })
63
+
64
+ switch nonStringFields {
65
+ | [] => items->Belt.Array.map(item => item.location)->Ok
66
+ | nonStringItems =>
67
+ let nonStringItems = nonStringItems->Js.Array2.joinWith(", ")
68
+ Error(
69
+ `Label schema must be an object with string (or optional string) values. Non string values: ${nonStringItems}`,
70
+ )
71
+ }
72
+ | _ => Error("Label schema must be an object")
73
+ }
74
+ }
75
+
76
+ let metricNames: Utils.Set.t<string> = Utils.Set.make()
77
+
78
+ module MakeSafePromMetric = (
79
+ M: {
80
+ type t
81
+ let make: {"name": string, "help": string, "labelNames": array<string>} => t
82
+ let labels: (t, 'a) => t
83
+ let handleFloat: (t, float) => unit
84
+ let handleInt: (t, int) => unit
85
+ },
86
+ ): {
87
+ type t<'a>
88
+ let makeOrThrow: (~name: string, ~help: string, ~labelSchema: S.t<'a>) => t<'a>
89
+ let handleInt: (t<'a>, ~labels: 'a, ~value: int) => unit
90
+ let handleFloat: (t<'a>, ~labels: 'a, ~value: float) => unit
91
+ } => {
92
+ type t<'a> = {metric: M.t, labelSchema: S.t<'a>}
93
+
94
+ let makeOrThrow = (~name, ~help, ~labelSchema: S.t<'a>): t<'a> =>
95
+ switch labelSchema->Labels.getLabelNames {
96
+ | Ok(labelNames) =>
97
+ if metricNames->Utils.Set.has(name) {
98
+ Js.Exn.raiseError("Duplicate prometheus metric name: " ++ name)
99
+ } else {
100
+ metricNames->Utils.Set.add(name)->ignore
101
+ let metric = M.make({
102
+ "name": name,
103
+ "help": help,
104
+ "labelNames": labelNames,
105
+ })
106
+
107
+ {metric, labelSchema}
108
+ }
109
+
110
+ | Error(error) => Js.Exn.raiseError(error)
111
+ }
112
+
113
+ let handleFloat = ({metric, labelSchema}: t<'a>, ~labels: 'a, ~value) =>
114
+ metric
115
+ ->M.labels(labels->S.reverseConvertToJsonOrThrow(labelSchema))
116
+ ->M.handleFloat(value)
117
+
118
+ let handleInt = ({metric, labelSchema}: t<'a>, ~labels: 'a, ~value) =>
119
+ metric
120
+ ->M.labels(labels->S.reverseConvertToJsonOrThrow(labelSchema))
121
+ ->M.handleInt(value)
122
+ }
123
+
124
+ module SafeCounter = MakeSafePromMetric({
125
+ type t = PromClient.Counter.counter
126
+ let make = PromClient.Counter.makeCounter
127
+ let labels = PromClient.Counter.labels
128
+ let handleInt = PromClient.Counter.incMany
129
+ let handleFloat = PromClient.Counter.incMany->Utils.magic
130
+ })
131
+
132
+ module SafeGauge = MakeSafePromMetric({
133
+ type t = PromClient.Gauge.gauge
134
+ let make = PromClient.Gauge.makeGauge
135
+ let labels = PromClient.Gauge.labels
136
+ let handleInt = PromClient.Gauge.set
137
+ let handleFloat = PromClient.Gauge.setFloat
138
+ })
139
+
140
+ module BenchmarkSummaryData = {
141
+ type labels = {
142
+ group: string,
143
+ stat: string,
144
+ label: string,
145
+ }
146
+ let labelSchema = S.schema(s => {
147
+ group: s.matches(S.string),
148
+ stat: s.matches(S.string),
149
+ label: s.matches(S.string),
150
+ })
151
+
152
+ let gauge = SafeGauge.makeOrThrow(
153
+ ~name="benchmark_summary_data",
154
+ ~help="All data points collected during indexer benchmark",
155
+ ~labelSchema,
156
+ )
157
+
158
+ let set = (
159
+ ~group: string,
160
+ ~label: string,
161
+ ~n: float,
162
+ ~mean: float,
163
+ ~stdDev: option<float>,
164
+ ~min: float,
165
+ ~max: float,
166
+ ~sum: float,
167
+ ) => {
168
+ let mk = stat => {
169
+ group,
170
+ stat,
171
+ label,
172
+ }
173
+ gauge->SafeGauge.handleFloat(~labels=mk("n"), ~value=n)
174
+ gauge->SafeGauge.handleFloat(~labels=mk("mean"), ~value=mean)
175
+ gauge->SafeGauge.handleFloat(~labels=mk("min"), ~value=min)
176
+ gauge->SafeGauge.handleFloat(~labels=mk("max"), ~value=max)
177
+ gauge->SafeGauge.handleFloat(~labels=mk("sum"), ~value=sum)
178
+ switch stdDev {
179
+ | Some(stdDev) => gauge->SafeGauge.handleFloat(~labels=mk("stdDev"), ~value=stdDev)
180
+ | None => ()
181
+ }
182
+ }
183
+ }
184
+
185
+ let processedUntilHeight = PromClient.Gauge.makeGauge({
186
+ "name": "chain_block_height_processed",
187
+ "help": "Block height processed by indexer",
188
+ "labelNames": ["chainId"],
189
+ })
190
+
191
+ let fetchedUntilHeight = PromClient.Gauge.makeGauge({
192
+ "name": "chain_block_height_fully_fetched",
193
+ "help": "Block height fully fetched by indexer",
194
+ "labelNames": ["chainId"],
195
+ })
196
+
197
+ let incrementLoadEntityDurationCounter = (~duration) => {
198
+ loadEntitiesDurationCounter->PromClient.Counter.incMany(duration)
199
+ }
200
+
201
+ let incrementEventRouterDurationCounter = (~duration) => {
202
+ eventRouterDurationCounter->PromClient.Counter.incMany(duration)
203
+ }
204
+
205
+ let incrementExecuteBatchDurationCounter = (~duration) => {
206
+ executeBatchDurationCounter->PromClient.Counter.incMany(duration)
207
+ }
208
+
209
+ let setEventsProcessedGuage = (~number, ~chainId) => {
210
+ eventsProcessedCounter
211
+ ->PromClient.Gauge.labels({"chainId": chainId})
212
+ ->PromClient.Gauge.set(number)
213
+ }
214
+
215
+ let incrementReorgsDetected = (~chain) => {
216
+ reorgsDetectedCounter->PromClient.Counter.incLabels({"chainId": chain->ChainMap.Chain.toString})
217
+ }
218
+
219
+ let setSourceChainHeight = (~blockNumber, ~chain) => {
220
+ sourceChainHeight
221
+ ->PromClient.Gauge.labels({"chainId": chain->ChainMap.Chain.toString})
222
+ ->PromClient.Gauge.set(blockNumber)
223
+ }
224
+
225
+ let setAllChainsSyncedToHead = () => {
226
+ allChainsSyncedToHead->PromClient.Gauge.set(1)
227
+ }
228
+
229
+ let setProcessedUntilHeight = (~blockNumber, ~chain) => {
230
+ processedUntilHeight
231
+ ->PromClient.Gauge.labels({"chainId": chain->ChainMap.Chain.toString})
232
+ ->PromClient.Gauge.set(blockNumber)
233
+ }
234
+
235
+ let setFetchedUntilHeight = (~blockNumber, ~chain) => {
236
+ fetchedUntilHeight
237
+ ->PromClient.Gauge.labels({"chainId": chain->ChainMap.Chain.toString})
238
+ ->PromClient.Gauge.set(blockNumber)
239
+ }
240
+
241
+ module BenchmarkCounters = {
242
+ type labels = {label: string}
243
+ let labelSchema = S.schema(s => {
244
+ label: s.matches(S.string),
245
+ })
246
+
247
+ let gauge = SafeGauge.makeOrThrow(
248
+ ~name="benchmark_counters",
249
+ ~help="All counters collected during indexer benchmark",
250
+ ~labelSchema,
251
+ )
252
+
253
+ let set = (~label, ~millis, ~totalRuntimeMillis) => {
254
+ gauge->SafeGauge.handleFloat(~labels={label: label}, ~value=millis)
255
+ gauge->SafeGauge.handleFloat(~labels={label: "Total Run Time (ms)"}, ~value=totalRuntimeMillis)
256
+ }
257
+ }
258
+
259
+ module PartitionBlockFetched = {
260
+ type labels = {chainId: int, partitionId: string}
261
+
262
+ let labelSchema = S.schema(s => {
263
+ chainId: s.matches(S.string->S.coerce(S.int)),
264
+ partitionId: s.matches(S.string),
265
+ })
266
+
267
+ let counter = SafeGauge.makeOrThrow(
268
+ ~name="partition_block_fetched",
269
+ ~help="The latest fetched block number for each partition",
270
+ ~labelSchema,
271
+ )
272
+
273
+ let set = (~blockNumber, ~partitionId, ~chainId) => {
274
+ counter->SafeGauge.handleInt(~labels={chainId, partitionId}, ~value=blockNumber)
275
+ }
276
+ }
277
+
278
+ let chainIdLabelsSchema = S.object(s => {
279
+ s.field("chainId", S.string->S.coerce(S.int))
280
+ })
281
+
282
+ module IndexingAddresses = {
283
+ let gauge = SafeGauge.makeOrThrow(
284
+ ~name="envio_indexing_addresses",
285
+ ~help="The number of addresses indexed on chain. Includes both static and dynamic addresses.",
286
+ ~labelSchema=chainIdLabelsSchema,
287
+ )
288
+
289
+ let set = (~addressesCount, ~chainId) => {
290
+ gauge->SafeGauge.handleInt(~labels=chainId, ~value=addressesCount)
291
+ }
292
+ }
293
+
294
+ module IndexingEndBlock = {
295
+ let gauge = SafeGauge.makeOrThrow(
296
+ ~name="envio_indexing_end_block",
297
+ ~help="The block number to stop indexing at. (inclusive)",
298
+ ~labelSchema=chainIdLabelsSchema,
299
+ )
300
+
301
+ let set = (~endBlock, ~chainId) => {
302
+ gauge->SafeGauge.handleInt(~labels=chainId, ~value=endBlock)
303
+ }
304
+ }
305
+
306
+ module ProgressBlockNumber = {
307
+ let gauge = SafeGauge.makeOrThrow(
308
+ ~name="envio_progress_block_number",
309
+ ~help="The block number to track the progress of indexing at. Currently uses the fully fetched block number. In the future will be changed to block number processed and stored in the database.",
310
+ ~labelSchema=chainIdLabelsSchema,
311
+ )
312
+
313
+ let set = (~endBlock, ~chainId) => {
314
+ gauge->SafeGauge.handleInt(~labels=chainId, ~value=endBlock)
315
+ }
316
+ }
@@ -0,0 +1,8 @@
1
+ /* TypeScript file generated from BigDecimal.res by genType. */
2
+
3
+ /* eslint-disable */
4
+ /* tslint:disable */
5
+
6
+ import type {default as $$t} from 'bignumber.js';
7
+
8
+ export type t = $$t;
@@ -0,0 +1,60 @@
1
+ @genType.import(("bignumber.js", "default"))
2
+ type rec t = {
3
+ toString: unit => string,
4
+ toFixed: int => string,
5
+ plus: t => t,
6
+ minus: t => t,
7
+ times: t => t,
8
+ div: t => t,
9
+ isEqualTo: t => bool,
10
+ gt: t => bool,
11
+ gte: t => bool,
12
+ lt: t => bool,
13
+ lte: t => bool,
14
+ }
15
+
16
+ // Constructors
17
+ @new @module external fromBigInt: bigint => t = "bignumber.js"
18
+ @new @module external fromFloat: float => t = "bignumber.js"
19
+ @new @module external fromInt: int => t = "bignumber.js"
20
+ @new @module external fromStringUnsafe: string => t = "bignumber.js"
21
+ @new @module external fromString: string => option<t> = "bignumber.js"
22
+
23
+ // Methods
24
+ @send external toString: t => string = "toString"
25
+ @send external toFixed: t => string = "toFixed"
26
+ let toInt = (b: t): option<int> => b->toString->Belt.Int.fromString
27
+ @send external toNumber: t => float = "toNumber"
28
+
29
+ // Arithmetic Operations
30
+ @send external plus: (t, t) => t = "plus"
31
+ @send external minus: (t, t) => t = "minus"
32
+ @send external times: (t, t) => t = "multipliedBy"
33
+ @send external div: (t, t) => t = "dividedBy"
34
+ @send external sqrt: t => t = "sqrt"
35
+
36
+ // Comparison
37
+ @send external equals: (t, t) => bool = "isEqualTo"
38
+ let notEquals: (t, t) => bool = (a, b) => !equals(a, b)
39
+ @send external gt: (t, t) => bool = "isGreaterThan"
40
+ @send external gte: (t, t) => bool = "isGreaterThanOrEqualTo"
41
+ @send external lt: (t, t) => bool = "isLessThan"
42
+ @send external lte: (t, t) => bool = "isLessThanOrEqualTo"
43
+
44
+ // Utilities
45
+ let zero = fromInt(0)
46
+ let one = fromInt(1)
47
+ @send external decimalPlaces: (t, int) => t = "decimalPlaces"
48
+
49
+ // Serialization
50
+ let schema =
51
+ S.string
52
+ ->S.setName("BigDecimal")
53
+ ->S.transform(s => {
54
+ parser: string =>
55
+ switch string->fromString {
56
+ | Some(bigDecimal) => bigDecimal
57
+ | None => s.fail("The string is not valid BigDecimal")
58
+ },
59
+ serializer: bigDecimal => bigDecimal.toString(),
60
+ })
@@ -0,0 +1,58 @@
1
+ /** All metric types have two mandatory parameters: name and help. Refer to https://prometheus.io/docs/practices/naming/ for guidance on naming metrics. */
2
+ type customMetric<'a> = {.."name": string, "help": string} as 'a
3
+
4
+ @module("prom-client") external collectDefaultMetrics: 'a => unit = "collectDefaultMetrics"
5
+
6
+ type registry
7
+ @new @module("prom-client") external makeRegistry: unit => registry = "Registry"
8
+
9
+ @module("prom-client") external defaultRegister: registry = "register"
10
+
11
+ @send external metrics: registry => Promise.t<string> = "metrics"
12
+ @get external getContentType: registry => string = "contentType"
13
+
14
+ module Counter = {
15
+ type counter
16
+ @new @module("prom-client") external makeCounter: customMetric<'a> => counter = "Counter"
17
+
18
+ @send external inc: counter => unit = "inc"
19
+ @send external incMany: (counter, int) => unit = "inc"
20
+
21
+ @send external incLabels: (counter, 'labelsObject) => unit = "labels"
22
+ @send external labels: (counter, 'labelsObject) => counter = "labels"
23
+ }
24
+
25
+ module Gauge = {
26
+ type gauge
27
+ @new @module("prom-client") external makeGauge: customMetric<'a> => gauge = "Gauge"
28
+
29
+ @send external inc: gauge => unit = "inc"
30
+ @send external incMany: (gauge, int) => unit = "inc"
31
+
32
+ @send external dec: gauge => unit = "dec"
33
+ @send external decMany: (gauge, int) => unit = "dec"
34
+
35
+ @send external set: (gauge, int) => unit = "set"
36
+
37
+ @send external setFloat: (gauge, float) => unit = "set"
38
+
39
+ @send external labels: (gauge, 'labelsObject) => gauge = "labels"
40
+ }
41
+
42
+ module Histogram = {
43
+ type histogram
44
+ @new @module("prom-client") external makeHistogram: customMetric<'a> => histogram = "Histogram"
45
+
46
+ @send external observe: (histogram, float) => unit = "observe"
47
+ @send external startTimer: (histogram, unit) => float = "startTimer"
48
+
49
+ @send external labels: (histogram, 'labelsObject) => histogram = "labels"
50
+ }
51
+
52
+ module Summary = {
53
+ type summary
54
+ @new @module("prom-client") external makeSummary: customMetric<'a> => summary = "Summary"
55
+
56
+ @send external observe: (summary, float) => unit = "observe"
57
+ @send external startTimer: (summary, unit) => float = "startTimer"
58
+ }
package/src/db/Table.res CHANGED
@@ -214,7 +214,10 @@ let toSqlParams = (table: table, ~schema) => {
214
214
  }
215
215
  | Bool =>
216
216
  // Workaround for https://github.com/porsager/postgres/issues/471
217
- S.union([S.literal(1)->S.to(_ => true), S.literal(0)->S.to(_ => false)])->S.toUnknown
217
+ S.union([
218
+ S.literal(1)->S.shape(_ => true),
219
+ S.literal(0)->S.shape(_ => false),
220
+ ])->S.toUnknown
218
221
  | _ => schema
219
222
  }
220
223