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.
- package/index.d.ts +32 -0
- package/package.json +5 -5
- package/src/Batch.res +22 -2
- package/src/Batch.res.js +15 -0
- package/src/Config.res +124 -0
- package/src/Config.res.js +84 -0
- package/src/Envio.gen.ts +21 -0
- package/src/Envio.res +79 -14
- package/src/Envio.res.js +52 -15
- package/src/EventRegister.res +2 -2
- package/src/EventRegister.resi +2 -2
- package/src/InMemoryTable.res +356 -0
- package/src/InMemoryTable.res.js +401 -0
- package/src/Indexer.res +5 -0
- package/src/Internal.res +16 -4
- package/src/Persistence.res +8 -3
- package/src/Persistence.res.js +3 -2
- package/src/PgStorage.res +1 -7
- package/src/PgStorage.res.js +1 -2
- package/src/Prometheus.res +47 -9
- package/src/Prometheus.res.js +42 -14
- package/src/TableIndices.res +110 -0
- package/src/TableIndices.res.js +143 -0
- package/src/Types.ts +5 -0
- package/src/bindings/Lodash.res +3 -0
- package/src/bindings/Lodash.res.js +11 -0
- package/src/bindings/vendored-lodash-fns.js +1441 -0
- package/src/db/InternalTable.res +2 -2
- package/src/sources/RpcSource.res +2 -2
- package/src/InternalConfig.res +0 -48
- /package/src/{InternalConfig.res.js → Indexer.res.js} +0 -0
|
@@ -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 */
|
package/src/Indexer.res
ADDED
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
|
|
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
|
-
|
|
307
|
+
storageMeta: effectCacheStorageMeta,
|
|
308
|
+
defaultShouldCache: bool,
|
|
300
309
|
output: S.t<effectOutput>,
|
|
301
310
|
input: S.t<effectInput>,
|
|
302
|
-
|
|
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>)
|
package/src/Persistence.res
CHANGED
|
@@ -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<
|
|
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
|
|
package/src/Persistence.res.js
CHANGED
|
@@ -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} =
|
|
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 _ =
|
package/src/PgStorage.res.js
CHANGED
|
@@ -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
|
|
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));
|
package/src/Prometheus.res
CHANGED
|
@@ -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
|
|
588
|
-
let
|
|
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="
|
|
614
|
+
~help="Cumulative number of resolved Effect function calls during the indexing process.",
|
|
591
615
|
~labelSchema=effectLabelsSchema,
|
|
592
616
|
)
|
|
593
617
|
|
|
594
|
-
let
|
|
595
|
-
|
|
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
|
|
633
|
-
~name="
|
|
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
|
-
|
|
727
|
+
sumTimeCounter->SafeCounter.handleInt(
|
|
690
728
|
~labels={operation},
|
|
691
729
|
~value=timerRef->Hrtime.timeSince->Hrtime.toMillis->Hrtime.intFromMillis,
|
|
692
730
|
)
|