envio 3.0.2 → 3.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/evm.schema.json +15 -8
- package/fuel.schema.json +19 -12
- package/index.d.ts +0 -2
- package/package.json +6 -7
- package/rescript.json +1 -1
- package/src/Batch.res +4 -214
- package/src/Batch.res.mjs +6 -165
- package/src/ChainFetcher.res +12 -28
- package/src/ChainFetcher.res.mjs +8 -17
- package/src/ChainManager.res +10 -9
- package/src/ChainManager.res.mjs +6 -10
- package/src/Config.res +9 -25
- package/src/Config.res.mjs +17 -27
- package/src/Core.res +7 -0
- package/src/Ctx.res +1 -0
- package/src/Env.res +0 -8
- package/src/Env.res.mjs +0 -6
- package/src/EventConfigBuilder.res +13 -123
- package/src/EventConfigBuilder.res.mjs +6 -73
- package/src/EventProcessing.res +5 -29
- package/src/EventProcessing.res.mjs +11 -20
- package/src/EventUtils.res +0 -27
- package/src/EventUtils.res.mjs +0 -24
- package/src/FetchState.res +2 -15
- package/src/FetchState.res.mjs +3 -18
- package/src/GlobalState.res +26 -39
- package/src/GlobalState.res.mjs +12 -40
- package/src/HandlerLoader.res +6 -5
- package/src/HandlerLoader.res.mjs +27 -9
- package/src/HandlerRegister.res +1 -12
- package/src/HandlerRegister.res.mjs +1 -6
- package/src/HandlerRegister.resi +1 -1
- package/src/Hasura.res +96 -32
- package/src/Hasura.res.mjs +93 -38
- package/src/InMemoryStore.res +205 -45
- package/src/InMemoryStore.res.mjs +157 -40
- package/src/InMemoryTable.res +165 -249
- package/src/InMemoryTable.res.mjs +156 -227
- package/src/Internal.res +10 -34
- package/src/Internal.res.mjs +9 -3
- package/src/LoadLayer.res +5 -5
- package/src/LoadLayer.res.mjs +5 -5
- package/src/LogSelection.res +15 -19
- package/src/LogSelection.res.mjs +5 -6
- package/src/Main.res +4 -6
- package/src/Main.res.mjs +26 -15
- package/src/Persistence.res +7 -132
- package/src/Persistence.res.mjs +1 -102
- package/src/PgStorage.res +57 -40
- package/src/PgStorage.res.mjs +60 -34
- package/src/ReorgDetection.res +35 -58
- package/src/ReorgDetection.res.mjs +21 -29
- package/src/SimulateItems.res.mjs +21 -3
- package/src/Sink.res +2 -2
- package/src/Sink.res.mjs +1 -1
- package/src/TableIndices.res +9 -2
- package/src/TableIndices.res.mjs +7 -1
- package/src/TestIndexer.res +53 -60
- package/src/TestIndexer.res.mjs +77 -63
- package/src/TestIndexerProxyStorage.res +4 -14
- package/src/TestIndexerProxyStorage.res.mjs +1 -5
- package/src/UserContext.res +2 -4
- package/src/UserContext.res.mjs +4 -5
- package/src/Utils.res +0 -2
- package/src/Utils.res.mjs +0 -3
- package/src/bindings/ClickHouse.res +45 -38
- package/src/bindings/ClickHouse.res.mjs +16 -17
- package/src/bindings/Vitest.res +3 -0
- package/src/db/InternalTable.res +59 -18
- package/src/db/InternalTable.res.mjs +82 -51
- package/src/db/Table.res +9 -2
- package/src/db/Table.res.mjs +10 -7
- package/src/sources/EnvioApiClient.res +15 -0
- package/src/sources/EnvioApiClient.res.mjs +24 -0
- package/src/sources/EvmChain.res +32 -10
- package/src/sources/EvmChain.res.mjs +31 -5
- package/src/sources/HyperFuelSource.res +15 -58
- package/src/sources/HyperFuelSource.res.mjs +20 -39
- package/src/sources/HyperSync.res +54 -100
- package/src/sources/HyperSync.res.mjs +67 -96
- package/src/sources/HyperSync.resi +4 -22
- package/src/sources/HyperSyncClient.res +70 -247
- package/src/sources/HyperSyncClient.res.mjs +47 -46
- package/src/sources/HyperSyncSource.res +94 -166
- package/src/sources/HyperSyncSource.res.mjs +100 -127
- package/src/sources/RpcSource.res +43 -22
- package/src/sources/RpcSource.res.mjs +50 -35
- package/src/sources/SimulateSource.res +1 -7
- package/src/sources/SimulateSource.res.mjs +1 -7
- package/src/sources/Source.res +10 -1
- package/src/sources/Source.res.mjs +3 -0
- package/src/sources/SourceManager.res +177 -8
- package/src/sources/SourceManager.res.mjs +141 -3
- package/src/sources/SourceManager.resi +19 -0
- package/src/tui/Tui.res +44 -6
- package/src/tui/Tui.res.mjs +56 -8
- package/src/tui/components/TuiData.res +3 -0
- package/svm.schema.json +11 -4
- package/src/sources/HyperSyncJsonApi.res +0 -390
- package/src/sources/HyperSyncJsonApi.res.mjs +0 -237
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Utils from "./Utils.res.mjs";
|
|
4
|
-
import * as
|
|
5
|
-
import * as Belt_Array from "@rescript/runtime/lib/es6/Belt_Array.js";
|
|
4
|
+
import * as Internal from "./Internal.res.mjs";
|
|
6
5
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
7
6
|
import * as TableIndices from "./TableIndices.res.mjs";
|
|
8
7
|
import * as ErrorHandling from "./ErrorHandling.res.mjs";
|
|
@@ -11,44 +10,6 @@ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
|
11
10
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
12
11
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
13
12
|
|
|
14
|
-
function make(hash) {
|
|
15
|
-
return {
|
|
16
|
-
dict: {},
|
|
17
|
-
hash: hash
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function set(self, key, value) {
|
|
22
|
-
self.dict[self.hash(key)] = value;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function setByHash(self, hash, value) {
|
|
26
|
-
self.dict[hash] = value;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function hasByHash(self, hash) {
|
|
30
|
-
return Utils.Dict.has(self.dict, hash);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function getUnsafeByHash(self, hash) {
|
|
34
|
-
return self.dict[hash];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function get(self, key) {
|
|
38
|
-
return self.dict[self.hash(key)];
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function values(self) {
|
|
42
|
-
return Object.values(self.dict);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function clone(self) {
|
|
46
|
-
return {
|
|
47
|
-
dict: Lodash.cloneDeep(self.dict),
|
|
48
|
-
hash: self.hash
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
13
|
let UnexpectedIdNotDefinedOnEntity = /* @__PURE__ */Primitive_exceptions.create("InMemoryTable.Entity.UnexpectedIdNotDefinedOnEntity");
|
|
53
14
|
|
|
54
15
|
function getEntityIdUnsafe(entity) {
|
|
@@ -62,171 +23,195 @@ function getEntityIdUnsafe(entity) {
|
|
|
62
23
|
}
|
|
63
24
|
}
|
|
64
25
|
|
|
26
|
+
function getOrCreateEntityIndices(self, entityId) {
|
|
27
|
+
let s = self.indicesByEntityId[entityId];
|
|
28
|
+
if (s !== undefined) {
|
|
29
|
+
return Primitive_option.valFromOption(s);
|
|
30
|
+
}
|
|
31
|
+
let s$1 = new Set();
|
|
32
|
+
self.indicesByEntityId[entityId] = s$1;
|
|
33
|
+
return s$1;
|
|
34
|
+
}
|
|
35
|
+
|
|
65
36
|
function makeIndicesSerializedToValue(index, relatedEntityIdsOpt) {
|
|
66
37
|
let relatedEntityIds = relatedEntityIdsOpt !== undefined ? Primitive_option.valFromOption(relatedEntityIdsOpt) : new Set();
|
|
67
|
-
let
|
|
68
|
-
|
|
69
|
-
let empty = {
|
|
70
|
-
dict: empty_dict,
|
|
71
|
-
hash: empty_hash
|
|
72
|
-
};
|
|
73
|
-
set(empty, index, [
|
|
38
|
+
let empty = {};
|
|
39
|
+
empty[TableIndices.Index.toString(index)] = [
|
|
74
40
|
index,
|
|
75
41
|
relatedEntityIds
|
|
76
|
-
]
|
|
42
|
+
];
|
|
77
43
|
return empty;
|
|
78
44
|
}
|
|
79
45
|
|
|
80
|
-
function make
|
|
46
|
+
function make() {
|
|
81
47
|
return {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
},
|
|
86
|
-
fieldNameIndices: {
|
|
87
|
-
dict: {},
|
|
88
|
-
hash: TableIndices.Index.getFieldName
|
|
89
|
-
}
|
|
48
|
+
latestEntityChangeById: {},
|
|
49
|
+
changesCount: 0,
|
|
50
|
+
prevEntityChanges: [],
|
|
51
|
+
indicesByEntityId: {},
|
|
52
|
+
fieldNameIndices: {}
|
|
90
53
|
};
|
|
91
54
|
}
|
|
92
55
|
|
|
93
|
-
function
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
56
|
+
function resetButKeepLatestChanges(self) {
|
|
57
|
+
let init = {
|
|
58
|
+
latestEntityChangeById: {},
|
|
59
|
+
changesCount: 0,
|
|
60
|
+
prevEntityChanges: [],
|
|
61
|
+
indicesByEntityId: {},
|
|
62
|
+
fieldNameIndices: {}
|
|
63
|
+
};
|
|
64
|
+
return {
|
|
65
|
+
latestEntityChangeById: self.latestEntityChangeById,
|
|
66
|
+
changesCount: self.changesCount,
|
|
67
|
+
prevEntityChanges: init.prevEntityChanges,
|
|
68
|
+
indicesByEntityId: init.indicesByEntityId,
|
|
69
|
+
fieldNameIndices: init.fieldNameIndices
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function resetButKeepLoadedFromDbChanges(self) {
|
|
74
|
+
let latestEntityChangeById = {};
|
|
75
|
+
let keptCount = {
|
|
76
|
+
contents: 0
|
|
77
|
+
};
|
|
78
|
+
Utils.Dict.forEachWithKey(self.latestEntityChangeById, (change, key) => {
|
|
79
|
+
if (change.checkpointId === Internal.loadedFromDbCheckpointId) {
|
|
80
|
+
latestEntityChangeById[key] = change;
|
|
81
|
+
keptCount.contents = keptCount.contents + 1;
|
|
99
82
|
return;
|
|
100
83
|
}
|
|
101
84
|
});
|
|
102
|
-
|
|
103
|
-
|
|
85
|
+
let init = {
|
|
86
|
+
latestEntityChangeById: {},
|
|
87
|
+
changesCount: 0,
|
|
88
|
+
prevEntityChanges: [],
|
|
89
|
+
indicesByEntityId: {},
|
|
90
|
+
fieldNameIndices: {}
|
|
91
|
+
};
|
|
92
|
+
return {
|
|
93
|
+
latestEntityChangeById: latestEntityChangeById,
|
|
94
|
+
changesCount: keptCount.contents,
|
|
95
|
+
prevEntityChanges: init.prevEntityChanges,
|
|
96
|
+
indicesByEntityId: init.indicesByEntityId,
|
|
97
|
+
fieldNameIndices: init.fieldNameIndices
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function updateIndices(self, entity) {
|
|
102
|
+
let entityId = getEntityIdUnsafe(entity);
|
|
103
|
+
let entityIndices = self.indicesByEntityId[entityId];
|
|
104
|
+
if (entityIndices !== undefined) {
|
|
105
|
+
let entityIndices$1 = Primitive_option.valFromOption(entityIndices);
|
|
106
|
+
entityIndices$1.forEach(index => {
|
|
107
|
+
let fieldName = TableIndices.Index.getFieldName(index);
|
|
108
|
+
let fieldValue = entity[fieldName];
|
|
109
|
+
if (!TableIndices.Index.evaluate(index, fieldName, fieldValue)) {
|
|
110
|
+
entityIndices$1.delete(index);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
Utils.Dict.forEachWithKey(self.fieldNameIndices, (indices, fieldName) => {
|
|
104
116
|
let fieldValue = entity[fieldName];
|
|
105
|
-
|
|
117
|
+
Utils.Dict.forEach(indices, param => {
|
|
106
118
|
let relatedEntityIds = param[1];
|
|
107
119
|
let index = param[0];
|
|
108
120
|
if (TableIndices.Index.evaluate(index, fieldName, fieldValue)) {
|
|
109
|
-
relatedEntityIds.add(
|
|
110
|
-
|
|
121
|
+
relatedEntityIds.add(entityId);
|
|
122
|
+
getOrCreateEntityIndices(self, entityId).add(index);
|
|
111
123
|
} else {
|
|
112
|
-
relatedEntityIds.delete(
|
|
124
|
+
relatedEntityIds.delete(entityId);
|
|
113
125
|
}
|
|
114
126
|
});
|
|
115
127
|
});
|
|
116
128
|
}
|
|
117
129
|
|
|
118
|
-
function deleteEntityFromIndices(self, entityId
|
|
119
|
-
entityIndices
|
|
120
|
-
|
|
130
|
+
function deleteEntityFromIndices(self, entityId) {
|
|
131
|
+
let entityIndices = self.indicesByEntityId[entityId];
|
|
132
|
+
if (entityIndices === undefined) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
let entityIndices$1 = Primitive_option.valFromOption(entityIndices);
|
|
136
|
+
entityIndices$1.forEach(index => {
|
|
137
|
+
let match = Stdlib_Option.flatMap(self.fieldNameIndices[TableIndices.Index.getFieldName(index)], indices => indices[TableIndices.Index.toString(index)]);
|
|
121
138
|
if (match !== undefined) {
|
|
122
139
|
match[1].delete(entityId);
|
|
123
140
|
}
|
|
124
|
-
entityIndices.delete(index);
|
|
141
|
+
entityIndices$1.delete(index);
|
|
125
142
|
});
|
|
126
143
|
}
|
|
127
144
|
|
|
128
|
-
function
|
|
129
|
-
let
|
|
130
|
-
let
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
updateIndices(inMemTable, Primitive_option.valFromOption(entity), entityIndices);
|
|
137
|
-
}
|
|
138
|
-
inMemTable.table.dict[inMemTable.table.hash(key)] = {
|
|
139
|
-
latest: entity,
|
|
140
|
-
status: "Loaded",
|
|
141
|
-
entityIndices: entityIndices
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function set$1(inMemTable, change, shouldSaveHistory, containsRollbackDiffChangeOpt) {
|
|
146
|
-
let containsRollbackDiffChange = containsRollbackDiffChangeOpt !== undefined ? containsRollbackDiffChangeOpt : false;
|
|
147
|
-
let latest;
|
|
148
|
-
latest = change.type === "SET" ? Primitive_option.some(change.entity) : undefined;
|
|
149
|
-
let match = get(inMemTable.table, change.entityId);
|
|
150
|
-
let updatedEntityRecord;
|
|
151
|
-
if (match !== undefined) {
|
|
152
|
-
let previous_values = match.status;
|
|
153
|
-
if (previous_values === "Loaded") {
|
|
154
|
-
updatedEntityRecord = {
|
|
155
|
-
latest: latest,
|
|
156
|
-
status: {
|
|
157
|
-
latestChange: change,
|
|
158
|
-
history: shouldSaveHistory ? [change] : Utils.$$Array.immutableEmpty,
|
|
159
|
-
containsRollbackDiffChange: containsRollbackDiffChange
|
|
160
|
-
},
|
|
161
|
-
entityIndices: match.entityIndices
|
|
162
|
-
};
|
|
163
|
-
} else {
|
|
164
|
-
let newStatus = {
|
|
165
|
-
latestChange: change,
|
|
166
|
-
history: shouldSaveHistory ? (
|
|
167
|
-
previous_values.latestChange.checkpointId === change.checkpointId ? Utils.$$Array.setIndexImmutable(previous_values.history, previous_values.history.length - 1 | 0, change) : Belt_Array.concatMany([
|
|
168
|
-
previous_values.history,
|
|
169
|
-
[change]
|
|
170
|
-
])
|
|
171
|
-
) : previous_values.history,
|
|
172
|
-
containsRollbackDiffChange: previous_values.containsRollbackDiffChange
|
|
173
|
-
};
|
|
174
|
-
updatedEntityRecord = {
|
|
175
|
-
latest: latest,
|
|
176
|
-
status: newStatus,
|
|
177
|
-
entityIndices: match.entityIndices
|
|
178
|
-
};
|
|
145
|
+
function set(inMemTable, committedCheckpointId, change) {
|
|
146
|
+
let entityId = change.entityId;
|
|
147
|
+
let prev = inMemTable.latestEntityChangeById[entityId];
|
|
148
|
+
if (prev !== undefined) {
|
|
149
|
+
let prevCheckpointId = prev.checkpointId;
|
|
150
|
+
if (prevCheckpointId > committedCheckpointId && prevCheckpointId < change.checkpointId) {
|
|
151
|
+
inMemTable.prevEntityChanges.push(prev);
|
|
152
|
+
inMemTable.changesCount = inMemTable.changesCount + 1;
|
|
179
153
|
}
|
|
180
154
|
} else {
|
|
181
|
-
|
|
182
|
-
latest: latest,
|
|
183
|
-
status: {
|
|
184
|
-
latestChange: change,
|
|
185
|
-
history: shouldSaveHistory ? [change] : Utils.$$Array.immutableEmpty,
|
|
186
|
-
containsRollbackDiffChange: containsRollbackDiffChange
|
|
187
|
-
},
|
|
188
|
-
entityIndices: new Set()
|
|
189
|
-
};
|
|
155
|
+
inMemTable.changesCount = inMemTable.changesCount + 1;
|
|
190
156
|
}
|
|
191
157
|
if (change.type === "SET") {
|
|
192
|
-
updateIndices(inMemTable, change.entity
|
|
158
|
+
updateIndices(inMemTable, change.entity);
|
|
193
159
|
} else {
|
|
194
|
-
deleteEntityFromIndices(inMemTable, change.entityId
|
|
160
|
+
deleteEntityFromIndices(inMemTable, change.entityId);
|
|
195
161
|
}
|
|
196
|
-
|
|
162
|
+
inMemTable.latestEntityChangeById[entityId] = change;
|
|
197
163
|
}
|
|
198
164
|
|
|
199
|
-
function
|
|
200
|
-
|
|
165
|
+
function initValue(inMemTable, committedCheckpointId, key, entity) {
|
|
166
|
+
if (!Stdlib_Option.isNone(inMemTable.latestEntityChangeById[key])) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
let change = entity !== undefined ? ({
|
|
170
|
+
type: "SET",
|
|
171
|
+
entityId: key,
|
|
172
|
+
entity: entity,
|
|
173
|
+
checkpointId: Internal.loadedFromDbCheckpointId
|
|
174
|
+
}) : ({
|
|
175
|
+
type: "DELETE",
|
|
176
|
+
entityId: key,
|
|
177
|
+
checkpointId: Internal.loadedFromDbCheckpointId
|
|
178
|
+
});
|
|
179
|
+
set(inMemTable, committedCheckpointId, change);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function mapChangeToEntity(change) {
|
|
183
|
+
if (change.type === "SET") {
|
|
184
|
+
return change.entity;
|
|
185
|
+
}
|
|
201
186
|
}
|
|
202
187
|
|
|
203
188
|
function getUnsafe(inMemTable) {
|
|
204
|
-
return key => inMemTable.
|
|
189
|
+
return key => mapChangeToEntity(inMemTable.latestEntityChangeById[key]);
|
|
205
190
|
}
|
|
206
191
|
|
|
207
192
|
function hasIndex(inMemTable, fieldName, operator) {
|
|
208
193
|
return fieldValueHash => {
|
|
209
|
-
let indicesSerializedToValue = inMemTable.fieldNameIndices
|
|
194
|
+
let indicesSerializedToValue = inMemTable.fieldNameIndices[fieldName];
|
|
210
195
|
if (indicesSerializedToValue === undefined) {
|
|
211
196
|
return false;
|
|
212
197
|
}
|
|
213
|
-
let key = fieldName
|
|
214
|
-
return indicesSerializedToValue
|
|
198
|
+
let key = TableIndices.Index.toStringByParts(fieldName, operator, fieldValueHash);
|
|
199
|
+
return indicesSerializedToValue[key] !== undefined;
|
|
215
200
|
};
|
|
216
201
|
}
|
|
217
202
|
|
|
218
203
|
function getUnsafeOnIndex(inMemTable, fieldName, operator) {
|
|
219
204
|
let getEntity = getUnsafe(inMemTable);
|
|
220
205
|
return fieldValueHash => {
|
|
221
|
-
let indicesSerializedToValue = inMemTable.fieldNameIndices
|
|
206
|
+
let indicesSerializedToValue = inMemTable.fieldNameIndices[fieldName];
|
|
222
207
|
if (indicesSerializedToValue === undefined) {
|
|
223
208
|
return Stdlib_JsError.throwWithMessage(`Unexpected error. Must have an index on field ` + fieldName);
|
|
224
209
|
}
|
|
225
|
-
let key = fieldName
|
|
226
|
-
let match = indicesSerializedToValue
|
|
210
|
+
let key = TableIndices.Index.toStringByParts(fieldName, operator, fieldValueHash);
|
|
211
|
+
let match = indicesSerializedToValue[key];
|
|
227
212
|
if (match !== undefined) {
|
|
228
213
|
return Stdlib_Array.filterMap(Array.from(match[1]), entityId => {
|
|
229
|
-
if (
|
|
214
|
+
if (entityId in inMemTable.latestEntityChangeById) {
|
|
230
215
|
return getEntity(entityId);
|
|
231
216
|
}
|
|
232
217
|
});
|
|
@@ -239,111 +224,55 @@ function getUnsafeOnIndex(inMemTable, fieldName, operator) {
|
|
|
239
224
|
function addEmptyIndex(inMemTable, index) {
|
|
240
225
|
let fieldName = TableIndices.Index.getFieldName(index);
|
|
241
226
|
let relatedEntityIds = new Set();
|
|
242
|
-
|
|
243
|
-
let entity =
|
|
227
|
+
Utils.Dict.forEach(inMemTable.latestEntityChangeById, change => {
|
|
228
|
+
let entity = mapChangeToEntity(change);
|
|
244
229
|
if (entity === undefined) {
|
|
245
230
|
return;
|
|
246
231
|
}
|
|
247
|
-
let
|
|
248
|
-
|
|
249
|
-
if (TableIndices.Index.evaluate(index, fieldName, fieldValue)) {
|
|
250
|
-
row.entityIndices.add(index);
|
|
251
|
-
relatedEntityIds.add(getEntityIdUnsafe(entity$1));
|
|
232
|
+
let fieldValue = entity[fieldName];
|
|
233
|
+
if (!TableIndices.Index.evaluate(index, fieldName, fieldValue)) {
|
|
252
234
|
return;
|
|
253
235
|
}
|
|
236
|
+
let entityId = getEntityIdUnsafe(entity);
|
|
237
|
+
getOrCreateEntityIndices(inMemTable, entityId).add(index);
|
|
238
|
+
relatedEntityIds.add(entityId);
|
|
254
239
|
});
|
|
255
|
-
let indicesSerializedToValue =
|
|
256
|
-
if (indicesSerializedToValue
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
let match = get(indicesSerializedToValue, index);
|
|
260
|
-
if (match !== undefined) {
|
|
261
|
-
return;
|
|
262
|
-
} else {
|
|
263
|
-
return set(indicesSerializedToValue, index, [
|
|
264
|
-
index,
|
|
265
|
-
relatedEntityIds
|
|
266
|
-
]);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
function addIdToIndex(inMemTable, index, entityId) {
|
|
271
|
-
let indicesSerializedToValue = get(inMemTable.fieldNameIndices, index);
|
|
272
|
-
if (indicesSerializedToValue === undefined) {
|
|
273
|
-
return set(inMemTable.fieldNameIndices, index, makeIndicesSerializedToValue(index, Primitive_option.some(new Set().add(entityId))));
|
|
274
|
-
}
|
|
275
|
-
let match = get(indicesSerializedToValue, index);
|
|
276
|
-
if (match !== undefined) {
|
|
277
|
-
match[1].add(entityId);
|
|
278
|
-
return;
|
|
279
|
-
} else {
|
|
280
|
-
return set(indicesSerializedToValue, index, [
|
|
281
|
-
index,
|
|
282
|
-
new Set().add(entityId)
|
|
283
|
-
]);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
function updates(inMemTable) {
|
|
288
|
-
return Stdlib_Array.filterMap(Object.values(inMemTable.table.dict), v => {
|
|
289
|
-
let update = v.status;
|
|
290
|
-
if (update === "Loaded") {
|
|
240
|
+
let indicesSerializedToValue = inMemTable.fieldNameIndices[fieldName];
|
|
241
|
+
if (indicesSerializedToValue !== undefined) {
|
|
242
|
+
let match = indicesSerializedToValue[TableIndices.Index.toString(index)];
|
|
243
|
+
if (match !== undefined) {
|
|
291
244
|
return;
|
|
292
245
|
} else {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
function values$1(inMemTable) {
|
|
299
|
-
return Stdlib_Array.filterMap(Object.values(inMemTable.table.dict), rowToEntity);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
function clone$1(param) {
|
|
303
|
-
let fieldNameIndices = param.fieldNameIndices;
|
|
304
|
-
return {
|
|
305
|
-
table: clone(param.table),
|
|
306
|
-
fieldNameIndices: {
|
|
307
|
-
dict: Object.fromEntries(Object.entries(fieldNameIndices.dict).map(param => [
|
|
308
|
-
param[0],
|
|
309
|
-
clone(param[1])
|
|
310
|
-
])),
|
|
311
|
-
hash: fieldNameIndices.hash
|
|
246
|
+
indicesSerializedToValue[TableIndices.Index.toString(index)] = [
|
|
247
|
+
index,
|
|
248
|
+
relatedEntityIds
|
|
249
|
+
];
|
|
250
|
+
return;
|
|
312
251
|
}
|
|
313
|
-
}
|
|
252
|
+
}
|
|
253
|
+
inMemTable.fieldNameIndices[fieldName] = makeIndicesSerializedToValue(index, Primitive_option.some(relatedEntityIds));
|
|
314
254
|
}
|
|
315
255
|
|
|
316
256
|
let Entity = {
|
|
317
257
|
UnexpectedIdNotDefinedOnEntity: UnexpectedIdNotDefinedOnEntity,
|
|
318
258
|
getEntityIdUnsafe: getEntityIdUnsafe,
|
|
259
|
+
getOrCreateEntityIndices: getOrCreateEntityIndices,
|
|
319
260
|
makeIndicesSerializedToValue: makeIndicesSerializedToValue,
|
|
320
|
-
make: make
|
|
261
|
+
make: make,
|
|
262
|
+
resetButKeepLatestChanges: resetButKeepLatestChanges,
|
|
263
|
+
resetButKeepLoadedFromDbChanges: resetButKeepLoadedFromDbChanges,
|
|
321
264
|
updateIndices: updateIndices,
|
|
322
265
|
deleteEntityFromIndices: deleteEntityFromIndices,
|
|
266
|
+
set: set,
|
|
323
267
|
initValue: initValue,
|
|
324
|
-
|
|
325
|
-
set: set$1,
|
|
326
|
-
rowToEntity: rowToEntity,
|
|
327
|
-
getRow: get,
|
|
268
|
+
mapChangeToEntity: mapChangeToEntity,
|
|
328
269
|
getUnsafe: getUnsafe,
|
|
329
270
|
hasIndex: hasIndex,
|
|
330
271
|
getUnsafeOnIndex: getUnsafeOnIndex,
|
|
331
|
-
addEmptyIndex: addEmptyIndex
|
|
332
|
-
addIdToIndex: addIdToIndex,
|
|
333
|
-
updates: updates,
|
|
334
|
-
values: values$1,
|
|
335
|
-
clone: clone$1
|
|
272
|
+
addEmptyIndex: addEmptyIndex
|
|
336
273
|
};
|
|
337
274
|
|
|
338
275
|
export {
|
|
339
|
-
make,
|
|
340
|
-
set,
|
|
341
|
-
setByHash,
|
|
342
|
-
hasByHash,
|
|
343
|
-
getUnsafeByHash,
|
|
344
|
-
get,
|
|
345
|
-
values,
|
|
346
|
-
clone,
|
|
347
276
|
Entity,
|
|
348
277
|
}
|
|
349
278
|
/* Utils Not a pure module */
|
package/src/Internal.res
CHANGED
|
@@ -330,17 +330,11 @@ type genericHandlerWithLoader<'loader, 'handler, 'where> = {
|
|
|
330
330
|
// param (or any nested field) is a Solidity struct. `name` is always non-empty —
|
|
331
331
|
// the CLI fills in `"0"`, `"1"`, ... for anonymous components in mixed-name
|
|
332
332
|
// tuples — so the runtime can always rebuild a keyed object.
|
|
333
|
-
type rec
|
|
334
|
-
name: string,
|
|
335
|
-
abiType: string,
|
|
336
|
-
components?: array<eventParamComponent>,
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
type eventParam = {
|
|
333
|
+
type rec paramMeta = {
|
|
340
334
|
name: string,
|
|
341
335
|
abiType: string,
|
|
342
336
|
indexed: bool,
|
|
343
|
-
components?: array<
|
|
337
|
+
components?: array<paramMeta>,
|
|
344
338
|
}
|
|
345
339
|
|
|
346
340
|
// This is private so it's not manually constructed internally
|
|
@@ -398,15 +392,11 @@ type eventFilters =
|
|
|
398
392
|
type evmEventConfig = {
|
|
399
393
|
...eventConfig,
|
|
400
394
|
getEventFiltersOrThrow: ChainMap.Chain.t => eventFilters,
|
|
401
|
-
convertHyperSyncEventArgs: HyperSyncClient.Decoder.decodedEvent => eventParams,
|
|
402
395
|
selectedBlockFields: Utils.Set.t<evmBlockField>,
|
|
403
396
|
selectedTransactionFields: Utils.Set.t<evmTransactionField>,
|
|
404
|
-
// Retained so `HandlerLoader.applyRegistrations` can re-run
|
|
405
|
-
// `LogSelection.parseEventFiltersOrThrow` after handler modules register
|
|
406
|
-
// with a `where:` filter. Only indexed params are kept — they're all the
|
|
407
|
-
// filter parser needs for topic-getter construction + key validation.
|
|
408
397
|
sighash: string,
|
|
409
|
-
|
|
398
|
+
topicCount: int,
|
|
399
|
+
paramsMetadata: array<paramMeta>,
|
|
410
400
|
}
|
|
411
401
|
|
|
412
402
|
// Shared formula for `eventConfig.dependsOnAddresses`. Kept here so
|
|
@@ -520,8 +510,6 @@ let fuelTransferParamsSchema = S.schema(s => {
|
|
|
520
510
|
amount: s.matches(Utils.BigInt.schema),
|
|
521
511
|
})
|
|
522
512
|
|
|
523
|
-
type multichain = | @as("ordered") Ordered | @as("unordered") Unordered
|
|
524
|
-
|
|
525
513
|
type entity = private {id: string}
|
|
526
514
|
|
|
527
515
|
// Per-entity storage resolved at parse time against the global storage
|
|
@@ -595,6 +583,12 @@ type noOnEventWhere
|
|
|
595
583
|
|
|
596
584
|
type checkpointId = bigint
|
|
597
585
|
|
|
586
|
+
// Assigned to changes loaded from the db, which never become history.
|
|
587
|
+
let loadedFromDbCheckpointId: checkpointId = 0n
|
|
588
|
+
|
|
589
|
+
// Committed checkpoint before any batch is written.
|
|
590
|
+
let initialCheckpointId: checkpointId = 0n
|
|
591
|
+
|
|
598
592
|
type reorgCheckpoint = {
|
|
599
593
|
@as("id")
|
|
600
594
|
checkpointId: bigint,
|
|
@@ -605,21 +599,3 @@ type reorgCheckpoint = {
|
|
|
605
599
|
@as("block_hash")
|
|
606
600
|
blockHash: string,
|
|
607
601
|
}
|
|
608
|
-
|
|
609
|
-
type inMemoryStoreEntityUpdate<'entity> = {
|
|
610
|
-
latestChange: Change.t<'entity>,
|
|
611
|
-
history: array<Change.t<'entity>>,
|
|
612
|
-
// In the event of a rollback, some entity updates may have been
|
|
613
|
-
// been affected by a rollback diff. If there was no rollback diff
|
|
614
|
-
// this will always be false.
|
|
615
|
-
// If there was a rollback diff, this will be false in the case of a
|
|
616
|
-
// new entity update (where entity affected is not present in the diff) b
|
|
617
|
-
// but true if the update is related to an entity that is
|
|
618
|
-
// currently present in the diff
|
|
619
|
-
containsRollbackDiffChange: bool,
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
@unboxed
|
|
623
|
-
type inMemoryStoreEntityStatus<'entity> =
|
|
624
|
-
| Updated(inMemoryStoreEntityUpdate<'entity>)
|
|
625
|
-
| Loaded // This means there is no change from the db.
|
package/src/Internal.res.mjs
CHANGED
|
@@ -151,11 +151,15 @@ let effectCacheItemRowsSchema = S$RescriptSchema.array(S$RescriptSchema.schema(s
|
|
|
151
151
|
|
|
152
152
|
function makeCacheTable(effectName) {
|
|
153
153
|
return Table.mkTable(cacheTablePrefix + effectName, undefined, [
|
|
154
|
-
Table.mkField("id", "String", S$RescriptSchema.string, undefined, undefined, undefined, true, undefined, undefined),
|
|
155
|
-
Table.mkField("output", "Json", cacheOutputSchema, undefined, undefined, true, undefined, undefined, undefined)
|
|
156
|
-
]);
|
|
154
|
+
Table.mkField("id", "String", S$RescriptSchema.string, undefined, undefined, undefined, true, undefined, undefined, undefined),
|
|
155
|
+
Table.mkField("output", "Json", cacheOutputSchema, undefined, undefined, true, undefined, undefined, undefined, undefined)
|
|
156
|
+
], undefined);
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
let loadedFromDbCheckpointId = 0n;
|
|
160
|
+
|
|
161
|
+
let initialCheckpointId = 0n;
|
|
162
|
+
|
|
159
163
|
export {
|
|
160
164
|
allEvmBlockFields,
|
|
161
165
|
evmBlockFieldSchema,
|
|
@@ -171,5 +175,7 @@ export {
|
|
|
171
175
|
cacheOutputSchema,
|
|
172
176
|
effectCacheItemRowsSchema,
|
|
173
177
|
makeCacheTable,
|
|
178
|
+
loadedFromDbCheckpointId,
|
|
179
|
+
initialCheckpointId,
|
|
174
180
|
}
|
|
175
181
|
/* evmBlockFieldSchema Not a pure module */
|
package/src/LoadLayer.res
CHANGED
|
@@ -36,7 +36,7 @@ let loadById = (
|
|
|
36
36
|
}
|
|
37
37
|
idsToLoad->Array.forEach(entityId => {
|
|
38
38
|
inMemTable->InMemoryTable.Entity.initValue(
|
|
39
|
-
~
|
|
39
|
+
~committedCheckpointId=inMemoryStore.committedCheckpointId,
|
|
40
40
|
~key=entityId,
|
|
41
41
|
~entity=entitiesMap->Utils.Dict.dangerouslyGetNonOption(entityId),
|
|
42
42
|
)
|
|
@@ -56,7 +56,7 @@ let loadById = (
|
|
|
56
56
|
~shouldGroup,
|
|
57
57
|
~hasher=LoadManager.noopHasher,
|
|
58
58
|
~getUnsafeInMemory=inMemTable->InMemoryTable.Entity.getUnsafe,
|
|
59
|
-
~hasInMemory=hash => inMemTable.
|
|
59
|
+
~hasInMemory=hash => inMemTable.latestEntityChangeById->Dict.has(hash),
|
|
60
60
|
~input=entityId,
|
|
61
61
|
)
|
|
62
62
|
}
|
|
@@ -253,7 +253,7 @@ let loadEffect = (
|
|
|
253
253
|
|
|
254
254
|
if (
|
|
255
255
|
switch persistence.storageStatus {
|
|
256
|
-
| Ready({cache}) => cache->
|
|
256
|
+
| Ready({cache}) => cache->Dict.has(effectName)
|
|
257
257
|
| _ => false
|
|
258
258
|
}
|
|
259
259
|
) {
|
|
@@ -335,7 +335,7 @@ let loadEffect = (
|
|
|
335
335
|
~shouldGroup,
|
|
336
336
|
~hasher=args => args.cacheKey,
|
|
337
337
|
~getUnsafeInMemory=hash => inMemTable.dict->Dict.getUnsafe(hash),
|
|
338
|
-
~hasInMemory=hash => inMemTable.dict->
|
|
338
|
+
~hasInMemory=hash => inMemTable.dict->Dict.has(hash),
|
|
339
339
|
~input=effectArgs,
|
|
340
340
|
)
|
|
341
341
|
}
|
|
@@ -397,7 +397,7 @@ let loadByField = (
|
|
|
397
397
|
|
|
398
398
|
entities->Array.forEach(entity => {
|
|
399
399
|
inMemTable->InMemoryTable.Entity.initValue(
|
|
400
|
-
~
|
|
400
|
+
~committedCheckpointId=inMemoryStore.committedCheckpointId,
|
|
401
401
|
~key=entity.id,
|
|
402
402
|
~entity=Some(entity),
|
|
403
403
|
)
|
package/src/LoadLayer.res.mjs
CHANGED
|
@@ -37,10 +37,10 @@ function loadById(loadManager, persistence, entityConfig, inMemoryStore, shouldG
|
|
|
37
37
|
let entity = dbEntities[idx];
|
|
38
38
|
entitiesMap[entity.id] = entity;
|
|
39
39
|
}
|
|
40
|
-
idsToLoad.forEach(entityId => InMemoryTable.Entity.initValue(inMemTable, entityId, entitiesMap[entityId]
|
|
40
|
+
idsToLoad.forEach(entityId => InMemoryTable.Entity.initValue(inMemTable, inMemoryStore.committedCheckpointId, entityId, entitiesMap[entityId]));
|
|
41
41
|
return Prometheus.StorageLoad.endOperation(timerRef, storage.name, key, idsToLoad.length, dbEntities.length);
|
|
42
42
|
};
|
|
43
|
-
return LoadManager.call(loadManager, entityId, key, load, LoadManager.noopHasher, shouldGroup, hash =>
|
|
43
|
+
return LoadManager.call(loadManager, entityId, key, load, LoadManager.noopHasher, shouldGroup, hash => hash in inMemTable.latestEntityChangeById, InMemoryTable.Entity.getUnsafe(inMemTable));
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
function callEffect(effect, arg, inMemTable, timerRef, onError) {
|
|
@@ -137,7 +137,7 @@ function loadEffect(loadManager, persistence, effect, effectArgs, inMemoryStore,
|
|
|
137
137
|
let idsFromCache = new Set();
|
|
138
138
|
let match = persistence.storageStatus;
|
|
139
139
|
let tmp;
|
|
140
|
-
tmp = typeof match !== "object" || match.TAG === "Initializing" ? false :
|
|
140
|
+
tmp = typeof match !== "object" || match.TAG === "Initializing" ? false : effectName in match._0.cache;
|
|
141
141
|
if (tmp) {
|
|
142
142
|
let storage = Persistence.getInitializedStorageOrThrow(persistence);
|
|
143
143
|
let timerRef = Prometheus.StorageLoad.startOperation(storage.name, key);
|
|
@@ -193,7 +193,7 @@ function loadEffect(loadManager, persistence, effect, effectArgs, inMemoryStore,
|
|
|
193
193
|
return await executeWithRateLimit(effect, argsToCall, inMemTable, onError, false);
|
|
194
194
|
}
|
|
195
195
|
};
|
|
196
|
-
return LoadManager.call(loadManager, effectArgs, key, load, args => args.cacheKey, shouldGroup, hash =>
|
|
196
|
+
return LoadManager.call(loadManager, effectArgs, key, load, args => args.cacheKey, shouldGroup, hash => hash in inMemTable.dict, hash => inMemTable.dict[hash]);
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
function loadByField(loadManager, persistence, operator, entityConfig, inMemoryStore, fieldName, fieldValueSchema, shouldGroup, item, fieldValue) {
|
|
@@ -238,7 +238,7 @@ function loadByField(loadManager, persistence, operator, entityConfig, inMemoryS
|
|
|
238
238
|
break;
|
|
239
239
|
}
|
|
240
240
|
let entities = await storage.loadByFieldOrThrow(TableIndices.Index.getFieldName(index), fieldValueSchema, index.fieldValue, tmp, entityConfig.table, entityConfig.rowsSchema);
|
|
241
|
-
entities.forEach(entity => InMemoryTable.Entity.initValue(inMemTable, entity.id, entity
|
|
241
|
+
entities.forEach(entity => InMemoryTable.Entity.initValue(inMemTable, inMemoryStore.committedCheckpointId, entity.id, entity));
|
|
242
242
|
size.contents = size.contents + entities.length | 0;
|
|
243
243
|
return;
|
|
244
244
|
} catch (raw_exn) {
|