envio 3.2.1 → 3.3.0-alpha.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/package.json +6 -7
- package/src/Batch.res +12 -15
- package/src/Batch.res.mjs +4 -5
- package/src/BatchProcessing.res +199 -0
- package/src/BatchProcessing.res.mjs +125 -0
- package/src/ChainFetching.res +375 -0
- package/src/ChainFetching.res.mjs +206 -0
- package/src/ChainMetadata.res +27 -0
- package/src/ChainMetadata.res.mjs +27 -0
- package/src/ChainState.res +618 -0
- package/src/ChainState.res.mjs +461 -0
- package/src/ChainState.resi +85 -0
- package/src/Config.res +13 -4
- package/src/Config.res.mjs +8 -3
- package/src/ContractRegisterContext.res +106 -0
- package/src/ContractRegisterContext.res.mjs +76 -0
- package/src/Core.res +3 -0
- package/src/CrossChainState.res +269 -0
- package/src/CrossChainState.res.mjs +197 -0
- package/src/CrossChainState.resi +47 -0
- package/src/Ecosystem.res +58 -0
- package/src/Ecosystem.res.mjs +43 -1
- package/src/Env.res +7 -2
- package/src/Env.res.mjs +5 -2
- package/src/EventConfigBuilder.res +2 -2
- package/src/EventProcessing.res +60 -46
- package/src/EventProcessing.res.mjs +33 -32
- package/src/EventUtils.res +0 -4
- package/src/EventUtils.res.mjs +0 -4
- package/src/ExitOnCaughtUp.res +10 -0
- package/src/ExitOnCaughtUp.res.mjs +22 -0
- package/src/FetchState.res +124 -62
- package/src/FetchState.res.mjs +159 -93
- package/src/InMemoryStore.res +36 -451
- package/src/InMemoryStore.res.mjs +20 -369
- package/src/IndexerLoop.res +44 -0
- package/src/IndexerLoop.res.mjs +46 -0
- package/src/IndexerState.res +544 -0
- package/src/IndexerState.res.mjs +547 -0
- package/src/IndexerState.resi +132 -0
- package/src/Internal.res +29 -8
- package/src/LoadLayer.res +20 -18
- package/src/LoadLayer.res.mjs +14 -12
- package/src/LoadLayer.resi +6 -3
- package/src/Logging.res +11 -44
- package/src/Logging.res.mjs +10 -42
- package/src/Main.res +54 -79
- package/src/Main.res.mjs +44 -56
- package/src/PgStorage.res +8 -71
- package/src/PgStorage.res.mjs +3 -47
- package/src/Prometheus.res +7 -8
- package/src/Prometheus.res.mjs +7 -4
- package/src/PruneStaleHistory.res +45 -0
- package/src/PruneStaleHistory.res.mjs +46 -0
- package/src/RawEvent.res +73 -0
- package/src/RawEvent.res.mjs +51 -0
- package/src/Rollback.res +204 -0
- package/src/Rollback.res.mjs +118 -0
- package/src/SimulateItems.res +12 -10
- package/src/SimulateItems.res.mjs +1 -1
- package/src/UserContext.res +26 -114
- package/src/UserContext.res.mjs +15 -78
- package/src/Writing.res +242 -0
- package/src/Writing.res.mjs +215 -0
- package/src/db/InternalTable.res +14 -27
- package/src/sources/Evm.res +40 -1
- package/src/sources/Evm.res.mjs +94 -84
- package/src/sources/Fuel.res +40 -1
- package/src/sources/Fuel.res.mjs +36 -26
- package/src/sources/HyperFuel.res +41 -120
- package/src/sources/HyperFuel.res.mjs +42 -80
- package/src/sources/HyperFuel.resi +1 -24
- package/src/sources/HyperFuelClient.res +16 -297
- package/src/sources/HyperFuelClient.res.mjs +5 -4
- package/src/sources/HyperFuelSource.res +33 -8
- package/src/sources/HyperFuelSource.res.mjs +56 -10
- package/src/sources/HyperSyncSource.res +5 -3
- package/src/sources/HyperSyncSource.res.mjs +1 -1
- package/src/sources/RpcSource.res +2 -2
- package/src/sources/RpcSource.res.mjs +1 -1
- package/src/sources/SourceManager.res +8 -18
- package/src/sources/SourceManager.res.mjs +8 -5
- package/src/sources/SourceManager.resi +4 -1
- package/src/sources/Svm.res +18 -1
- package/src/sources/Svm.res.mjs +30 -22
- package/src/sources/SvmHyperSyncSource.res +1 -1
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
- package/src/tui/Tui.res +38 -36
- package/src/tui/Tui.res.mjs +51 -51
- package/src/ChainFetcher.res +0 -519
- package/src/ChainFetcher.res.mjs +0 -314
- package/src/ChainManager.res +0 -358
- package/src/ChainManager.res.mjs +0 -291
- package/src/Ctx.res +0 -6
- package/src/Ctx.res.mjs +0 -2
- package/src/GlobalState.res +0 -1056
- package/src/GlobalState.res.mjs +0 -1086
- package/src/GlobalStateManager.res +0 -57
- package/src/GlobalStateManager.res.mjs +0 -68
- package/src/GlobalStateManager.resi +0 -7
- package/src/Ports.res +0 -5
- package/src/Ports.res.mjs +0 -9
- package/src/adapters/MarkBatchProcessedAdapter.res +0 -5
- package/src/adapters/MarkBatchProcessedAdapter.res.mjs +0 -14
- package/src/sources/EnvioApiClient.res +0 -15
- package/src/sources/EnvioApiClient.res.mjs +0 -24
package/src/Main.res
CHANGED
|
@@ -79,7 +79,7 @@ let blockRangeSchema: S.t<blockRange> = S.object(s => {
|
|
|
79
79
|
|
|
80
80
|
let defaultBlockRange: blockRange = {_gte: None, _lte: None, _every: 1}
|
|
81
81
|
|
|
82
|
-
let
|
|
82
|
+
let indexerStateRef: ref<option<IndexerState.t>> = ref(None)
|
|
83
83
|
|
|
84
84
|
// Persistence is set by Main.start before handler modules load, so that
|
|
85
85
|
// the exported indexer value can lazily expose DB state (startBlock,
|
|
@@ -145,12 +145,12 @@ let buildChainsObject = (~config: Config.t) => {
|
|
|
145
145
|
{
|
|
146
146
|
enumerable: true,
|
|
147
147
|
get: () => {
|
|
148
|
-
switch
|
|
149
|
-
| Some(
|
|
150
|
-
// Before the
|
|
148
|
+
switch indexerStateRef.contents {
|
|
149
|
+
| Some(state) => state->IndexerState.isRealtime
|
|
150
|
+
// Before the global state is available (eg during handler
|
|
151
151
|
// module load after resume), derive from persistence: every chain
|
|
152
152
|
// must have previously caught up to head or endBlock. Mirror the
|
|
153
|
-
//
|
|
153
|
+
// IndexerState.makeFromDbState path: updateSyncTimeOnRestart wipes
|
|
154
154
|
// the saved timestamps so a restart re-enters backfill.
|
|
155
155
|
| None if Env.updateSyncTimeOnRestart => false
|
|
156
156
|
| None =>
|
|
@@ -179,12 +179,11 @@ let buildChainsObject = (~config: Config.t) => {
|
|
|
179
179
|
{
|
|
180
180
|
enumerable: true,
|
|
181
181
|
get: () => {
|
|
182
|
-
switch
|
|
183
|
-
| Some(
|
|
184
|
-
let state = gsManager->GlobalStateManager.getState
|
|
182
|
+
switch indexerStateRef.contents {
|
|
183
|
+
| Some(state) => {
|
|
185
184
|
let chain = ChainMap.Chain.makeUnsafe(~chainId=chainConfig.id)
|
|
186
|
-
let
|
|
187
|
-
let indexingAddresses =
|
|
185
|
+
let chainState = state->IndexerState.getChainState(~chain)
|
|
186
|
+
let indexingAddresses = (chainState->ChainState.fetchState).indexingAddresses
|
|
188
187
|
|
|
189
188
|
// Collect all addresses for this contract name from indexingAddresses
|
|
190
189
|
let addresses = []
|
|
@@ -197,7 +196,7 @@ let buildChainsObject = (~config: Config.t) => {
|
|
|
197
196
|
}
|
|
198
197
|
addresses
|
|
199
198
|
}
|
|
200
|
-
// Before the
|
|
199
|
+
// Before the global state is available (eg during handler
|
|
201
200
|
// module load after resume), combine static addresses from config
|
|
202
201
|
// with dynamic contracts persisted in the database.
|
|
203
202
|
| None =>
|
|
@@ -586,7 +585,7 @@ let getGlobalIndexer = (): 'indexer => {
|
|
|
586
585
|
Utils.Proxy.make(Utils.Object.createNullObject(), traps)->(Utils.magic: {..} => 'indexer)
|
|
587
586
|
}
|
|
588
587
|
|
|
589
|
-
let startServer = (~getState, ~
|
|
588
|
+
let startServer = (~getState, ~persistence: Persistence.t, ~isDevelopmentMode: bool) => {
|
|
590
589
|
open Express
|
|
591
590
|
|
|
592
591
|
let app = make()
|
|
@@ -629,7 +628,7 @@ let startServer = (~getState, ~ctx: Ctx.t, ~isDevelopmentMode: bool) => {
|
|
|
629
628
|
|
|
630
629
|
app->post("/console/syncCache", (_req, res) => {
|
|
631
630
|
if isDevelopmentMode {
|
|
632
|
-
(
|
|
631
|
+
(persistence->Persistence.getInitializedStorageOrThrow).dumpEffectCache()
|
|
633
632
|
->Promise.thenResolve(_ => res->json(Boolean(true)))
|
|
634
633
|
->Promise.ignore
|
|
635
634
|
} else {
|
|
@@ -757,112 +756,88 @@ let start = async (
|
|
|
757
756
|
| Some(patchConfig) => patchConfig(config, registrations)
|
|
758
757
|
| None => config
|
|
759
758
|
}
|
|
760
|
-
// The single fatal-error handler,
|
|
761
|
-
// manager's catch.
|
|
759
|
+
// The single fatal-error handler, invoked once via IndexerState.errorExit.
|
|
762
760
|
let onError = (errHandler: ErrorHandling.t) => {
|
|
763
761
|
errHandler->ErrorHandling.log
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
~persistence,
|
|
774
|
-
~config,
|
|
775
|
-
~onError=exn => onError(exn->ErrorHandling.make(~msg="Failed writing batch to the database")),
|
|
776
|
-
),
|
|
762
|
+
if isTest {
|
|
763
|
+
// The TestIndexer runs the indexer in a worker thread and reads the
|
|
764
|
+
// failure off the worker 'error' event. Re-throw the original error
|
|
765
|
+
// outside the promise chain on the next tick so the test sees its real
|
|
766
|
+
// message instead of a generic non-zero exit code.
|
|
767
|
+
NodeJs.setImmediate(() => errHandler->ErrorHandling.raiseExn)
|
|
768
|
+
} else {
|
|
769
|
+
NodeJs.process->NodeJs.exitWithCode(Failure)
|
|
770
|
+
}
|
|
777
771
|
}
|
|
778
|
-
|
|
779
772
|
let envioVersion = Utils.EnvioPackage.value.version
|
|
780
773
|
Prometheus.Info.set(~version=envioVersion)
|
|
781
774
|
Prometheus.ProcessStartTimeSeconds.set()
|
|
782
|
-
Prometheus.RollbackEnabled.set(~enabled=
|
|
775
|
+
Prometheus.RollbackEnabled.set(~enabled=config.shouldRollbackOnReorg)
|
|
783
776
|
|
|
784
777
|
if !isTest {
|
|
785
|
-
startServer(~
|
|
786
|
-
switch
|
|
778
|
+
startServer(~persistence, ~isDevelopmentMode, ~getState=() =>
|
|
779
|
+
switch indexerStateRef.contents {
|
|
787
780
|
| None => Initializing({})
|
|
788
|
-
| Some(
|
|
789
|
-
let state = gsManager->GlobalStateManager.getState
|
|
781
|
+
| Some(state) => {
|
|
790
782
|
let chains =
|
|
791
|
-
state
|
|
792
|
-
->
|
|
793
|
-
->
|
|
794
|
-
|
|
783
|
+
state
|
|
784
|
+
->IndexerState.chainStates
|
|
785
|
+
->Dict.valuesToArray
|
|
786
|
+
->Array.map(cs => {
|
|
787
|
+
let fetchState = cs->ChainState.fetchState
|
|
795
788
|
let latestFetchedBlockNumber = Pervasives.max(
|
|
796
789
|
FetchState.bufferBlockNumber(fetchState),
|
|
797
790
|
0,
|
|
798
791
|
)
|
|
799
792
|
let knownHeight =
|
|
800
|
-
|
|
801
|
-
?
|
|
802
|
-
:
|
|
793
|
+
cs->ChainState.hasProcessedToEndblock
|
|
794
|
+
? fetchState.endBlock->Option.getOr(fetchState.knownHeight)
|
|
795
|
+
: fetchState.knownHeight
|
|
803
796
|
|
|
804
797
|
{
|
|
805
|
-
chainId:
|
|
798
|
+
chainId: (cs->ChainState.chainConfig).id->Int.toFloat,
|
|
806
799
|
poweredByHyperSync: (
|
|
807
|
-
|
|
800
|
+
cs->ChainState.sourceManager->SourceManager.getActiveSource
|
|
808
801
|
).poweredByHyperSync,
|
|
809
802
|
latestFetchedBlockNumber,
|
|
810
803
|
knownHeight,
|
|
811
804
|
numBatchesFetched: 0,
|
|
812
|
-
startBlock:
|
|
813
|
-
endBlock:
|
|
814
|
-
firstEventBlockNumber:
|
|
815
|
-
latestProcessedBlock:
|
|
805
|
+
startBlock: fetchState.startBlock,
|
|
806
|
+
endBlock: fetchState.endBlock,
|
|
807
|
+
firstEventBlockNumber: fetchState.firstEventBlock,
|
|
808
|
+
latestProcessedBlock: cs->ChainState.committedProgressBlockNumber === -1
|
|
816
809
|
? None
|
|
817
|
-
: Some(
|
|
818
|
-
timestampCaughtUpToHeadOrEndblock:
|
|
819
|
-
numEventsProcessed:
|
|
820
|
-
numAddresses:
|
|
810
|
+
: Some(cs->ChainState.committedProgressBlockNumber),
|
|
811
|
+
timestampCaughtUpToHeadOrEndblock: cs->ChainState.timestampCaughtUpToHeadOrEndblock,
|
|
812
|
+
numEventsProcessed: cs->ChainState.numEventsProcessed,
|
|
813
|
+
numAddresses: fetchState->FetchState.numAddresses,
|
|
821
814
|
}
|
|
822
815
|
})
|
|
823
816
|
Active({
|
|
824
817
|
envioVersion,
|
|
825
818
|
chains,
|
|
826
|
-
indexerStartTime: state.indexerStartTime,
|
|
819
|
+
indexerStartTime: state->IndexerState.indexerStartTime,
|
|
827
820
|
isPreRegisteringDynamicContracts: false,
|
|
828
|
-
rollbackOnReorg:
|
|
821
|
+
rollbackOnReorg: config.shouldRollbackOnReorg,
|
|
829
822
|
})
|
|
830
823
|
}
|
|
831
824
|
}
|
|
832
825
|
)
|
|
833
826
|
}
|
|
834
827
|
|
|
835
|
-
let
|
|
836
|
-
~
|
|
837
|
-
~
|
|
838
|
-
~
|
|
839
|
-
|
|
840
|
-
let globalState = GlobalState.make(
|
|
841
|
-
~ctx,
|
|
842
|
-
~chainManager,
|
|
828
|
+
let state = IndexerState.makeFromDbState(
|
|
829
|
+
~config,
|
|
830
|
+
~persistence,
|
|
831
|
+
~initialState=persistence->Persistence.getInitializedState,
|
|
832
|
+
~registrations,
|
|
843
833
|
~isDevelopmentMode,
|
|
844
834
|
~shouldUseTui,
|
|
845
835
|
~exitAfterFirstEventBlock,
|
|
846
836
|
~onError,
|
|
847
837
|
)
|
|
848
|
-
let gsManager =
|
|
849
|
-
globalState->GlobalStateManager.make(
|
|
850
|
-
~reducers=GlobalState.makeReducers(
|
|
851
|
-
~markBatchProcessed=MarkBatchProcessedAdapter.make(~inMemoryStore=ctx.inMemoryStore),
|
|
852
|
-
),
|
|
853
|
-
~onError=exn =>
|
|
854
|
-
onError(exn->ErrorHandling.make(~msg="Indexer has failed with an unexpected error")),
|
|
855
|
-
)
|
|
856
838
|
if shouldUseTui {
|
|
857
|
-
let _rerender = Tui.start(~getState=() =>
|
|
839
|
+
let _rerender = Tui.start(~getState=() => state)
|
|
858
840
|
}
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
/*
|
|
862
|
-
NOTE:
|
|
863
|
-
This `ProcessEventBatch` dispatch shouldn't be necessary but we are adding for safety, it should immediately return doing
|
|
864
|
-
nothing since there is no events on the queues.
|
|
865
|
-
*/
|
|
866
|
-
|
|
867
|
-
gsManager->GlobalStateManager.dispatchTask(ProcessEventBatch)
|
|
841
|
+
indexerStateRef := Some(state)
|
|
842
|
+
state->IndexerLoop.start
|
|
868
843
|
}
|
package/src/Main.res.mjs
CHANGED
|
@@ -10,17 +10,16 @@ import Express from "express";
|
|
|
10
10
|
import * as Process from "process";
|
|
11
11
|
import * as ChainMap from "./ChainMap.res.mjs";
|
|
12
12
|
import * as PgStorage from "./PgStorage.res.mjs";
|
|
13
|
+
import * as ChainState from "./ChainState.res.mjs";
|
|
13
14
|
import * as FetchState from "./FetchState.res.mjs";
|
|
14
15
|
import * as Prometheus from "./Prometheus.res.mjs";
|
|
15
|
-
import * as
|
|
16
|
+
import * as IndexerLoop from "./IndexerLoop.res.mjs";
|
|
16
17
|
import * as Persistence from "./Persistence.res.mjs";
|
|
17
18
|
import * as PromClient from "prom-client";
|
|
18
19
|
import Yargs from "yargs/yargs";
|
|
19
|
-
import * as
|
|
20
|
-
import * as ChainManager from "./ChainManager.res.mjs";
|
|
20
|
+
import * as IndexerState from "./IndexerState.res.mjs";
|
|
21
21
|
import * as ErrorHandling from "./ErrorHandling.res.mjs";
|
|
22
22
|
import * as HandlerLoader from "./HandlerLoader.res.mjs";
|
|
23
|
-
import * as InMemoryStore from "./InMemoryStore.res.mjs";
|
|
24
23
|
import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
25
24
|
import * as SourceManager from "./sources/SourceManager.res.mjs";
|
|
26
25
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
@@ -30,9 +29,7 @@ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
|
30
29
|
import * as HandlerRegister from "./HandlerRegister.res.mjs";
|
|
31
30
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
32
31
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
33
|
-
import * as GlobalStateManager from "./GlobalStateManager.res.mjs";
|
|
34
32
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
35
|
-
import * as MarkBatchProcessedAdapter from "./adapters/MarkBatchProcessedAdapter.res.mjs";
|
|
36
33
|
|
|
37
34
|
let chainDataSchema = S$RescriptSchema.schema(s => ({
|
|
38
35
|
chainId: s.m(S$RescriptSchema.float),
|
|
@@ -78,7 +75,7 @@ let defaultBlockRange = {
|
|
|
78
75
|
_every: 1
|
|
79
76
|
};
|
|
80
77
|
|
|
81
|
-
let
|
|
78
|
+
let indexerStateRef = {
|
|
82
79
|
contents: undefined
|
|
83
80
|
};
|
|
84
81
|
|
|
@@ -139,9 +136,9 @@ function buildChainsObject(config) {
|
|
|
139
136
|
}), "isRealtime", {
|
|
140
137
|
enumerable: true,
|
|
141
138
|
get: () => {
|
|
142
|
-
let
|
|
143
|
-
if (
|
|
144
|
-
return
|
|
139
|
+
let state = indexerStateRef.contents;
|
|
140
|
+
if (state !== undefined) {
|
|
141
|
+
return IndexerState.isRealtime(Primitive_option.valFromOption(state));
|
|
145
142
|
} else if (Env.updateSyncTimeOnRestart) {
|
|
146
143
|
return false;
|
|
147
144
|
} else {
|
|
@@ -167,12 +164,11 @@ function buildChainsObject(config) {
|
|
|
167
164
|
}), "addresses", {
|
|
168
165
|
enumerable: true,
|
|
169
166
|
get: () => {
|
|
170
|
-
let
|
|
171
|
-
if (
|
|
172
|
-
let state = GlobalStateManager.getState(Primitive_option.valFromOption(gsManager));
|
|
167
|
+
let state = indexerStateRef.contents;
|
|
168
|
+
if (state !== undefined) {
|
|
173
169
|
let chain = ChainMap.Chain.makeUnsafe(chainConfig.id);
|
|
174
|
-
let
|
|
175
|
-
let indexingAddresses =
|
|
170
|
+
let chainState = IndexerState.getChainState(Primitive_option.valFromOption(state), chain);
|
|
171
|
+
let indexingAddresses = ChainState.fetchState(chainState).indexingAddresses;
|
|
176
172
|
let addresses = [];
|
|
177
173
|
let values = Object.values(indexingAddresses);
|
|
178
174
|
for (let idx = 0, idx_finish = values.length; idx < idx_finish; ++idx) {
|
|
@@ -183,12 +179,12 @@ function buildChainsObject(config) {
|
|
|
183
179
|
}
|
|
184
180
|
return addresses;
|
|
185
181
|
}
|
|
186
|
-
let chainState = getInitialChainState(chainConfig.id);
|
|
187
|
-
if (chainState === undefined) {
|
|
182
|
+
let chainState$1 = getInitialChainState(chainConfig.id);
|
|
183
|
+
if (chainState$1 === undefined) {
|
|
188
184
|
return contract.addresses;
|
|
189
185
|
}
|
|
190
186
|
let addresses$1 = contract.addresses.slice();
|
|
191
|
-
chainState.indexingAddresses.forEach(dc => {
|
|
187
|
+
chainState$1.indexingAddresses.forEach(dc => {
|
|
192
188
|
if (dc.contractName === contract.name) {
|
|
193
189
|
addresses$1.push(dc.address);
|
|
194
190
|
return;
|
|
@@ -450,7 +446,7 @@ function getGlobalIndexer() {
|
|
|
450
446
|
return new Proxy(Object.create(null), traps);
|
|
451
447
|
}
|
|
452
448
|
|
|
453
|
-
function startServer(getState,
|
|
449
|
+
function startServer(getState, persistence, isDevelopmentMode) {
|
|
454
450
|
let app = Express();
|
|
455
451
|
let consoleCorsMiddleware = (req, res, next) => {
|
|
456
452
|
let origin = req.headers["origin"];
|
|
@@ -480,7 +476,7 @@ function startServer(getState, ctx, isDevelopmentMode) {
|
|
|
480
476
|
});
|
|
481
477
|
app.post("/console/syncCache", (_req, res) => {
|
|
482
478
|
if (isDevelopmentMode) {
|
|
483
|
-
Persistence.getInitializedStorageOrThrow(
|
|
479
|
+
Persistence.getInitializedStorageOrThrow(persistence).dumpEffectCache().then(() => {
|
|
484
480
|
res.json(true);
|
|
485
481
|
});
|
|
486
482
|
} else {
|
|
@@ -571,14 +567,11 @@ async function start(persistence, resetOpt, isTestOpt, exitAfterFirstEventBlockO
|
|
|
571
567
|
let config$2 = patchConfig !== undefined ? patchConfig(config$1, registrations) : config$1;
|
|
572
568
|
let onError = errHandler => {
|
|
573
569
|
ErrorHandling.log(errHandler);
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
config: config$2,
|
|
580
|
-
persistence: persistence$1,
|
|
581
|
-
inMemoryStore: ctx_inMemoryStore
|
|
570
|
+
if (isTest) {
|
|
571
|
+
setImmediate(() => ErrorHandling.raiseExn(errHandler));
|
|
572
|
+
} else {
|
|
573
|
+
Process.exit(1);
|
|
574
|
+
}
|
|
582
575
|
};
|
|
583
576
|
let envioVersion = Utils.EnvioPackage.value.version;
|
|
584
577
|
Prometheus.Info.set(envioVersion);
|
|
@@ -586,53 +579,48 @@ async function start(persistence, resetOpt, isTestOpt, exitAfterFirstEventBlockO
|
|
|
586
579
|
Prometheus.RollbackEnabled.set(config$2.shouldRollbackOnReorg);
|
|
587
580
|
if (!isTest) {
|
|
588
581
|
startServer(() => {
|
|
589
|
-
let
|
|
590
|
-
if (
|
|
582
|
+
let state = indexerStateRef.contents;
|
|
583
|
+
if (state === undefined) {
|
|
591
584
|
return {
|
|
592
585
|
status: "initializing"
|
|
593
586
|
};
|
|
594
587
|
}
|
|
595
|
-
let state =
|
|
596
|
-
let chains =
|
|
597
|
-
let
|
|
598
|
-
let
|
|
588
|
+
let state$1 = Primitive_option.valFromOption(state);
|
|
589
|
+
let chains = Object.values(IndexerState.chainStates(state$1)).map(cs => {
|
|
590
|
+
let fetchState = ChainState.fetchState(cs);
|
|
591
|
+
let latestFetchedBlockNumber = Primitive_int.max(FetchState.bufferBlockNumber(fetchState), 0);
|
|
592
|
+
let knownHeight = ChainState.hasProcessedToEndblock(cs) ? Stdlib_Option.getOr(fetchState.endBlock, fetchState.knownHeight) : fetchState.knownHeight;
|
|
599
593
|
return {
|
|
600
|
-
chainId:
|
|
601
|
-
poweredByHyperSync: SourceManager.getActiveSource(
|
|
602
|
-
firstEventBlockNumber:
|
|
603
|
-
latestProcessedBlock:
|
|
604
|
-
timestampCaughtUpToHeadOrEndblock:
|
|
605
|
-
numEventsProcessed:
|
|
594
|
+
chainId: ChainState.chainConfig(cs).id,
|
|
595
|
+
poweredByHyperSync: SourceManager.getActiveSource(ChainState.sourceManager(cs)).poweredByHyperSync,
|
|
596
|
+
firstEventBlockNumber: fetchState.firstEventBlock,
|
|
597
|
+
latestProcessedBlock: ChainState.committedProgressBlockNumber(cs) === -1 ? undefined : ChainState.committedProgressBlockNumber(cs),
|
|
598
|
+
timestampCaughtUpToHeadOrEndblock: ChainState.timestampCaughtUpToHeadOrEndblock(cs),
|
|
599
|
+
numEventsProcessed: ChainState.numEventsProcessed(cs),
|
|
606
600
|
latestFetchedBlockNumber: latestFetchedBlockNumber,
|
|
607
601
|
currentBlockHeight: knownHeight,
|
|
608
602
|
numBatchesFetched: 0,
|
|
609
|
-
startBlock:
|
|
610
|
-
endBlock:
|
|
611
|
-
numAddresses: FetchState.numAddresses(
|
|
603
|
+
startBlock: fetchState.startBlock,
|
|
604
|
+
endBlock: fetchState.endBlock,
|
|
605
|
+
numAddresses: FetchState.numAddresses(fetchState)
|
|
612
606
|
};
|
|
613
607
|
});
|
|
614
608
|
return {
|
|
615
609
|
status: "active",
|
|
616
610
|
envioVersion: envioVersion,
|
|
617
611
|
chains: chains,
|
|
618
|
-
indexerStartTime:
|
|
612
|
+
indexerStartTime: IndexerState.indexerStartTime(state$1),
|
|
619
613
|
isPreRegisteringDynamicContracts: false,
|
|
620
614
|
rollbackOnReorg: config$2.shouldRollbackOnReorg
|
|
621
615
|
};
|
|
622
|
-
},
|
|
616
|
+
}, persistence$1, isDevelopmentMode);
|
|
623
617
|
}
|
|
624
|
-
let
|
|
625
|
-
let globalState = GlobalState.make(ctx, chainManager, isDevelopmentMode, shouldUseTui, exitAfterFirstEventBlock, onError);
|
|
626
|
-
let gsManager = GlobalStateManager.make(globalState, GlobalState.makeReducers(undefined, undefined, undefined, MarkBatchProcessedAdapter.make(ctx_inMemoryStore)), exn => onError(ErrorHandling.make(exn, undefined, "Indexer has failed with an unexpected error")));
|
|
618
|
+
let state = IndexerState.makeFromDbState(config$2, persistence$1, Persistence.getInitializedState(persistence$1), registrations, isDevelopmentMode, shouldUseTui, exitAfterFirstEventBlock, undefined, undefined, undefined, undefined, onError);
|
|
627
619
|
if (shouldUseTui) {
|
|
628
|
-
Tui.start(() =>
|
|
620
|
+
Tui.start(() => state);
|
|
629
621
|
}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
TAG: "NextQuery",
|
|
633
|
-
_0: "CheckAllChains"
|
|
634
|
-
});
|
|
635
|
-
return GlobalStateManager.dispatchTask(gsManager, "ProcessEventBatch");
|
|
622
|
+
indexerStateRef.contents = Primitive_option.some(state);
|
|
623
|
+
return IndexerLoop.start(state);
|
|
636
624
|
}
|
|
637
625
|
|
|
638
626
|
export {
|
|
@@ -640,7 +628,7 @@ export {
|
|
|
640
628
|
stateSchema,
|
|
641
629
|
blockRangeSchema,
|
|
642
630
|
defaultBlockRange,
|
|
643
|
-
|
|
631
|
+
indexerStateRef,
|
|
644
632
|
globalPersistenceRef,
|
|
645
633
|
getInitialChainState,
|
|
646
634
|
buildChainsObject,
|
package/src/PgStorage.res
CHANGED
|
@@ -308,7 +308,12 @@ let rec makeFilterCondition = (
|
|
|
308
308
|
}),
|
|
309
309
|
)
|
|
310
310
|
}
|
|
311
|
-
let serializeParamOrThrow = (
|
|
311
|
+
let serializeParamOrThrow = (
|
|
312
|
+
~queryField: Table.queryField,
|
|
313
|
+
~fieldName,
|
|
314
|
+
~fieldValue: unknown,
|
|
315
|
+
~isArray,
|
|
316
|
+
) => {
|
|
312
317
|
let param = try fieldValue->S.reverseConvertToJsonOrThrow(
|
|
313
318
|
isArray ? queryField.arrayFieldSchema : queryField.fieldSchema,
|
|
314
319
|
) catch {
|
|
@@ -815,74 +820,6 @@ let executeSet = (
|
|
|
815
820
|
}
|
|
816
821
|
}
|
|
817
822
|
|
|
818
|
-
let convertFieldsToJson = (fields: option<dict<unknown>>) => {
|
|
819
|
-
switch fields {
|
|
820
|
-
| None => %raw(`{}`)
|
|
821
|
-
| Some(fields) =>
|
|
822
|
-
// Convert bigint fields to string. There are no fields with nested
|
|
823
|
-
// bigints, so iterating only the top level is safe.
|
|
824
|
-
fields
|
|
825
|
-
->Utils.Dict.mapValues(value =>
|
|
826
|
-
typeof(value) === #bigint
|
|
827
|
-
? value
|
|
828
|
-
->(Utils.magic: unknown => bigint)
|
|
829
|
-
->BigInt.toString
|
|
830
|
-
->(Utils.magic: string => unknown)
|
|
831
|
-
: value
|
|
832
|
-
)
|
|
833
|
-
->(Utils.magic: dict<unknown> => JSON.t)
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
let makeRawEvent = (
|
|
838
|
-
eventItem: Internal.eventItem,
|
|
839
|
-
~config: Config.t,
|
|
840
|
-
): InternalTable.RawEvents.t => {
|
|
841
|
-
let {event, eventConfig, chain, blockNumber, blockHash, timestamp: blockTimestamp} = eventItem
|
|
842
|
-
let {block, transaction, params, logIndex, srcAddress} = event->Internal.toGenericEvent
|
|
843
|
-
let chainId = chain->ChainMap.Chain.toChainId
|
|
844
|
-
let eventId = EventUtils.packEventIndex(~logIndex, ~blockNumber)
|
|
845
|
-
let blockFields =
|
|
846
|
-
block
|
|
847
|
-
->(Utils.magic: Internal.eventBlock => option<dict<unknown>>)
|
|
848
|
-
->convertFieldsToJson
|
|
849
|
-
let transactionFields =
|
|
850
|
-
transaction
|
|
851
|
-
->(Utils.magic: Internal.eventTransaction => option<dict<unknown>>)
|
|
852
|
-
->convertFieldsToJson
|
|
853
|
-
|
|
854
|
-
blockFields->config.ecosystem.cleanUpRawEventFieldsInPlace
|
|
855
|
-
|
|
856
|
-
// Serialize to unknown, because serializing to Js.Json.t fails for Bytes Fuel type, since it has unknown schema
|
|
857
|
-
let params =
|
|
858
|
-
params
|
|
859
|
-
->S.reverseConvertOrThrow(eventConfig.paramsRawEventSchema)
|
|
860
|
-
->(Utils.magic: unknown => JSON.t)
|
|
861
|
-
let params = if params === %raw(`null`) {
|
|
862
|
-
// Should probably make the params field nullable
|
|
863
|
-
// But this is currently needed to make events
|
|
864
|
-
// with empty params work
|
|
865
|
-
%raw(`"null"`)
|
|
866
|
-
} else {
|
|
867
|
-
params
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
{
|
|
871
|
-
chainId,
|
|
872
|
-
eventId,
|
|
873
|
-
eventName: eventConfig.name,
|
|
874
|
-
contractName: eventConfig.contractName,
|
|
875
|
-
blockNumber,
|
|
876
|
-
logIndex,
|
|
877
|
-
srcAddress,
|
|
878
|
-
blockHash,
|
|
879
|
-
blockTimestamp,
|
|
880
|
-
blockFields,
|
|
881
|
-
transactionFields,
|
|
882
|
-
params,
|
|
883
|
-
}
|
|
884
|
-
}
|
|
885
|
-
|
|
886
823
|
let rec writeBatch = async (
|
|
887
824
|
sql,
|
|
888
825
|
~batch: Batch.t,
|
|
@@ -906,7 +843,7 @@ let rec writeBatch = async (
|
|
|
906
843
|
let rawEvents = if config.enableRawEvents {
|
|
907
844
|
let rows = batch.items->Array.filterMap(item =>
|
|
908
845
|
switch item {
|
|
909
|
-
| Internal.Event(_) => Some(item->Internal.castUnsafeEventItem
|
|
846
|
+
| Internal.Event(_) => Some(config.ecosystem.toRawEvent(item->Internal.castUnsafeEventItem))
|
|
910
847
|
| Internal.Block(_) => None
|
|
911
848
|
}
|
|
912
849
|
)
|
|
@@ -1493,7 +1430,7 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
|
|
|
1493
1430
|
numEventsProcessed: 0.,
|
|
1494
1431
|
firstEventBlockNumber: None,
|
|
1495
1432
|
timestampCaughtUpToHeadOrEndblock: None,
|
|
1496
|
-
indexingAddresses:
|
|
1433
|
+
indexingAddresses: ChainState.configAddresses(chainConfig),
|
|
1497
1434
|
sourceBlockNumber: 0,
|
|
1498
1435
|
}),
|
|
1499
1436
|
checkpointId: InternalTable.Checkpoints.initialCheckpointId,
|
package/src/PgStorage.res.mjs
CHANGED
|
@@ -13,10 +13,9 @@ import * as Schema from "./db/Schema.res.mjs";
|
|
|
13
13
|
import * as Logging from "./Logging.res.mjs";
|
|
14
14
|
import * as Internal from "./Internal.res.mjs";
|
|
15
15
|
import Postgres from "postgres";
|
|
16
|
-
import * as
|
|
16
|
+
import * as ChainState from "./ChainState.res.mjs";
|
|
17
17
|
import * as Prometheus from "./Prometheus.res.mjs";
|
|
18
18
|
import * as Persistence from "./Persistence.res.mjs";
|
|
19
|
-
import * as ChainFetcher from "./ChainFetcher.res.mjs";
|
|
20
19
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
21
20
|
import * as EntityHistory from "./db/EntityHistory.res.mjs";
|
|
22
21
|
import * as InternalTable from "./db/InternalTable.res.mjs";
|
|
@@ -608,47 +607,6 @@ function executeSet(sql, items, dbFunction) {
|
|
|
608
607
|
}
|
|
609
608
|
}
|
|
610
609
|
|
|
611
|
-
function convertFieldsToJson(fields) {
|
|
612
|
-
if (fields !== undefined) {
|
|
613
|
-
return Utils.Dict.mapValues(fields, value => {
|
|
614
|
-
if (typeof value === "bigint") {
|
|
615
|
-
return value.toString();
|
|
616
|
-
} else {
|
|
617
|
-
return value;
|
|
618
|
-
}
|
|
619
|
-
});
|
|
620
|
-
} else {
|
|
621
|
-
return {};
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
function makeRawEvent(eventItem, config) {
|
|
626
|
-
let event = eventItem.event;
|
|
627
|
-
let blockNumber = eventItem.blockNumber;
|
|
628
|
-
let eventConfig = eventItem.eventConfig;
|
|
629
|
-
let logIndex = event.logIndex;
|
|
630
|
-
let eventId = EventUtils.packEventIndex(blockNumber, logIndex);
|
|
631
|
-
let blockFields = convertFieldsToJson(event.block);
|
|
632
|
-
let transactionFields = convertFieldsToJson(event.transaction);
|
|
633
|
-
config.ecosystem.cleanUpRawEventFieldsInPlace(blockFields);
|
|
634
|
-
let params = S$RescriptSchema.reverseConvertOrThrow(event.params, eventConfig.paramsRawEventSchema);
|
|
635
|
-
let params$1 = params === null ? "null" : params;
|
|
636
|
-
return {
|
|
637
|
-
chain_id: eventItem.chain,
|
|
638
|
-
event_id: eventId,
|
|
639
|
-
event_name: eventConfig.name,
|
|
640
|
-
contract_name: eventConfig.contractName,
|
|
641
|
-
block_number: blockNumber,
|
|
642
|
-
log_index: logIndex,
|
|
643
|
-
src_address: event.srcAddress,
|
|
644
|
-
block_hash: eventItem.blockHash,
|
|
645
|
-
block_timestamp: eventItem.timestamp,
|
|
646
|
-
block_fields: blockFields,
|
|
647
|
-
transaction_fields: transactionFields,
|
|
648
|
-
params: params$1
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
|
-
|
|
652
610
|
async function writeBatch(sql, batch, pgSchema, rollback, isInReorgThreshold, config, allEntities, setEffectCacheOrThrow, updatedEffectsCache, updatedEntities, sinkPromise, chainMetaData, escapeTables) {
|
|
653
611
|
try {
|
|
654
612
|
let shouldSaveHistory = Config.shouldSaveHistory(config, isInReorgThreshold);
|
|
@@ -659,7 +617,7 @@ async function writeBatch(sql, batch, pgSchema, rollback, isInReorgThreshold, co
|
|
|
659
617
|
if (config.enableRawEvents) {
|
|
660
618
|
let rows = Stdlib_Array.filterMap(batch.items, item => {
|
|
661
619
|
if (item.kind === 0) {
|
|
662
|
-
return
|
|
620
|
+
return config.ecosystem.toRawEvent(item);
|
|
663
621
|
}
|
|
664
622
|
});
|
|
665
623
|
if (escapeTables !== undefined && Primitive_option.valFromOption(escapeTables).has(InternalTable.RawEvents.table)) {
|
|
@@ -1004,7 +962,7 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
|
|
|
1004
962
|
numEventsProcessed: 0,
|
|
1005
963
|
firstEventBlockNumber: undefined,
|
|
1006
964
|
timestampCaughtUpToHeadOrEndblock: undefined,
|
|
1007
|
-
indexingAddresses:
|
|
965
|
+
indexingAddresses: ChainState.configAddresses(chainConfig),
|
|
1008
966
|
sourceBlockNumber: 0
|
|
1009
967
|
})),
|
|
1010
968
|
checkpointId: InternalTable.Checkpoints.initialCheckpointId,
|
|
@@ -1275,8 +1233,6 @@ export {
|
|
|
1275
1233
|
deleteByIdsOrThrow,
|
|
1276
1234
|
makeInsertDeleteUpdatesQuery,
|
|
1277
1235
|
executeSet,
|
|
1278
|
-
convertFieldsToJson,
|
|
1279
|
-
makeRawEvent,
|
|
1280
1236
|
writeBatch,
|
|
1281
1237
|
makeGetRollbackRestoredEntitiesQuery,
|
|
1282
1238
|
makeGetRollbackRemovedIdsQuery,
|
package/src/Prometheus.res
CHANGED
|
@@ -352,14 +352,13 @@ module IndexingAddresses = {
|
|
|
352
352
|
}
|
|
353
353
|
|
|
354
354
|
module IndexingMaxConcurrency = {
|
|
355
|
-
let gauge =
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
)
|
|
355
|
+
let gauge = PromClient.Gauge.makeGauge({
|
|
356
|
+
"name": "envio_indexing_max_concurrency",
|
|
357
|
+
"help": "The maximum number of concurrent data-source queries across the whole indexer.",
|
|
358
|
+
})
|
|
360
359
|
|
|
361
|
-
let set = (~maxConcurrency
|
|
362
|
-
gauge->
|
|
360
|
+
let set = (~maxConcurrency) => {
|
|
361
|
+
gauge->PromClient.Gauge.set(maxConcurrency)
|
|
363
362
|
}
|
|
364
363
|
}
|
|
365
364
|
|
|
@@ -426,7 +425,7 @@ module IndexingBufferSize = {
|
|
|
426
425
|
module IndexingTargetBufferSize = {
|
|
427
426
|
let gauge = PromClient.Gauge.makeGauge({
|
|
428
427
|
"name": "envio_indexing_target_buffer_size",
|
|
429
|
-
"help": "The target buffer size
|
|
428
|
+
"help": "The indexer-wide target buffer size shared across all chains. The actual number of items in the queue may exceed this value, but the indexer always tries to keep the buffer filled up to this target.",
|
|
430
429
|
})
|
|
431
430
|
|
|
432
431
|
let set = (~targetBufferSize) => {
|