envio 2.32.0-alpha.0 → 2.32.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/index.d.ts +32 -0
- package/package.json +5 -5
- package/src/Batch.res +2 -2
- package/src/Config.res +124 -0
- package/src/Config.res.js +84 -0
- package/src/Envio.gen.ts +21 -0
- package/src/Envio.res +77 -13
- package/src/Envio.res.js +51 -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 +13 -3
- package/src/Persistence.res +7 -2
- package/src/Persistence.res.js +3 -2
- package/src/PgStorage.res +1 -7
- package/src/PgStorage.res.js +1 -2
- package/src/Prometheus.res +18 -0
- package/src/Prometheus.res.js +18 -3
- package/src/ReorgDetection.res +8 -22
- package/src/ReorgDetection.res.js +11 -21
- package/src/TableIndices.res +110 -0
- package/src/TableIndices.res.js +143 -0
- package/src/Types.ts +5 -0
- package/src/bindings/Hrtime.res +4 -0
- package/src/bindings/Hrtime.res.js +5 -0
- package/src/bindings/Hrtime.resi +2 -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 +25 -21
- package/src/sources/RpcSource.res.js +21 -15
- 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,27 +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.
|
|
303
312
|
mutable activeCallsCount: int,
|
|
304
313
|
mutable prevCallStartTimerRef: Hrtime.timeRef,
|
|
314
|
+
rateLimit: option<rateLimitState>,
|
|
305
315
|
}
|
|
306
316
|
let cacheTablePrefix = "envio_effect_"
|
|
307
317
|
let cacheOutputSchema = S.json(~validate=false)->(Utils.magic: S.t<Js.Json.t> => S.t<effectOutput>)
|
package/src/Persistence.res
CHANGED
|
@@ -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
|
@@ -646,6 +646,24 @@ module EffectCacheInvalidationsCount = {
|
|
|
646
646
|
}
|
|
647
647
|
}
|
|
648
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 timeCounter = SafeCounter.makeOrThrow(
|
|
657
|
+
~name="envio_effect_queue_time",
|
|
658
|
+
~help="The time spent waiting in the rate limit queue. (milliseconds)",
|
|
659
|
+
~labelSchema=effectLabelsSchema,
|
|
660
|
+
)
|
|
661
|
+
|
|
662
|
+
let set = (~count, ~effectName) => {
|
|
663
|
+
gauge->SafeGauge.handleInt(~labels=effectName, ~value=count)
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
649
667
|
module StorageLoad = {
|
|
650
668
|
let operationLabelsSchema = S.object(s => s.field("operation", S.string))
|
|
651
669
|
|
package/src/Prometheus.res.js
CHANGED
|
@@ -740,11 +740,25 @@ var EffectCacheInvalidationsCount = {
|
|
|
740
740
|
increment: increment$6
|
|
741
741
|
};
|
|
742
742
|
|
|
743
|
+
var gauge$22 = makeOrThrow$1("envio_effect_queue_count", "The number of effect calls waiting in the rate limit queue.", effectLabelsSchema);
|
|
744
|
+
|
|
745
|
+
var timeCounter$3 = makeOrThrow("envio_effect_queue_time", "The time spent waiting in the rate limit queue. (milliseconds)", effectLabelsSchema);
|
|
746
|
+
|
|
747
|
+
function set$21(count, effectName) {
|
|
748
|
+
handleInt$1(gauge$22, effectName, count);
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
var EffectQueueCount = {
|
|
752
|
+
gauge: gauge$22,
|
|
753
|
+
timeCounter: timeCounter$3,
|
|
754
|
+
set: set$21
|
|
755
|
+
};
|
|
756
|
+
|
|
743
757
|
var operationLabelsSchema = S$RescriptSchema.object(function (s) {
|
|
744
758
|
return s.f("operation", S$RescriptSchema.string);
|
|
745
759
|
});
|
|
746
760
|
|
|
747
|
-
var timeCounter$
|
|
761
|
+
var timeCounter$4 = makeOrThrow("envio_storage_load_time", "Processing time taken to load data from storage. (milliseconds)", operationLabelsSchema);
|
|
748
762
|
|
|
749
763
|
var sumTimeCounter$1 = makeOrThrow("envio_storage_load_sum_time", "Cumulative time spent loading data from storage during the indexing process. (milliseconds)", operationLabelsSchema);
|
|
750
764
|
|
|
@@ -773,7 +787,7 @@ function endOperation(timerRef, operation, whereSize, size) {
|
|
|
773
787
|
var operationRef = operations[operation];
|
|
774
788
|
operationRef.pendingCount = operationRef.pendingCount - 1 | 0;
|
|
775
789
|
if (operationRef.pendingCount === 0) {
|
|
776
|
-
handleInt(timeCounter$
|
|
790
|
+
handleInt(timeCounter$4, operation, Hrtime.intFromMillis(Hrtime.toMillis(Hrtime.timeSince(operationRef.timerRef))));
|
|
777
791
|
Utils.Dict.deleteInPlace(operations, operation);
|
|
778
792
|
}
|
|
779
793
|
handleInt(sumTimeCounter$1, operation, Hrtime.intFromMillis(Hrtime.toMillis(Hrtime.timeSince(timerRef))));
|
|
@@ -784,7 +798,7 @@ function endOperation(timerRef, operation, whereSize, size) {
|
|
|
784
798
|
|
|
785
799
|
var StorageLoad = {
|
|
786
800
|
operationLabelsSchema: operationLabelsSchema,
|
|
787
|
-
timeCounter: timeCounter$
|
|
801
|
+
timeCounter: timeCounter$4,
|
|
788
802
|
sumTimeCounter: sumTimeCounter$1,
|
|
789
803
|
counter: counter$7,
|
|
790
804
|
whereSizeCounter: whereSizeCounter,
|
|
@@ -844,5 +858,6 @@ exports.effectLabelsSchema = effectLabelsSchema;
|
|
|
844
858
|
exports.EffectCalls = EffectCalls;
|
|
845
859
|
exports.EffectCacheCount = EffectCacheCount;
|
|
846
860
|
exports.EffectCacheInvalidationsCount = EffectCacheInvalidationsCount;
|
|
861
|
+
exports.EffectQueueCount = EffectQueueCount;
|
|
847
862
|
exports.StorageLoad = StorageLoad;
|
|
848
863
|
/* loadEntitiesDurationCounter Not a pure module */
|
package/src/ReorgDetection.res
CHANGED
|
@@ -51,18 +51,12 @@ type t = {
|
|
|
51
51
|
// A hash map of recent blockdata by block number to make comparison checks
|
|
52
52
|
// for reorgs.
|
|
53
53
|
dataByBlockNumber: dict<blockData>,
|
|
54
|
-
// The latest block which detected a reorg
|
|
55
|
-
// and should never be valid.
|
|
56
|
-
// We keep track of this to avoid responses
|
|
57
|
-
// with the stale data from other data-source instances.
|
|
58
|
-
detectedReorgBlock: option<blockData>,
|
|
59
54
|
}
|
|
60
55
|
|
|
61
56
|
let make = (
|
|
62
57
|
~chainReorgCheckpoints: array<Internal.reorgCheckpoint>,
|
|
63
58
|
~maxReorgDepth,
|
|
64
59
|
~shouldRollbackOnReorg,
|
|
65
|
-
~detectedReorgBlock=?,
|
|
66
60
|
) => {
|
|
67
61
|
let dataByBlockNumber = Js.Dict.empty()
|
|
68
62
|
|
|
@@ -80,7 +74,6 @@ let make = (
|
|
|
80
74
|
shouldRollbackOnReorg,
|
|
81
75
|
maxReorgDepth,
|
|
82
76
|
dataByBlockNumber,
|
|
83
|
-
detectedReorgBlock,
|
|
84
77
|
}
|
|
85
78
|
}
|
|
86
79
|
|
|
@@ -149,10 +142,7 @@ let registerReorgGuard = (
|
|
|
149
142
|
switch maybeReorgDetected {
|
|
150
143
|
| Some(reorgDetected) => (
|
|
151
144
|
shouldRollbackOnReorg
|
|
152
|
-
?
|
|
153
|
-
...self,
|
|
154
|
-
detectedReorgBlock: Some(reorgDetected.scannedBlock),
|
|
155
|
-
}
|
|
145
|
+
? self
|
|
156
146
|
: make(~chainReorgCheckpoints=[], ~maxReorgDepth, ~shouldRollbackOnReorg),
|
|
157
147
|
ReorgDetected(reorgDetected),
|
|
158
148
|
)
|
|
@@ -174,7 +164,6 @@ let registerReorgGuard = (
|
|
|
174
164
|
{
|
|
175
165
|
maxReorgDepth,
|
|
176
166
|
dataByBlockNumber: dataByBlockNumberCopyInThreshold,
|
|
177
|
-
detectedReorgBlock: None,
|
|
178
167
|
shouldRollbackOnReorg,
|
|
179
168
|
},
|
|
180
169
|
NoReorg,
|
|
@@ -202,20 +191,18 @@ let getLatestValidScannedBlock = (
|
|
|
202
191
|
let getPrevScannedBlockNumber = idx =>
|
|
203
192
|
ascBlockNumberKeys
|
|
204
193
|
->Belt.Array.get(idx - 1)
|
|
205
|
-
->Option.
|
|
206
|
-
|
|
207
|
-
switch verifiedDataByBlockNumber->Utils.Dict.dangerouslyGetNonOption(key) {
|
|
208
|
-
| Some(v) => Some(v.blockNumber)
|
|
209
|
-
| None => None
|
|
210
|
-
}
|
|
194
|
+
->Option.map(key => {
|
|
195
|
+
(verifiedDataByBlockNumber->Js.Dict.unsafeGet(key)).blockNumber
|
|
211
196
|
})
|
|
212
197
|
|
|
213
198
|
let rec loop = idx => {
|
|
214
199
|
switch ascBlockNumberKeys->Belt.Array.get(idx) {
|
|
215
200
|
| Some(blockNumberKey) =>
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
201
|
+
switch reorgDetection.dataByBlockNumber->Utils.Dict.dangerouslyGetNonOption(blockNumberKey) {
|
|
202
|
+
| Some(scannedBlock)
|
|
203
|
+
if (verifiedDataByBlockNumber->Js.Dict.unsafeGet(blockNumberKey)).blockHash ===
|
|
204
|
+
scannedBlock.blockHash =>
|
|
205
|
+
loop(idx + 1)
|
|
219
206
|
| _ => getPrevScannedBlockNumber(idx)
|
|
220
207
|
}
|
|
221
208
|
| None => getPrevScannedBlockNumber(idx)
|
|
@@ -257,7 +244,6 @@ let rollbackToValidBlockNumber = (
|
|
|
257
244
|
{
|
|
258
245
|
maxReorgDepth,
|
|
259
246
|
dataByBlockNumber: newDataByBlockNumber,
|
|
260
|
-
detectedReorgBlock: None,
|
|
261
247
|
shouldRollbackOnReorg,
|
|
262
248
|
}
|
|
263
249
|
}
|