envio 2.31.1 → 2.32.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.
@@ -0,0 +1,401 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ 'use strict';
3
+
4
+ var Utils = require("./Utils.res.js");
5
+ var Js_exn = require("rescript/lib/js/js_exn.js");
6
+ var Lodash = require("./bindings/Lodash.res.js");
7
+ var Js_dict = require("rescript/lib/js/js_dict.js");
8
+ var Belt_Array = require("rescript/lib/js/belt_Array.js");
9
+ var Belt_Option = require("rescript/lib/js/belt_Option.js");
10
+ var Caml_option = require("rescript/lib/js/caml_option.js");
11
+ var TableIndices = require("./TableIndices.res.js");
12
+ var ErrorHandling = require("./ErrorHandling.res.js");
13
+ var Caml_exceptions = require("rescript/lib/js/caml_exceptions.js");
14
+
15
+ function make(hash) {
16
+ return {
17
+ dict: {},
18
+ hash: hash
19
+ };
20
+ }
21
+
22
+ function set(self, key, value) {
23
+ self.dict[self.hash(key)] = value;
24
+ }
25
+
26
+ function setByHash(self, hash, value) {
27
+ self.dict[hash] = value;
28
+ }
29
+
30
+ function hasByHash(self, hash) {
31
+ return Utils.Dict.has(self.dict, hash);
32
+ }
33
+
34
+ function getUnsafeByHash(self, hash) {
35
+ return self.dict[hash];
36
+ }
37
+
38
+ function get(self, key) {
39
+ return self.dict[self.hash(key)];
40
+ }
41
+
42
+ function values(self) {
43
+ return Js_dict.values(self.dict);
44
+ }
45
+
46
+ function clone(self) {
47
+ return {
48
+ dict: Lodash.cloneDeep(self.dict),
49
+ hash: self.hash
50
+ };
51
+ }
52
+
53
+ var UnexpectedIdNotDefinedOnEntity = /* @__PURE__ */Caml_exceptions.create("InMemoryTable.Entity.UnexpectedIdNotDefinedOnEntity");
54
+
55
+ function getEntityIdUnsafe(entity) {
56
+ var id = entity.id;
57
+ if (id !== undefined) {
58
+ return Caml_option.valFromOption(id);
59
+ } else {
60
+ return ErrorHandling.mkLogAndRaise(undefined, "Property 'id' does not exist on expected entity object", {
61
+ RE_EXN_ID: UnexpectedIdNotDefinedOnEntity
62
+ });
63
+ }
64
+ }
65
+
66
+ function makeIndicesSerializedToValue(index, relatedEntityIdsOpt) {
67
+ var relatedEntityIds = relatedEntityIdsOpt !== undefined ? Caml_option.valFromOption(relatedEntityIdsOpt) : new Set();
68
+ var empty_dict = {};
69
+ var empty_hash = TableIndices.Index.toString;
70
+ var empty = {
71
+ dict: empty_dict,
72
+ hash: empty_hash
73
+ };
74
+ set(empty, index, [
75
+ index,
76
+ relatedEntityIds
77
+ ]);
78
+ return empty;
79
+ }
80
+
81
+ function make$1() {
82
+ return {
83
+ table: {
84
+ dict: {},
85
+ hash: (function (str) {
86
+ return str;
87
+ })
88
+ },
89
+ fieldNameIndices: {
90
+ dict: {},
91
+ hash: TableIndices.Index.getFieldName
92
+ }
93
+ };
94
+ }
95
+
96
+ var UndefinedKey = /* @__PURE__ */Caml_exceptions.create("InMemoryTable.Entity.UndefinedKey");
97
+
98
+ function updateIndices(self, entity, entityIndices) {
99
+ entityIndices.forEach(function (index) {
100
+ var fieldName = TableIndices.Index.getFieldName(index);
101
+ var fieldValue = Js_dict.get(entity, fieldName);
102
+ if (!TableIndices.Index.evaluate(index, fieldName, fieldValue)) {
103
+ entityIndices.delete(index);
104
+ return ;
105
+ }
106
+
107
+ });
108
+ Belt_Array.forEach(Object.keys(self.fieldNameIndices.dict), (function (fieldName) {
109
+ var match = Js_dict.get(entity, fieldName);
110
+ var match$1 = Js_dict.get(self.fieldNameIndices.dict, fieldName);
111
+ if (match !== undefined && match$1 !== undefined) {
112
+ var fieldValue = Caml_option.valFromOption(match);
113
+ return Belt_Array.forEach(Js_dict.values(match$1.dict), (function (param) {
114
+ var relatedEntityIds = param[1];
115
+ var index = param[0];
116
+ if (TableIndices.Index.evaluate(index, fieldName, fieldValue)) {
117
+ relatedEntityIds.add(getEntityIdUnsafe(entity));
118
+ entityIndices.add(index);
119
+ } else {
120
+ relatedEntityIds.delete(getEntityIdUnsafe(entity));
121
+ }
122
+ }));
123
+ }
124
+ ErrorHandling.mkLogAndRaise(undefined, "Expected field name to exist on the referenced index and the provided entity", {
125
+ RE_EXN_ID: UndefinedKey,
126
+ _1: fieldName
127
+ });
128
+ }));
129
+ }
130
+
131
+ function deleteEntityFromIndices(self, entityId, entityIndices) {
132
+ entityIndices.forEach(function (index) {
133
+ var match = Belt_Option.flatMap(get(self.fieldNameIndices, index), (function (__x) {
134
+ return get(__x, index);
135
+ }));
136
+ if (match !== undefined) {
137
+ match[1].delete(entityId);
138
+ }
139
+ entityIndices.delete(index);
140
+ });
141
+ }
142
+
143
+ function initValue(inMemTable, key, entity, allowOverWriteEntityOpt) {
144
+ var allowOverWriteEntity = allowOverWriteEntityOpt !== undefined ? allowOverWriteEntityOpt : false;
145
+ var shouldWriteEntity = allowOverWriteEntity || Belt_Option.isNone(Js_dict.get(inMemTable.table.dict, inMemTable.table.hash(key)));
146
+ if (!shouldWriteEntity) {
147
+ return ;
148
+ }
149
+ var entityIndices = new Set();
150
+ var initialStoreRow;
151
+ if (entity !== undefined) {
152
+ var entity$1 = Caml_option.valFromOption(entity);
153
+ updateIndices(inMemTable, entity$1, entityIndices);
154
+ initialStoreRow = {
155
+ TAG: "InitialReadFromDb",
156
+ _0: {
157
+ TAG: "AlreadySet",
158
+ _0: entity$1
159
+ }
160
+ };
161
+ } else {
162
+ initialStoreRow = {
163
+ TAG: "InitialReadFromDb",
164
+ _0: "NotSet"
165
+ };
166
+ }
167
+ inMemTable.table.dict[inMemTable.table.hash(key)] = {
168
+ entityRow: initialStoreRow,
169
+ entityIndices: entityIndices
170
+ };
171
+ }
172
+
173
+ function set$1(inMemTable, entityUpdate, shouldSaveHistory, containsRollbackDiffChangeOpt) {
174
+ var containsRollbackDiffChange = containsRollbackDiffChangeOpt !== undefined ? containsRollbackDiffChangeOpt : false;
175
+ var match = get(inMemTable.table, entityUpdate.entityId);
176
+ var match$1;
177
+ if (match !== undefined) {
178
+ var previous_values = match.entityRow;
179
+ if (previous_values.TAG === "Updated") {
180
+ var previous_values$1 = previous_values._0;
181
+ var entityRow = {
182
+ TAG: "Updated",
183
+ _0: {
184
+ latest: entityUpdate,
185
+ history: shouldSaveHistory ? (
186
+ previous_values$1.latest.checkpointId === entityUpdate.checkpointId ? Utils.$$Array.setIndexImmutable(previous_values$1.history, previous_values$1.history.length - 1 | 0, entityUpdate) : Belt_Array.concatMany([
187
+ previous_values$1.history,
188
+ [entityUpdate]
189
+ ])
190
+ ) : previous_values$1.history,
191
+ containsRollbackDiffChange: previous_values$1.containsRollbackDiffChange
192
+ }
193
+ };
194
+ match$1 = {
195
+ entityRow: entityRow,
196
+ entityIndices: match.entityIndices
197
+ };
198
+ } else {
199
+ match$1 = {
200
+ entityRow: {
201
+ TAG: "Updated",
202
+ _0: {
203
+ latest: entityUpdate,
204
+ history: shouldSaveHistory ? [entityUpdate] : [],
205
+ containsRollbackDiffChange: containsRollbackDiffChange
206
+ }
207
+ },
208
+ entityIndices: match.entityIndices
209
+ };
210
+ }
211
+ } else {
212
+ match$1 = {
213
+ entityRow: {
214
+ TAG: "Updated",
215
+ _0: {
216
+ latest: entityUpdate,
217
+ history: shouldSaveHistory ? [entityUpdate] : [],
218
+ containsRollbackDiffChange: containsRollbackDiffChange
219
+ }
220
+ },
221
+ entityIndices: new Set()
222
+ };
223
+ }
224
+ var entityIndices = match$1.entityIndices;
225
+ var entity = entityUpdate.entityUpdateAction;
226
+ if (typeof entity !== "object") {
227
+ deleteEntityFromIndices(inMemTable, entityUpdate.entityId, entityIndices);
228
+ } else {
229
+ updateIndices(inMemTable, entity._0, entityIndices);
230
+ }
231
+ set(inMemTable.table, entityUpdate.entityId, {
232
+ entityRow: match$1.entityRow,
233
+ entityIndices: entityIndices
234
+ });
235
+ }
236
+
237
+ function rowToEntity(row) {
238
+ var match = row.entityRow;
239
+ if (match.TAG === "Updated") {
240
+ var entity = match._0.latest.entityUpdateAction;
241
+ if (typeof entity !== "object") {
242
+ return ;
243
+ } else {
244
+ return Caml_option.some(entity._0);
245
+ }
246
+ }
247
+ var entity$1 = match._0;
248
+ if (typeof entity$1 !== "object") {
249
+ return ;
250
+ } else {
251
+ return Caml_option.some(entity$1._0);
252
+ }
253
+ }
254
+
255
+ function getUnsafe(inMemTable) {
256
+ return function (key) {
257
+ return rowToEntity(inMemTable.table.dict[key]);
258
+ };
259
+ }
260
+
261
+ function hasIndex(inMemTable, fieldName, operator) {
262
+ return function (fieldValueHash) {
263
+ var indicesSerializedToValue = inMemTable.fieldNameIndices.dict[fieldName];
264
+ if (indicesSerializedToValue === undefined) {
265
+ return false;
266
+ }
267
+ var key = fieldName + ":" + operator + ":" + fieldValueHash;
268
+ return indicesSerializedToValue.dict[key] !== undefined;
269
+ };
270
+ }
271
+
272
+ function getUnsafeOnIndex(inMemTable, fieldName, operator) {
273
+ var getEntity = getUnsafe(inMemTable);
274
+ return function (fieldValueHash) {
275
+ var indicesSerializedToValue = inMemTable.fieldNameIndices.dict[fieldName];
276
+ if (indicesSerializedToValue === undefined) {
277
+ return Js_exn.raiseError("Unexpected error. Must have an index on field " + fieldName);
278
+ }
279
+ var key = fieldName + ":" + operator + ":" + fieldValueHash;
280
+ var match = indicesSerializedToValue.dict[key];
281
+ if (match !== undefined) {
282
+ return Belt_Array.keepMap(Array.from(match[1]), (function (entityId) {
283
+ if (hasByHash(inMemTable.table, entityId)) {
284
+ return getEntity(entityId);
285
+ }
286
+
287
+ }));
288
+ } else {
289
+ return Js_exn.raiseError("Unexpected error. Must have an index for the value " + fieldValueHash + " on field " + fieldName);
290
+ }
291
+ };
292
+ }
293
+
294
+ function addEmptyIndex(inMemTable, index) {
295
+ var fieldName = TableIndices.Index.getFieldName(index);
296
+ var relatedEntityIds = new Set();
297
+ Belt_Array.forEach(Js_dict.values(inMemTable.table.dict), (function (row) {
298
+ var entity = rowToEntity(row);
299
+ if (entity === undefined) {
300
+ return ;
301
+ }
302
+ var entity$1 = Caml_option.valFromOption(entity);
303
+ var fieldValue = entity$1[fieldName];
304
+ if (TableIndices.Index.evaluate(index, fieldName, fieldValue)) {
305
+ row.entityIndices.add(index);
306
+ relatedEntityIds.add(getEntityIdUnsafe(entity$1));
307
+ return ;
308
+ }
309
+
310
+ }));
311
+ var indicesSerializedToValue = get(inMemTable.fieldNameIndices, index);
312
+ if (indicesSerializedToValue === undefined) {
313
+ return set(inMemTable.fieldNameIndices, index, makeIndicesSerializedToValue(index, Caml_option.some(relatedEntityIds)));
314
+ }
315
+ var match = get(indicesSerializedToValue, index);
316
+ if (match !== undefined) {
317
+ return ;
318
+ } else {
319
+ return set(indicesSerializedToValue, index, [
320
+ index,
321
+ relatedEntityIds
322
+ ]);
323
+ }
324
+ }
325
+
326
+ function addIdToIndex(inMemTable, index, entityId) {
327
+ var indicesSerializedToValue = get(inMemTable.fieldNameIndices, index);
328
+ if (indicesSerializedToValue === undefined) {
329
+ return set(inMemTable.fieldNameIndices, index, makeIndicesSerializedToValue(index, Caml_option.some(new Set().add(entityId))));
330
+ }
331
+ var match = get(indicesSerializedToValue, index);
332
+ if (match !== undefined) {
333
+ match[1].add(entityId);
334
+ return ;
335
+ } else {
336
+ return set(indicesSerializedToValue, index, [
337
+ index,
338
+ new Set().add(entityId)
339
+ ]);
340
+ }
341
+ }
342
+
343
+ function rows(inMemTable) {
344
+ return Belt_Array.map(Js_dict.values(inMemTable.table.dict), (function (v) {
345
+ return v.entityRow;
346
+ }));
347
+ }
348
+
349
+ function values$1(inMemTable) {
350
+ return Belt_Array.keepMap(Js_dict.values(inMemTable.table.dict), rowToEntity);
351
+ }
352
+
353
+ function clone$1(param) {
354
+ var fieldNameIndices = param.fieldNameIndices;
355
+ return {
356
+ table: clone(param.table),
357
+ fieldNameIndices: {
358
+ dict: Js_dict.fromArray(Belt_Array.map(Js_dict.entries(fieldNameIndices.dict), (function (param) {
359
+ return [
360
+ param[0],
361
+ clone(param[1])
362
+ ];
363
+ }))),
364
+ hash: fieldNameIndices.hash
365
+ }
366
+ };
367
+ }
368
+
369
+ var Entity = {
370
+ UnexpectedIdNotDefinedOnEntity: UnexpectedIdNotDefinedOnEntity,
371
+ getEntityIdUnsafe: getEntityIdUnsafe,
372
+ makeIndicesSerializedToValue: makeIndicesSerializedToValue,
373
+ make: make$1,
374
+ UndefinedKey: UndefinedKey,
375
+ updateIndices: updateIndices,
376
+ deleteEntityFromIndices: deleteEntityFromIndices,
377
+ initValue: initValue,
378
+ setRow: set,
379
+ set: set$1,
380
+ rowToEntity: rowToEntity,
381
+ getRow: get,
382
+ getUnsafe: getUnsafe,
383
+ hasIndex: hasIndex,
384
+ getUnsafeOnIndex: getUnsafeOnIndex,
385
+ addEmptyIndex: addEmptyIndex,
386
+ addIdToIndex: addIdToIndex,
387
+ rows: rows,
388
+ values: values$1,
389
+ clone: clone$1
390
+ };
391
+
392
+ exports.make = make;
393
+ exports.set = set;
394
+ exports.setByHash = setByHash;
395
+ exports.hasByHash = hasByHash;
396
+ exports.getUnsafeByHash = getUnsafeByHash;
397
+ exports.get = get;
398
+ exports.values = values;
399
+ exports.clone = clone;
400
+ exports.Entity = Entity;
401
+ /* Utils Not a pure module */
@@ -0,0 +1,5 @@
1
+ type t = {
2
+ registrations: EventRegister.registrations,
3
+ config: Config.t,
4
+ persistence: Persistence.t,
5
+ }
package/src/Internal.res CHANGED
@@ -281,25 +281,37 @@ let makeEnumConfig = (~name, ~variants) => {
281
281
 
282
282
  type effectInput
283
283
  type effectOutput
284
- type effectContext
284
+ type effectContext = private {mutable cache: bool}
285
285
  type effectArgs = {
286
286
  input: effectInput,
287
287
  context: effectContext,
288
288
  cacheKey: string,
289
289
  }
290
290
  type effectCacheItem = {id: string, output: effectOutput}
291
- type effectCacheMeta = {
291
+ type effectCacheStorageMeta = {
292
292
  itemSchema: S.t<effectCacheItem>,
293
293
  outputSchema: S.t<effectOutput>,
294
294
  table: Table.table,
295
295
  }
296
+ type rateLimitState = {
297
+ callsPerDuration: int,
298
+ durationMs: int,
299
+ mutable availableCalls: int,
300
+ mutable windowStartTime: float,
301
+ mutable queueCount: int,
302
+ mutable nextWindowPromise: option<promise<unit>>,
303
+ }
296
304
  type effect = {
297
305
  name: string,
298
306
  handler: effectArgs => promise<effectOutput>,
299
- cache: option<effectCacheMeta>,
307
+ storageMeta: effectCacheStorageMeta,
308
+ defaultShouldCache: bool,
300
309
  output: S.t<effectOutput>,
301
310
  input: S.t<effectInput>,
302
- mutable callsCount: int,
311
+ // The number of functions that are currently running.
312
+ mutable activeCallsCount: int,
313
+ mutable prevCallStartTimerRef: Hrtime.timeRef,
314
+ rateLimit: option<rateLimitState>,
303
315
  }
304
316
  let cacheTablePrefix = "envio_effect_"
305
317
  let cacheOutputSchema = S.json(~validate=false)->(Utils.magic: S.t<Js.Json.t> => S.t<effectOutput>)
@@ -34,7 +34,7 @@ type initialState = {
34
34
  reorgCheckpoints: array<Internal.reorgCheckpoint>,
35
35
  }
36
36
 
37
- type operator = [#">" | #"="]
37
+ type operator = [#">" | #"=" | #"<"]
38
38
 
39
39
  type storage = {
40
40
  // Should return true if we already have persisted data
@@ -43,7 +43,7 @@ type storage = {
43
43
  // Should initialize the storage so we can start interacting with it
44
44
  // Eg create connection, schema, tables, etc.
45
45
  initialize: (
46
- ~chainConfigs: array<InternalConfig.chain>=?,
46
+ ~chainConfigs: array<Config.chain>=?,
47
47
  ~entities: array<Internal.entityConfig>=?,
48
48
  ~enums: array<Internal.enumConfig<Internal.enum>>=?,
49
49
  ) => promise<initialState>,
@@ -91,7 +91,10 @@ type t = {
91
91
  allEntities: array<Internal.entityConfig>,
92
92
  allEnums: array<Internal.enumConfig<Internal.enum>>,
93
93
  mutable storageStatus: storageStatus,
94
- storage: storage,
94
+ mutable storage: storage,
95
+ // FIXME: This is temporary to move it library
96
+ // Should be a part of the storage interface and db agnostic
97
+ mutable sql: Postgres.sql,
95
98
  }
96
99
 
97
100
  let entityHistoryActionEnumConfig: Internal.enumConfig<EntityHistory.RowAction.t> = {
@@ -106,6 +109,7 @@ let make = (
106
109
  // TODO: Should only pass userEnums and create internal config in runtime
107
110
  ~allEnums,
108
111
  ~storage,
112
+ ~sql,
109
113
  ) => {
110
114
  let allEntities = userEntities->Js.Array2.concat([InternalTable.DynamicContractRegistry.config])
111
115
  let allEnums =
@@ -116,6 +120,7 @@ let make = (
116
120
  allEnums,
117
121
  storageStatus: Unknown,
118
122
  storage,
123
+ sql,
119
124
  }
120
125
  }
121
126
 
@@ -25,7 +25,7 @@ var entityHistoryActionEnumConfig = {
25
25
  default: "SET"
26
26
  };
27
27
 
28
- function make(userEntities, allEnums, storage) {
28
+ function make(userEntities, allEnums, storage, sql) {
29
29
  var allEntities = userEntities.concat([InternalTable.DynamicContractRegistry.config]);
30
30
  var allEnums$1 = allEnums.concat([entityHistoryActionEnumConfig]);
31
31
  return {
@@ -33,7 +33,8 @@ function make(userEntities, allEnums, storage) {
33
33
  allEntities: allEntities,
34
34
  allEnums: allEnums$1,
35
35
  storageStatus: "Unknown",
36
- storage: storage
36
+ storage: storage,
37
+ sql: sql
37
38
  };
38
39
  }
39
40
 
package/src/PgStorage.res CHANGED
@@ -789,13 +789,7 @@ let make = (
789
789
  ~items: array<Internal.effectCacheItem>,
790
790
  ~initialize: bool,
791
791
  ) => {
792
- let {table, itemSchema} = switch effect.cache {
793
- | Some(cacheMeta) => cacheMeta
794
- | None =>
795
- Js.Exn.raiseError(
796
- `Failed to set effect cache for "${effect.name}". Effect has no cache enabled.`,
797
- )
798
- }
792
+ let {table, itemSchema} = effect.storageMeta
799
793
 
800
794
  if initialize {
801
795
  let _ =
@@ -570,8 +570,7 @@ function make(sql, pgHost, pgSchema, pgPort, pgUser, pgDatabase, pgPassword, isH
570
570
  return setOrThrow(sql, items, table, itemSchema, pgSchema);
571
571
  };
572
572
  var setEffectCacheOrThrow = async function (effect, items, initialize) {
573
- var cacheMeta = effect.cache;
574
- var match = cacheMeta !== undefined ? cacheMeta : Js_exn.raiseError("Failed to set effect cache for \"" + effect.name + "\". Effect has no cache enabled.");
573
+ var match = effect.storageMeta;
575
574
  var table = match.table;
576
575
  if (initialize) {
577
576
  await sql.unsafe(makeCreateTableQuery(table, pgSchema, false));
@@ -580,20 +580,46 @@ module ProgressBatchCount = {
580
580
  }
581
581
  }
582
582
 
583
+ module ProgressLatency = {
584
+ let gauge = SafeGauge.makeOrThrow(
585
+ ~name="envio_progress_latency",
586
+ ~help="The latency in milliseconds between the latest processed event creation and the time it was written to storage.",
587
+ ~labelSchema=chainIdLabelsSchema,
588
+ )
589
+
590
+ let set = (~latencyMs, ~chainId) => {
591
+ gauge->SafeGauge.handleInt(~labels=chainId, ~value=latencyMs)
592
+ }
593
+ }
594
+
583
595
  let effectLabelsSchema = S.object(s => {
584
596
  s.field("effect", S.string)
585
597
  })
586
598
 
587
- module EffectCallsCount = {
588
- let gauge = SafeGauge.makeOrThrow(
599
+ module EffectCalls = {
600
+ let timeCounter = SafeCounter.makeOrThrow(
601
+ ~name="envio_effect_calls_time",
602
+ ~help="Processing time taken to call the Effect function. (milliseconds)",
603
+ ~labelSchema=effectLabelsSchema,
604
+ )
605
+
606
+ let sumTimeCounter = SafeCounter.makeOrThrow(
607
+ ~name="envio_effect_calls_sum_time",
608
+ ~help="Cumulative time spent calling the Effect function during the indexing process. (milliseconds)",
609
+ ~labelSchema=effectLabelsSchema,
610
+ )
611
+
612
+ let totalCallsCount = SafeCounter.makeOrThrow(
589
613
  ~name="envio_effect_calls_count",
590
- ~help="The number of calls to the effect. Including both handler execution and cache hits.",
614
+ ~help="Cumulative number of resolved Effect function calls during the indexing process.",
591
615
  ~labelSchema=effectLabelsSchema,
592
616
  )
593
617
 
594
- let set = (~callsCount, ~effectName) => {
595
- gauge->SafeGauge.handleInt(~labels=effectName, ~value=callsCount)
596
- }
618
+ let activeCallsCount = SafeGauge.makeOrThrow(
619
+ ~name="envio_effect_active_calls_count",
620
+ ~help="The number of Effect function calls that are currently running.",
621
+ ~labelSchema=effectLabelsSchema,
622
+ )
597
623
  }
598
624
 
599
625
  module EffectCacheCount = {
@@ -620,6 +646,18 @@ module EffectCacheInvalidationsCount = {
620
646
  }
621
647
  }
622
648
 
649
+ module EffectQueueCount = {
650
+ let gauge = SafeGauge.makeOrThrow(
651
+ ~name="envio_effect_queue_count",
652
+ ~help="The number of effect calls waiting in the rate limit queue.",
653
+ ~labelSchema=effectLabelsSchema,
654
+ )
655
+
656
+ let set = (~count, ~effectName) => {
657
+ gauge->SafeGauge.handleInt(~labels=effectName, ~value=count)
658
+ }
659
+ }
660
+
623
661
  module StorageLoad = {
624
662
  let operationLabelsSchema = S.object(s => s.field("operation", S.string))
625
663
 
@@ -629,8 +667,8 @@ module StorageLoad = {
629
667
  ~labelSchema=operationLabelsSchema,
630
668
  )
631
669
 
632
- let totalTimeCounter = SafeCounter.makeOrThrow(
633
- ~name="envio_storage_load_total_time",
670
+ let sumTimeCounter = SafeCounter.makeOrThrow(
671
+ ~name="envio_storage_load_sum_time",
634
672
  ~help="Cumulative time spent loading data from storage during the indexing process. (milliseconds)",
635
673
  ~labelSchema=operationLabelsSchema,
636
674
  )
@@ -686,7 +724,7 @@ module StorageLoad = {
686
724
  )
687
725
  operations->Utils.Dict.deleteInPlace(operation)
688
726
  }
689
- totalTimeCounter->SafeCounter.handleInt(
727
+ sumTimeCounter->SafeCounter.handleInt(
690
728
  ~labels={operation},
691
729
  ~value=timerRef->Hrtime.timeSince->Hrtime.toMillis->Hrtime.intFromMillis,
692
730
  )