envio 3.1.1 → 3.2.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/evm.schema.json +83 -11
- package/fuel.schema.json +83 -11
- package/index.d.ts +184 -3
- package/package.json +6 -6
- package/src/Batch.res +2 -2
- package/src/ChainFetcher.res +27 -3
- package/src/ChainFetcher.res.mjs +17 -3
- package/src/ChainManager.res +163 -0
- package/src/ChainManager.res.mjs +136 -0
- package/src/Config.res +213 -30
- package/src/Config.res.mjs +102 -41
- package/src/Core.res +16 -10
- package/src/Ecosystem.res +0 -3
- package/src/Env.res +2 -2
- package/src/Env.res.mjs +2 -2
- package/src/Envio.res +101 -2
- package/src/Envio.res.mjs +2 -3
- package/src/EventConfigBuilder.res +52 -0
- package/src/EventConfigBuilder.res.mjs +32 -0
- package/src/EventUtils.res +2 -2
- package/src/FetchState.res +126 -71
- package/src/FetchState.res.mjs +73 -51
- package/src/GlobalState.res +219 -363
- package/src/GlobalState.res.mjs +314 -491
- package/src/GlobalStateManager.res +49 -59
- package/src/GlobalStateManager.res.mjs +5 -4
- package/src/GlobalStateManager.resi +1 -1
- package/src/HandlerLoader.res +12 -1
- package/src/HandlerLoader.res.mjs +6 -1
- package/src/HandlerRegister.res +9 -9
- package/src/HandlerRegister.res.mjs +9 -9
- package/src/Hasura.res +102 -32
- package/src/Hasura.res.mjs +88 -34
- package/src/InMemoryStore.res +10 -1
- package/src/InMemoryStore.res.mjs +4 -1
- package/src/InMemoryTable.res +83 -136
- package/src/InMemoryTable.res.mjs +57 -86
- package/src/Internal.res +54 -5
- package/src/Internal.res.mjs +2 -8
- package/src/LazyLoader.res +2 -2
- package/src/LazyLoader.res.mjs +3 -3
- package/src/LoadLayer.res +47 -60
- package/src/LoadLayer.res.mjs +28 -50
- package/src/LoadLayer.resi +2 -5
- package/src/LogSelection.res +4 -4
- package/src/LogSelection.res.mjs +5 -7
- package/src/Logging.res +1 -1
- package/src/Main.res +61 -2
- package/src/Main.res.mjs +37 -1
- package/src/Persistence.res +3 -16
- package/src/PgStorage.res +125 -114
- package/src/PgStorage.res.mjs +112 -95
- package/src/Ports.res +5 -0
- package/src/Ports.res.mjs +9 -0
- package/src/Prometheus.res +3 -3
- package/src/Prometheus.res.mjs +4 -4
- package/src/ReorgDetection.res +4 -4
- package/src/ReorgDetection.res.mjs +4 -5
- package/src/SafeCheckpointTracking.res +16 -16
- package/src/SafeCheckpointTracking.res.mjs +2 -2
- package/src/SimulateItems.res +10 -14
- package/src/SimulateItems.res.mjs +5 -2
- package/src/Sink.res +1 -1
- package/src/Sink.res.mjs +1 -2
- package/src/SvmTypes.res +9 -0
- package/src/SvmTypes.res.mjs +14 -0
- package/src/TestIndexer.res +17 -57
- package/src/TestIndexer.res.mjs +14 -48
- package/src/TestIndexerProxyStorage.res +23 -23
- package/src/TestIndexerProxyStorage.res.mjs +12 -15
- package/src/Throttler.res +2 -2
- package/src/Time.res +2 -2
- package/src/Time.res.mjs +2 -2
- package/src/UserContext.res +19 -118
- package/src/UserContext.res.mjs +10 -66
- package/src/Utils.res +15 -15
- package/src/Utils.res.mjs +7 -8
- package/src/adapters/MarkBatchProcessedAdapter.res +5 -0
- package/src/adapters/MarkBatchProcessedAdapter.res.mjs +14 -0
- package/src/bindings/BigDecimal.res +1 -1
- package/src/bindings/BigDecimal.res.mjs +2 -2
- package/src/bindings/ClickHouse.res +8 -6
- package/src/bindings/ClickHouse.res.mjs +5 -5
- package/src/bindings/Hrtime.res +1 -1
- package/src/bindings/Pino.res +2 -2
- package/src/bindings/Pino.res.mjs +3 -4
- package/src/db/EntityFilter.res +410 -0
- package/src/db/EntityFilter.res.mjs +424 -0
- package/src/db/EntityHistory.res +1 -1
- package/src/db/EntityHistory.res.mjs +1 -1
- package/src/db/InternalTable.res +10 -10
- package/src/db/InternalTable.res.mjs +41 -45
- package/src/db/Schema.res +2 -2
- package/src/db/Schema.res.mjs +3 -3
- package/src/db/Table.res +106 -22
- package/src/db/Table.res.mjs +84 -35
- package/src/sources/EventRouter.res +67 -2
- package/src/sources/EventRouter.res.mjs +45 -3
- package/src/sources/Evm.res +0 -7
- package/src/sources/Evm.res.mjs +0 -15
- package/src/sources/EvmChain.res +1 -1
- package/src/sources/EvmChain.res.mjs +1 -2
- package/src/sources/EvmRpcClient.res +42 -0
- package/src/sources/EvmRpcClient.res.mjs +64 -0
- package/src/sources/Fuel.res +0 -7
- package/src/sources/Fuel.res.mjs +0 -15
- package/src/sources/HyperFuelSource.res +5 -4
- package/src/sources/HyperFuelSource.res.mjs +2 -2
- package/src/sources/HyperSyncClient.res +9 -5
- package/src/sources/HyperSyncClient.res.mjs +2 -2
- package/src/sources/HyperSyncHeightStream.res +2 -2
- package/src/sources/HyperSyncHeightStream.res.mjs +2 -2
- package/src/sources/HyperSyncSource.res +10 -9
- package/src/sources/HyperSyncSource.res.mjs +4 -4
- package/src/sources/Rpc.res +1 -5
- package/src/sources/Rpc.res.mjs +1 -9
- package/src/sources/RpcSource.res +57 -21
- package/src/sources/RpcSource.res.mjs +47 -20
- package/src/sources/RpcWebSocketHeightStream.res +1 -1
- package/src/sources/SourceManager.res +3 -2
- package/src/sources/SourceManager.res.mjs +1 -1
- package/src/sources/Svm.res +3 -10
- package/src/sources/Svm.res.mjs +4 -18
- package/src/sources/SvmHyperSyncClient.res +265 -0
- package/src/sources/SvmHyperSyncClient.res.mjs +28 -0
- package/src/sources/SvmHyperSyncSource.res +638 -0
- package/src/sources/SvmHyperSyncSource.res.mjs +557 -0
- package/src/tui/Tui.res +9 -2
- package/src/tui/Tui.res.mjs +18 -3
- package/src/tui/components/BufferedProgressBar.res +2 -2
- package/src/tui/components/TuiData.res +3 -0
- package/svm.schema.json +523 -14
- package/src/TableIndices.res +0 -115
- package/src/TableIndices.res.mjs +0 -144
package/src/PgStorage.res
CHANGED
|
@@ -26,7 +26,7 @@ let makeCreateIndexQuery = (~tableName, ~indexFields, ~pgSchema) => {
|
|
|
26
26
|
let indexName = tableName ++ "_" ++ indexFields->Array.joinUnsafe("_")
|
|
27
27
|
|
|
28
28
|
// Case for indexer before envio@2.28
|
|
29
|
-
let index = indexFields->
|
|
29
|
+
let index = indexFields->Array.map(idx => `"${idx}"`)->Array.joinUnsafe(", ")
|
|
30
30
|
`CREATE INDEX IF NOT EXISTS "${indexName}" ON "${pgSchema}"."${tableName}"(${index});`
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -55,7 +55,7 @@ let makeCreateCompositeIndexQuery = (
|
|
|
55
55
|
->Array.joinUnsafe("_")
|
|
56
56
|
let index =
|
|
57
57
|
indexFields
|
|
58
|
-
->
|
|
58
|
+
->Array.map(f => `"${f.fieldName}"${directionToSql(f.direction)}`)
|
|
59
59
|
->Array.joinUnsafe(", ")
|
|
60
60
|
`CREATE INDEX IF NOT EXISTS "${indexName}" ON "${pgSchema}"."${tableName}"(${index});`
|
|
61
61
|
}
|
|
@@ -81,7 +81,7 @@ let makeCreateTableQuery = (table: Table.table, ~pgSchema, ~isNumericArrayAsText
|
|
|
81
81
|
->Table.getFields
|
|
82
82
|
->Array.map(field => {
|
|
83
83
|
let {fieldType, isNullable, isArray, defaultValue} = field
|
|
84
|
-
let fieldName = field->Table.
|
|
84
|
+
let fieldName = field->Table.getPgDbFieldName
|
|
85
85
|
|
|
86
86
|
{
|
|
87
87
|
`"${fieldName}" ${Table.getPgFieldType(
|
|
@@ -98,7 +98,7 @@ let makeCreateTableQuery = (table: Table.table, ~pgSchema, ~isNumericArrayAsText
|
|
|
98
98
|
})
|
|
99
99
|
->Array.joinUnsafe(", ")
|
|
100
100
|
|
|
101
|
-
let primaryKeyFieldNames = table->Table.
|
|
101
|
+
let primaryKeyFieldNames = table->Table.getPgPrimaryKeyFieldNames
|
|
102
102
|
let primaryKey = primaryKeyFieldNames->Array.map(field => `"${field}"`)->Array.joinUnsafe(", ")
|
|
103
103
|
|
|
104
104
|
`CREATE TABLE IF NOT EXISTS "${pgSchema}"."${table.tableName}"(${fieldsMapped}${primaryKeyFieldNames->Array.length > 0
|
|
@@ -116,7 +116,7 @@ let getEntityHistory = (~entityConfig: Internal.entityConfig): EntityHistory.pgE
|
|
|
116
116
|
let cache = {
|
|
117
117
|
let id = "id"
|
|
118
118
|
|
|
119
|
-
let dataFields = entityConfig.table.fields->
|
|
119
|
+
let dataFields = entityConfig.table.fields->Array.filterMap(field =>
|
|
120
120
|
switch field {
|
|
121
121
|
| Field(field) =>
|
|
122
122
|
switch field.fieldName {
|
|
@@ -157,7 +157,7 @@ let getEntityHistory = (~entityConfig: Internal.entityConfig): EntityHistory.pgE
|
|
|
157
157
|
//ignore composite indices
|
|
158
158
|
let table = Table.mkTable(
|
|
159
159
|
historyTableName,
|
|
160
|
-
~fields=dataFields->
|
|
160
|
+
~fields=dataFields->Array.concat([checkpointIdField, actionField]),
|
|
161
161
|
)
|
|
162
162
|
|
|
163
163
|
let setChangeSchema = EntityHistory.makeSetUpdateSchema(entityConfig.schema)
|
|
@@ -245,7 +245,7 @@ GRANT ALL ON SCHEMA "${pgSchema}" TO public;`,
|
|
|
245
245
|
->Table.getDerivedFromFields
|
|
246
246
|
->Array.forEach(derivedFromField => {
|
|
247
247
|
let indexField =
|
|
248
|
-
derivedSchema->Schema.
|
|
248
|
+
derivedSchema->Schema.getDerivedFromPgFieldName(derivedFromField)->Utils.unwrapResultExn
|
|
249
249
|
query :=
|
|
250
250
|
query.contents ++
|
|
251
251
|
"\n" ++
|
|
@@ -281,16 +281,82 @@ $$ LANGUAGE plpgsql;`,
|
|
|
281
281
|
]
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
-
let
|
|
285
|
-
`SELECT * FROM "${pgSchema}"."${tableName}" WHERE
|
|
284
|
+
let makeLoadQuery = (~pgSchema, ~tableName, ~condition) => {
|
|
285
|
+
`SELECT * FROM "${pgSchema}"."${tableName}" WHERE ${condition};`
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
288
|
+
// Appends the filter's serialized field values to params (mutated in place)
|
|
289
|
+
// and returns the matching SQL condition referencing them by index.
|
|
290
|
+
// Field names are spliced as quoted identifiers only after the queryFields
|
|
291
|
+
// lookup proves they exist on the table (and they originate from
|
|
292
|
+
// codegen-validated schemas), so the interpolation can't be abused.
|
|
293
|
+
let rec makeFilterCondition = (
|
|
294
|
+
~filter: EntityFilter.t,
|
|
295
|
+
~table: Table.table,
|
|
296
|
+
~params: array<JSON.t>,
|
|
297
|
+
) => {
|
|
298
|
+
// Filters reference fields by API name, while the SQL references columns
|
|
299
|
+
// by their possibly renamed db names.
|
|
300
|
+
let getQueryFieldOrThrow = fieldName =>
|
|
301
|
+
switch table->Table.queryFields->Dict.get(fieldName) {
|
|
302
|
+
| Some(queryField) => queryField
|
|
303
|
+
| None =>
|
|
304
|
+
throw(
|
|
305
|
+
Persistence.StorageError({
|
|
306
|
+
message: `Failed loading "${table.tableName}" from storage. The table doesn't have the field "${fieldName}".`,
|
|
307
|
+
reason: Table.NonExistingTableField(fieldName),
|
|
308
|
+
}),
|
|
309
|
+
)
|
|
310
|
+
}
|
|
311
|
+
let serializeParamOrThrow = (~queryField: Table.queryField, ~fieldName, ~fieldValue: unknown, ~isArray) => {
|
|
312
|
+
let param = try fieldValue->S.reverseConvertToJsonOrThrow(
|
|
313
|
+
isArray ? queryField.arrayFieldSchema : queryField.fieldSchema,
|
|
314
|
+
) catch {
|
|
315
|
+
| exn =>
|
|
316
|
+
throw(
|
|
317
|
+
Persistence.StorageError({
|
|
318
|
+
message: `Failed loading "${table.tableName}" from storage by field "${fieldName}". Couldn't serialize provided value.`,
|
|
319
|
+
reason: exn,
|
|
320
|
+
}),
|
|
321
|
+
)
|
|
322
|
+
}
|
|
323
|
+
params->Array.push(param)->ignore
|
|
324
|
+
`$${params->Array.length->Int.toString}`
|
|
325
|
+
}
|
|
326
|
+
let scalarCondition = (~fieldName, ~fieldValue, ~op) => {
|
|
327
|
+
let queryField = getQueryFieldOrThrow(fieldName)
|
|
328
|
+
`"${queryField.pgDbFieldName}" ${op} ${serializeParamOrThrow(
|
|
329
|
+
~queryField,
|
|
330
|
+
~fieldName,
|
|
331
|
+
~fieldValue,
|
|
332
|
+
~isArray=false,
|
|
333
|
+
)}`
|
|
334
|
+
}
|
|
335
|
+
switch filter {
|
|
336
|
+
| Eq({fieldName, fieldValue}) => scalarCondition(~fieldName, ~fieldValue, ~op="=")
|
|
337
|
+
| Gt({fieldName, fieldValue}) => scalarCondition(~fieldName, ~fieldValue, ~op=">")
|
|
338
|
+
| Lt({fieldName, fieldValue}) => scalarCondition(~fieldName, ~fieldValue, ~op="<")
|
|
339
|
+
| In({fieldName, fieldValue}) => {
|
|
340
|
+
let queryField = getQueryFieldOrThrow(fieldName)
|
|
341
|
+
`"${queryField.pgDbFieldName}" = ANY(${serializeParamOrThrow(
|
|
342
|
+
~queryField,
|
|
343
|
+
~fieldName,
|
|
344
|
+
~fieldValue=fieldValue->(Utils.magic: array<unknown> => unknown),
|
|
345
|
+
~isArray=true,
|
|
346
|
+
)})`
|
|
347
|
+
}
|
|
348
|
+
| And({filters: []}) =>
|
|
349
|
+
throw(
|
|
350
|
+
Persistence.StorageError({
|
|
351
|
+
message: `Failed loading "${table.tableName}" from storage. The "and" filter must contain at least one nested filter.`,
|
|
352
|
+
reason: Utils.Error.make(`Empty "and" filter`),
|
|
353
|
+
}),
|
|
354
|
+
)
|
|
355
|
+
| And({filters}) =>
|
|
356
|
+
`(${filters
|
|
357
|
+
->Array.map(filter => makeFilterCondition(~filter, ~table, ~params))
|
|
358
|
+
->Array.join(" AND ")})`
|
|
359
|
+
}
|
|
294
360
|
}
|
|
295
361
|
|
|
296
362
|
let makeDeleteByIdQuery = (~pgSchema, ~tableName) => {
|
|
@@ -309,7 +375,7 @@ let makeInsertUnnestSetQuery = (~pgSchema, ~table: Table.table, ~itemSchema, ~is
|
|
|
309
375
|
let {quotedFieldNames, quotedNonPrimaryFieldNames, arrayFieldTypes} =
|
|
310
376
|
table->Table.toSqlParams(~schema=itemSchema, ~pgSchema)
|
|
311
377
|
|
|
312
|
-
let primaryKeyFieldNames = Table.
|
|
378
|
+
let primaryKeyFieldNames = Table.getPgPrimaryKeyFieldNames(table)
|
|
313
379
|
|
|
314
380
|
`INSERT INTO "${pgSchema}"."${table.tableName}" (${quotedFieldNames->Array.joinUnsafe(", ")})
|
|
315
381
|
SELECT * FROM unnest(${arrayFieldTypes
|
|
@@ -339,7 +405,7 @@ let makeInsertValuesSetQuery = (~pgSchema, ~table: Table.table, ~itemSchema, ~it
|
|
|
339
405
|
let {quotedFieldNames, quotedNonPrimaryFieldNames} =
|
|
340
406
|
table->Table.toSqlParams(~schema=itemSchema, ~pgSchema)
|
|
341
407
|
|
|
342
|
-
let primaryKeyFieldNames = Table.
|
|
408
|
+
let primaryKeyFieldNames = Table.getPgPrimaryKeyFieldNames(table)
|
|
343
409
|
let fieldsCount = quotedFieldNames->Array.length
|
|
344
410
|
|
|
345
411
|
// Create placeholder variables for the VALUES clause - using $1, $2, etc.
|
|
@@ -698,9 +764,9 @@ let makeInsertDeleteUpdatesQuery = (~entityConfig: Internal.entityConfig, ~pgSch
|
|
|
698
764
|
)
|
|
699
765
|
|
|
700
766
|
// Get all field names for the INSERT statement
|
|
701
|
-
let allHistoryFieldNames = entityConfig.table.fields->
|
|
767
|
+
let allHistoryFieldNames = entityConfig.table.fields->Array.filterMap(fieldOrDerived =>
|
|
702
768
|
switch fieldOrDerived {
|
|
703
|
-
| Field(field) => field->Table.
|
|
769
|
+
| Field(field) => field->Table.getPgDbFieldName->Some
|
|
704
770
|
| DerivedFrom(_) => None
|
|
705
771
|
}
|
|
706
772
|
)
|
|
@@ -708,10 +774,10 @@ let makeInsertDeleteUpdatesQuery = (~entityConfig: Internal.entityConfig, ~pgSch
|
|
|
708
774
|
allHistoryFieldNames->Array.push(EntityHistory.changeFieldName)->ignore
|
|
709
775
|
|
|
710
776
|
let allHistoryFieldNamesStr =
|
|
711
|
-
allHistoryFieldNames->
|
|
777
|
+
allHistoryFieldNames->Array.map(name => `"${name}"`)->Array.joinUnsafe(", ")
|
|
712
778
|
|
|
713
779
|
// Build the SELECT part: id from unnest, envio_checkpoint_id from unnest, 'DELETE' for action, NULL for all other fields
|
|
714
|
-
let selectParts = allHistoryFieldNames->
|
|
780
|
+
let selectParts = allHistoryFieldNames->Array.map(fieldName => {
|
|
715
781
|
switch fieldName {
|
|
716
782
|
| field if field == Table.idFieldName => `u.${Table.idFieldName}`
|
|
717
783
|
| field if field == EntityHistory.checkpointIdFieldName =>
|
|
@@ -772,8 +838,8 @@ let makeRawEvent = (
|
|
|
772
838
|
eventItem: Internal.eventItem,
|
|
773
839
|
~config: Config.t,
|
|
774
840
|
): InternalTable.RawEvents.t => {
|
|
775
|
-
let {event, eventConfig, chain, blockNumber, timestamp: blockTimestamp} = eventItem
|
|
776
|
-
let {block, transaction, params, logIndex, srcAddress} = event
|
|
841
|
+
let {event, eventConfig, chain, blockNumber, blockHash, timestamp: blockTimestamp} = eventItem
|
|
842
|
+
let {block, transaction, params, logIndex, srcAddress} = event->Internal.toGenericEvent
|
|
777
843
|
let chainId = chain->ChainMap.Chain.toChainId
|
|
778
844
|
let eventId = EventUtils.packEventIndex(~logIndex, ~blockNumber)
|
|
779
845
|
let blockFields =
|
|
@@ -809,7 +875,7 @@ let makeRawEvent = (
|
|
|
809
875
|
blockNumber,
|
|
810
876
|
logIndex,
|
|
811
877
|
srcAddress,
|
|
812
|
-
blockHash
|
|
878
|
+
blockHash,
|
|
813
879
|
blockTimestamp,
|
|
814
880
|
blockFields,
|
|
815
881
|
transactionFields,
|
|
@@ -838,7 +904,7 @@ let rec writeBatch = async (
|
|
|
838
904
|
let specificError = ref(None)
|
|
839
905
|
|
|
840
906
|
let rawEvents = if config.enableRawEvents {
|
|
841
|
-
let rows = batch.items->
|
|
907
|
+
let rows = batch.items->Array.filterMap(item =>
|
|
842
908
|
switch item {
|
|
843
909
|
| Internal.Event(_) => Some(item->Internal.castUnsafeEventItem->makeRawEvent(~config))
|
|
844
910
|
| Internal.Block(_) => None
|
|
@@ -869,7 +935,7 @@ let rec writeBatch = async (
|
|
|
869
935
|
}
|
|
870
936
|
}
|
|
871
937
|
|
|
872
|
-
let setEntities = updatedEntities->
|
|
938
|
+
let setEntities = updatedEntities->Array.map(({entityConfig, changes}) => {
|
|
873
939
|
let entitiesToSet = []
|
|
874
940
|
let idsToDelete = []
|
|
875
941
|
|
|
@@ -888,10 +954,10 @@ let rec writeBatch = async (
|
|
|
888
954
|
// history-table batches.
|
|
889
955
|
let latestChangeById = Dict.make()
|
|
890
956
|
let orderedIds = []
|
|
891
|
-
changes->
|
|
957
|
+
changes->Array.forEach(change => {
|
|
892
958
|
let entityId = change->Change.getEntityId
|
|
893
959
|
if latestChangeById->Utils.Dict.dangerouslyGetNonOption(entityId)->Option.isNone {
|
|
894
|
-
orderedIds->
|
|
960
|
+
orderedIds->Array.push(entityId)
|
|
895
961
|
}
|
|
896
962
|
latestChangeById->Dict.set(entityId, change)
|
|
897
963
|
if shouldSaveHistory {
|
|
@@ -900,19 +966,19 @@ let rec writeBatch = async (
|
|
|
900
966
|
} else {
|
|
901
967
|
switch change {
|
|
902
968
|
| Delete({entityId, checkpointId}) =>
|
|
903
|
-
batchDeleteEntityIds->
|
|
904
|
-
batchDeleteCheckpointIds->
|
|
905
|
-
| Set(_) => batchSetUpdates->
|
|
969
|
+
batchDeleteEntityIds->Array.push(entityId)->ignore
|
|
970
|
+
batchDeleteCheckpointIds->Array.push(checkpointId)->ignore
|
|
971
|
+
| Set(_) => batchSetUpdates->Array.push(change)->ignore
|
|
906
972
|
}
|
|
907
973
|
}
|
|
908
974
|
}
|
|
909
975
|
})
|
|
910
976
|
|
|
911
977
|
let backfillHistoryIds = Utils.Set.make()
|
|
912
|
-
orderedIds->
|
|
978
|
+
orderedIds->Array.forEach(entityId => {
|
|
913
979
|
switch latestChangeById->Dict.getUnsafe(entityId) {
|
|
914
|
-
| Set({entity}) => entitiesToSet->
|
|
915
|
-
| Delete({entityId}) => idsToDelete->
|
|
980
|
+
| Set({entity}) => entitiesToSet->Array.push(entity)
|
|
981
|
+
| Delete({entityId}) => idsToDelete->Array.push(entityId)
|
|
916
982
|
}
|
|
917
983
|
|
|
918
984
|
// An id needs a history backfill iff none of its changes is the diff.
|
|
@@ -943,7 +1009,7 @@ let rec writeBatch = async (
|
|
|
943
1009
|
}
|
|
944
1010
|
|
|
945
1011
|
if batchDeleteCheckpointIds->Utils.Array.notEmpty {
|
|
946
|
-
promises->
|
|
1012
|
+
promises->Array.push(
|
|
947
1013
|
sql
|
|
948
1014
|
->Postgres.preparedUnsafe(
|
|
949
1015
|
makeInsertDeleteUpdatesQuery(~entityConfig, ~pgSchema),
|
|
@@ -986,7 +1052,7 @@ let rec writeBatch = async (
|
|
|
986
1052
|
if shouldRemoveInvalidUtf8 {
|
|
987
1053
|
entitiesToSet->removeInvalidUtf8InPlace
|
|
988
1054
|
}
|
|
989
|
-
promises->
|
|
1055
|
+
promises->Array.push(
|
|
990
1056
|
sql->setOrThrow(
|
|
991
1057
|
~items=entitiesToSet,
|
|
992
1058
|
~table=entityConfig.table,
|
|
@@ -996,7 +1062,7 @@ let rec writeBatch = async (
|
|
|
996
1062
|
)
|
|
997
1063
|
}
|
|
998
1064
|
if idsToDelete->Utils.Array.notEmpty {
|
|
999
|
-
promises->
|
|
1065
|
+
promises->Array.push(
|
|
1000
1066
|
sql->deleteByIdsOrThrow(~pgSchema, ~ids=idsToDelete, ~table=entityConfig.table),
|
|
1001
1067
|
)
|
|
1002
1068
|
}
|
|
@@ -1066,7 +1132,7 @@ let rec writeBatch = async (
|
|
|
1066
1132
|
}),
|
|
1067
1133
|
),
|
|
1068
1134
|
setRawEvents,
|
|
1069
|
-
]->
|
|
1135
|
+
]->Array.concat(setEntities)
|
|
1070
1136
|
|
|
1071
1137
|
switch chainMetaData {
|
|
1072
1138
|
| Some(chainsData) =>
|
|
@@ -1079,7 +1145,7 @@ let rec writeBatch = async (
|
|
|
1079
1145
|
}
|
|
1080
1146
|
|
|
1081
1147
|
if shouldSaveHistory {
|
|
1082
|
-
setOperations->
|
|
1148
|
+
setOperations->Array.push(sql =>
|
|
1083
1149
|
sql->InternalTable.Checkpoints.insert(
|
|
1084
1150
|
~pgSchema,
|
|
1085
1151
|
~checkpointIds=batch.checkpointIds,
|
|
@@ -1092,7 +1158,7 @@ let rec writeBatch = async (
|
|
|
1092
1158
|
}
|
|
1093
1159
|
|
|
1094
1160
|
await setOperations
|
|
1095
|
-
->
|
|
1161
|
+
->Array.map(dbFunc => sql->dbFunc)
|
|
1096
1162
|
->Promise.all
|
|
1097
1163
|
->Utils.Promise.ignoreValue
|
|
1098
1164
|
|
|
@@ -1108,7 +1174,7 @@ let rec writeBatch = async (
|
|
|
1108
1174
|
// Since effect cache currently doesn't support rollback,
|
|
1109
1175
|
// we can run it outside of the transaction for simplicity.
|
|
1110
1176
|
updatedEffectsCache
|
|
1111
|
-
->
|
|
1177
|
+
->Array.map(({effect, items, shouldInitialize}: Persistence.updatedEffectCache) => {
|
|
1112
1178
|
setEffectCacheOrThrow(~effect, ~items, ~initialize=shouldInitialize)
|
|
1113
1179
|
})
|
|
1114
1180
|
->Promise.all,
|
|
@@ -1157,15 +1223,15 @@ let rec writeBatch = async (
|
|
|
1157
1223
|
// Returns the most recent entity state for IDs that need to be restored during rollback.
|
|
1158
1224
|
// For each ID modified after the rollback target, retrieves its latest state at or before the target.
|
|
1159
1225
|
let makeGetRollbackRestoredEntitiesQuery = (~entityConfig: Internal.entityConfig, ~pgSchema) => {
|
|
1160
|
-
let dataFieldNames = entityConfig.table.fields->
|
|
1226
|
+
let dataFieldNames = entityConfig.table.fields->Array.filterMap(fieldOrDerived =>
|
|
1161
1227
|
switch fieldOrDerived {
|
|
1162
|
-
| Field(field) => field->Table.
|
|
1228
|
+
| Field(field) => field->Table.getPgDbFieldName->Some
|
|
1163
1229
|
| DerivedFrom(_) => None
|
|
1164
1230
|
}
|
|
1165
1231
|
)
|
|
1166
1232
|
|
|
1167
1233
|
let dataFieldsCommaSeparated =
|
|
1168
|
-
dataFieldNames->
|
|
1234
|
+
dataFieldNames->Array.map(name => `"${name}"`)->Array.joinUnsafe(", ")
|
|
1169
1235
|
|
|
1170
1236
|
let historyTableName = EntityHistory.historyTableName(
|
|
1171
1237
|
~entityName=entityConfig.name,
|
|
@@ -1434,80 +1500,26 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
|
|
|
1434
1500
|
}
|
|
1435
1501
|
}
|
|
1436
1502
|
|
|
1437
|
-
let
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
| [_] =>
|
|
1441
|
-
sql->Postgres.preparedUnsafe(
|
|
1442
|
-
makeLoadByIdQuery(~pgSchema, ~tableName=table.tableName),
|
|
1443
|
-
ids->Obj.magic,
|
|
1444
|
-
)
|
|
1445
|
-
| _ =>
|
|
1446
|
-
sql->Postgres.preparedUnsafe(
|
|
1447
|
-
makeLoadByIdsQuery(~pgSchema, ~tableName=table.tableName),
|
|
1448
|
-
[ids]->Obj.magic,
|
|
1449
|
-
)
|
|
1450
|
-
}
|
|
1451
|
-
) {
|
|
1452
|
-
| exception exn =>
|
|
1453
|
-
throw(
|
|
1454
|
-
Persistence.StorageError({
|
|
1455
|
-
message: `Failed loading "${table.tableName}" from storage by ids`,
|
|
1456
|
-
reason: exn,
|
|
1457
|
-
}),
|
|
1458
|
-
)
|
|
1459
|
-
| rows =>
|
|
1460
|
-
try rows->S.parseOrThrow(rowsSchema) catch {
|
|
1461
|
-
| exn =>
|
|
1462
|
-
throw(
|
|
1463
|
-
Persistence.StorageError({
|
|
1464
|
-
message: `Failed to parse "${table.tableName}" loaded from storage by ids`,
|
|
1465
|
-
reason: exn,
|
|
1466
|
-
}),
|
|
1467
|
-
)
|
|
1468
|
-
}
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
|
|
1472
|
-
let loadByFieldOrThrow = async (
|
|
1473
|
-
~fieldName: string,
|
|
1474
|
-
~fieldSchema,
|
|
1475
|
-
~fieldValue,
|
|
1476
|
-
~operator: Persistence.operator,
|
|
1477
|
-
~table: Table.table,
|
|
1478
|
-
~rowsSchema,
|
|
1479
|
-
) => {
|
|
1480
|
-
let params = try [fieldValue->S.reverseConvertToJsonOrThrow(fieldSchema)]->Obj.magic catch {
|
|
1481
|
-
| exn =>
|
|
1482
|
-
throw(
|
|
1483
|
-
Persistence.StorageError({
|
|
1484
|
-
message: `Failed loading "${table.tableName}" from storage by field "${fieldName}". Couldn't serialize provided value.`,
|
|
1485
|
-
reason: exn,
|
|
1486
|
-
}),
|
|
1487
|
-
)
|
|
1488
|
-
}
|
|
1503
|
+
let loadOrThrow = async (~filter: EntityFilter.t, ~table: Table.table) => {
|
|
1504
|
+
let params = []
|
|
1505
|
+
let condition = makeFilterCondition(~filter, ~table, ~params)
|
|
1489
1506
|
switch await sql->Postgres.preparedUnsafe(
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
~tableName=table.tableName,
|
|
1493
|
-
~fieldName,
|
|
1494
|
-
~operator=(operator :> string),
|
|
1495
|
-
),
|
|
1496
|
-
params,
|
|
1507
|
+
makeLoadQuery(~pgSchema, ~tableName=table.tableName, ~condition),
|
|
1508
|
+
params->Obj.magic,
|
|
1497
1509
|
) {
|
|
1498
1510
|
| exception exn =>
|
|
1499
1511
|
throw(
|
|
1500
1512
|
Persistence.StorageError({
|
|
1501
|
-
message: `Failed loading "${table.tableName}" from storage by
|
|
1513
|
+
message: `Failed loading "${table.tableName}" from storage by condition: ${condition}`,
|
|
1502
1514
|
reason: exn,
|
|
1503
1515
|
}),
|
|
1504
1516
|
)
|
|
1505
1517
|
| rows =>
|
|
1506
|
-
try rows->S.parseOrThrow(
|
|
1518
|
+
try rows->S.parseOrThrow(table->Table.pgRowsSchema) catch {
|
|
1507
1519
|
| exn =>
|
|
1508
1520
|
throw(
|
|
1509
1521
|
Persistence.StorageError({
|
|
1510
|
-
message: `Failed to parse "${table.tableName}" loaded from storage by
|
|
1522
|
+
message: `Failed to parse "${table.tableName}" loaded from storage by condition: ${condition}`,
|
|
1511
1523
|
reason: exn,
|
|
1512
1524
|
}),
|
|
1513
1525
|
)
|
|
@@ -1576,7 +1588,7 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
|
|
|
1576
1588
|
Logging.info(
|
|
1577
1589
|
`Dumping cache: ${cacheTableInfo
|
|
1578
1590
|
->Array.map(({tableName, count}) =>
|
|
1579
|
-
tableName ++ " (" ++ count->
|
|
1591
|
+
tableName ++ " (" ++ count->Int.toString ++ " rows)"
|
|
1580
1592
|
)
|
|
1581
1593
|
->Array.joinUnsafe(", ")}`,
|
|
1582
1594
|
)
|
|
@@ -1620,7 +1632,7 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
|
|
|
1620
1632
|
sql,
|
|
1621
1633
|
~pgSchema,
|
|
1622
1634
|
)->Promise.thenResolve(rawInitialStates => {
|
|
1623
|
-
rawInitialStates->
|
|
1635
|
+
rawInitialStates->Array.map((rawInitialState): Persistence.initialChainState => {
|
|
1624
1636
|
id: rawInitialState.id,
|
|
1625
1637
|
startBlock: rawInitialState.startBlock,
|
|
1626
1638
|
endBlock: rawInitialState.endBlock->Null.toOption,
|
|
@@ -1651,10 +1663,10 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
|
|
|
1651
1663
|
InternalTable.EnvioInfo.read(sql, ~pgSchema),
|
|
1652
1664
|
))
|
|
1653
1665
|
|
|
1654
|
-
let checkpointId = (checkpointIdResult->
|
|
1666
|
+
let checkpointId = (checkpointIdResult->Array.getUnsafe(0))["id"]->BigInt.fromStringOrThrow
|
|
1655
1667
|
|
|
1656
1668
|
// Convert string checkpoint IDs from DB to bigint
|
|
1657
|
-
let reorgCheckpoints =
|
|
1669
|
+
let reorgCheckpoints = Array.map(reorgCheckpoints, (raw): Internal.reorgCheckpoint => {
|
|
1658
1670
|
checkpointId: raw["id"]->BigInt.fromStringOrThrow,
|
|
1659
1671
|
chainId: raw["chain_id"],
|
|
1660
1672
|
blockNumber: raw["block_number"],
|
|
@@ -1803,8 +1815,7 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
|
|
|
1803
1815
|
isInitialized,
|
|
1804
1816
|
initialize,
|
|
1805
1817
|
resumeInitialState,
|
|
1806
|
-
|
|
1807
|
-
loadByIdsOrThrow,
|
|
1818
|
+
loadOrThrow,
|
|
1808
1819
|
dumpEffectCache,
|
|
1809
1820
|
reset,
|
|
1810
1821
|
setChainMeta,
|
|
@@ -1883,7 +1894,7 @@ let makeStorageFromEnv = (
|
|
|
1883
1894
|
~pgSchema,
|
|
1884
1895
|
~userEntities=config->Config.getPgUserEntities,
|
|
1885
1896
|
~responseLimit=Env.Hasura.responseLimit,
|
|
1886
|
-
~schema=Schema.make(config.allEntities->
|
|
1897
|
+
~schema=Schema.make(config.allEntities->Array.map(e => e.table)),
|
|
1887
1898
|
~aggregateEntities=Env.Hasura.aggregateEntities,
|
|
1888
1899
|
)->Promise.catch(err => {
|
|
1889
1900
|
Logging.errorWithExn(err->Utils.prettifyExn, `Error tracking tables`)->Promise.resolve
|
|
@@ -1908,7 +1919,7 @@ let makeStorageFromEnv = (
|
|
|
1908
1919
|
~tableConfigs=tableNames->Array.map(tableName => {
|
|
1909
1920
|
Hasura.tableName,
|
|
1910
1921
|
description: None,
|
|
1911
|
-
|
|
1922
|
+
columnConfigs: dict{},
|
|
1912
1923
|
}),
|
|
1913
1924
|
)->Promise.catch(err => {
|
|
1914
1925
|
Logging.errorWithExn(
|