envio 3.15.0-subgraph → 3.16.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/README.md +40 -34
- package/evm.schema.json +3 -3
- package/fuel.schema.json +2 -2
- package/index.d.ts +3 -3
- package/licenses/README.md +1 -1
- package/package.json +9 -10
- package/src/Batch.res.mjs +5 -5
- package/src/BatchProcessing.res +1 -0
- package/src/BatchProcessing.res.mjs +1 -0
- package/src/Bin.res +0 -7
- package/src/Bin.res.mjs +0 -8
- package/src/ChainFetching.res +17 -456
- package/src/ChainFetching.res.mjs +33 -404
- package/src/ChainState.res +48 -83
- package/src/ChainState.res.mjs +83 -115
- package/src/ChainState.resi +0 -26
- package/src/Clock.res +57 -0
- package/src/Clock.res.mjs +72 -0
- package/src/Config.res +7 -16
- package/src/Config.res.mjs +4 -11
- package/src/ContractRegisterContext.res +6 -3
- package/src/ContractRegisterContext.res.mjs +2 -4
- package/src/Core.res +5 -136
- package/src/Core.res.mjs +1 -90
- package/src/CrossChainState.res +2 -8
- package/src/CrossChainState.res.mjs +3 -3
- package/src/Ecosystem.res +4 -7
- package/src/Ecosystem.res.mjs +8 -8
- package/src/EffectState.res +10 -2
- package/src/EffectState.res.mjs +8 -4
- package/src/EffectState.resi +3 -1
- package/src/EntityId.res +2 -7
- package/src/EntityId.res.mjs +1 -8
- package/src/EntityTables.res +4 -1
- package/src/EntityTables.res.mjs +1 -1
- package/src/Env.res +0 -16
- package/src/Env.res.mjs +0 -11
- package/src/EventProcessing.res +1 -38
- package/src/EventProcessing.res.mjs +1 -28
- package/src/FetchState.res +160 -319
- package/src/FetchState.res.mjs +182 -292
- package/src/FinalizeBackfill.res +2 -4
- package/src/FinalizeBackfill.res.mjs +3 -4
- package/src/HandlerLoader.res +15 -39
- package/src/HandlerLoader.res.mjs +8 -27
- package/src/HandlerRegister.res +0 -4
- package/src/HandlerRegister.res.mjs +2 -5
- package/src/HandlerRegister.resi +0 -2
- package/src/InMemoryTable.res +17 -16
- package/src/InMemoryTable.res.mjs +14 -15
- package/src/IndexerState.res +28 -4
- package/src/IndexerState.res.mjs +19 -6
- package/src/IndexerState.resi +4 -0
- package/src/Internal.res +0 -110
- package/src/Internal.res.mjs +1 -115
- package/src/LoadLayer.res +21 -47
- package/src/LoadLayer.res.mjs +47 -72
- package/src/LoadLayer.resi +0 -26
- package/src/Main.res +1 -14
- package/src/Main.res.mjs +3 -4
- package/src/Persistence.res +3 -23
- package/src/Persistence.res.mjs +3 -3
- package/src/Rollback.res +0 -1
- package/src/Rollback.res.mjs +1 -1
- package/src/RunScope.res +0 -3
- package/src/SafeCheckpointTracking.res +4 -4
- package/src/SafeCheckpointTracking.res.mjs +1 -1
- package/src/SimulateItems.res +26 -42
- package/src/SimulateItems.res.mjs +16 -40
- package/src/StagedRows.res +106 -0
- package/src/StagedRows.res.mjs +102 -0
- package/src/Staging.res +32 -14
- package/src/Staging.res.mjs +17 -20
- package/src/Storage.res +277 -998
- package/src/Storage.res.mjs +216 -731
- package/src/Supervisor.res +75 -56
- package/src/Supervisor.res.mjs +55 -26
- package/src/TestIndexer.res +22 -27
- package/src/TestIndexer.res.mjs +20 -17
- package/src/Throttler.res +15 -8
- package/src/Throttler.res.mjs +9 -6
- package/src/Throttler.resi +1 -1
- package/src/UserContext.res +46 -410
- package/src/UserContext.res.mjs +30 -318
- package/src/Utils.res +0 -23
- package/src/Utils.res.mjs +1 -17
- package/src/Writing.res +0 -1
- package/src/Writing.res.mjs +1 -1
- package/src/bindings/ClickHouse.res +0 -322
- package/src/bindings/ClickHouse.res.mjs +0 -338
- package/src/bindings/StorageClient.res +107 -175
- package/src/bindings/StorageClient.res.mjs +19 -8
- package/src/bindings/Vitest.res +0 -26
- package/src/bindings/Vitest.res.mjs +0 -3
- package/src/db/Table.res +24 -150
- package/src/db/Table.res.mjs +38 -272
- package/src/sources/AddressSet.res +0 -2
- package/src/sources/AddressStore.res +0 -3
- package/src/sources/ChainSources.res +2 -0
- package/src/sources/ChainSources.res.mjs +2 -2
- package/src/sources/EvmChain.res +4 -7
- package/src/sources/EvmChain.res.mjs +5 -4
- package/src/sources/EvmHyperSyncSource.res +2 -2
- package/src/sources/EvmHyperSyncSource.res.mjs +1 -1
- package/src/sources/EvmRpcClient.res +13 -3
- package/src/sources/EvmRpcClient.res.mjs +4 -3
- package/src/sources/EvmRpcWs.res +4 -3
- package/src/sources/EvmRpcWs.res.mjs +2 -2
- package/src/sources/HeightFeed.res +31 -10
- package/src/sources/HeightFeed.res.mjs +10 -6
- package/src/sources/HeightStream.res +32 -17
- package/src/sources/HeightStream.res.mjs +10 -10
- package/src/sources/HyperSync.res +1 -2
- package/src/sources/HyperSync.res.mjs +1 -2
- package/src/sources/HyperSyncSSE.res +4 -6
- package/src/sources/HyperSyncSSE.res.mjs +2 -2
- package/src/sources/RpcSource.res +10 -1
- package/src/sources/RpcSource.res.mjs +4 -3
- package/src/sources/Source.res +3 -0
- package/src/sources/SourceManager.res +85 -104
- package/src/sources/SourceManager.res.mjs +18 -37
- package/src/sources/SourceManager.resi +3 -5
- package/src/sources/StartBlockResolver.res +1 -0
- package/src/sources/StartBlockResolver.res.mjs +4 -3
- package/src/sources/SvmHyperSyncSource.res +2 -2
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
- package/svm.schema.json +3 -3
- package/src/EffectCacheLookup.res +0 -98
- package/src/EffectCacheLookup.res.mjs +0 -116
- package/src/PgWriting.res +0 -36
- package/src/PgWriting.res.mjs +0 -34
- package/src/PreloadLookahead.res +0 -184
- package/src/PreloadLookahead.res.mjs +0 -197
- package/src/SubgraphLog.res +0 -19
- package/src/SubgraphLog.res.mjs +0 -26
- package/src/SyncWrites.res +0 -101
- package/src/SyncWrites.res.mjs +0 -98
- package/src/db/IndexDefinition.res +0 -47
- package/src/db/IndexDefinition.res.mjs +0 -60
- package/src/sources/CallSource.res +0 -274
- package/src/sources/CallSource.res.mjs +0 -196
- package/src/subgraph/abi-types.ts +0 -84
- package/src/subgraph/aggregations.ts +0 -745
- package/src/subgraph/as-package.ts +0 -143
- package/src/subgraph/assemblyscript-regex.ts +0 -67
- package/src/subgraph/assemblyscript.ts +0 -731
- package/src/subgraph/blocks.ts +0 -398
- package/src/subgraph/calls-source.ts +0 -702
- package/src/subgraph/calls.ts +0 -258
- package/src/subgraph/conformance.ts +0 -106
- package/src/subgraph/errors.ts +0 -85
- package/src/subgraph/graft.ts +0 -73
- package/src/subgraph/graph-cli-worker.mjs +0 -35
- package/src/subgraph/graph-cli.ts +0 -900
- package/src/subgraph/graph-node-decimal.ts +0 -199
- package/src/subgraph/graph-ts-enums.ts +0 -28
- package/src/subgraph/graph-ts-types/VERSION +0 -2
- package/src/subgraph/graph-ts-types/chain/arweave.d.ts +0 -70
- package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +0 -327
- package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +0 -233
- package/src/subgraph/graph-ts-types/chain/near.d.ts +0 -253
- package/src/subgraph/graph-ts-types/chain/starknet.d.ts +0 -32
- package/src/subgraph/graph-ts-types/common/collections.d.ts +0 -136
- package/src/subgraph/graph-ts-types/common/conversion.d.ts +0 -11
- package/src/subgraph/graph-ts-types/common/datasource.d.ts +0 -30
- package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
- package/src/subgraph/graph-ts-types/common/json.d.ts +0 -17
- package/src/subgraph/graph-ts-types/common/numbers.d.ts +0 -120
- package/src/subgraph/graph-ts-types/common/value.d.ts +0 -120
- package/src/subgraph/graph-ts-types/common/yaml.d.ts +0 -90
- package/src/subgraph/graph-ts-types/global/global.d.ts +0 -194
- package/src/subgraph/graph-ts-types/helper-functions.d.ts +0 -22
- package/src/subgraph/graph-ts-types/index.d.ts +0 -102
- package/src/subgraph/graph-ts.ts +0 -4280
- package/src/subgraph/hosts.ts +0 -554
- package/src/subgraph/log.ts +0 -28
- package/src/subgraph/receipts.ts +0 -184
- package/src/subgraph/register-slots.ts +0 -93
- package/src/subgraph/rollup.ts +0 -109
- package/src/subgraph/rpc.ts +0 -337
- package/src/subgraph/runtime.ts +0 -2060
- package/src/subgraph/scope.ts +0 -177
- package/src/subgraph/stats.ts +0 -42
- package/src/subgraph/template-instances.ts +0 -66
- package/src/subgraph/toolchain.ts +0 -327
- package/src/subgraph/transient.ts +0 -176
package/src/ChainFetching.res
CHANGED
|
@@ -11,42 +11,21 @@ type partitionQueryResponse = {
|
|
|
11
11
|
let hasContractRegister = (item: Internal.item) =>
|
|
12
12
|
switch item {
|
|
13
13
|
| Event({onEventRegistration: {contractRegister: Some(_)}}) => true
|
|
14
|
-
| Block({onBlockRegistration: {contractRegister: ?Some(_)}}) => true
|
|
15
14
|
| Event(_) | Block(_) => false
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
let invokeContractRegister = (runtime: HandlerRuntime.t, item: Internal.item) =>
|
|
19
|
-
switch item {
|
|
20
|
-
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
// Unexpected case, since we should pass only events with contract register to this function
|
|
25
|
-
JsError.throwWithMessage("Contract register is not set for event " ++ eventName)
|
|
26
|
-
}
|
|
27
|
-
contractRegister({
|
|
28
|
-
event: item->Ecosystem.getItemEvent(~ecosystem=runtime->HandlerRuntime.ecosystem),
|
|
29
|
-
context: runtime.contractRegisterContext,
|
|
30
|
-
})
|
|
31
|
-
| Block({blockNumber, onBlockRegistration, ?block}) =>
|
|
32
|
-
let contractRegister = switch onBlockRegistration {
|
|
33
|
-
| {contractRegister: ?Some(contractRegister)} => contractRegister
|
|
34
|
-
| {name} => JsError.throwWithMessage("Contract register is not set for block handler " ++ name)
|
|
35
|
-
}
|
|
36
|
-
let ecosystem = runtime->HandlerRuntime.ecosystem
|
|
37
|
-
let context = runtime.contractRegisterContext
|
|
38
|
-
// A block handler's register pass gets what its handler gets, the block (or
|
|
39
|
-
// slot), with the register context in place of the handler's.
|
|
40
|
-
contractRegister(
|
|
41
|
-
switch ecosystem.name {
|
|
42
|
-
| Svm => {slot: blockNumber, ?block, context}
|
|
43
|
-
| Evm | Fuel => {
|
|
44
|
-
block: block->Option.getOr(Ecosystem.makeKeyOnlyBlock(~blockNumber, ~ecosystem)),
|
|
45
|
-
context,
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
)
|
|
17
|
+
let invokeContractRegister = (runtime: HandlerRuntime.t, item: Internal.item) => {
|
|
18
|
+
let contractRegister = switch (item->Internal.castUnsafeEventItem).onEventRegistration {
|
|
19
|
+
| {contractRegister: Some(contractRegister)} => contractRegister
|
|
20
|
+
| {contractRegister: None, eventConfig: {name: eventName}} =>
|
|
21
|
+
// Unexpected case, since we should pass only events with contract register to this function
|
|
22
|
+
JsError.throwWithMessage("Contract register is not set for event " ++ eventName)
|
|
49
23
|
}
|
|
24
|
+
contractRegister({
|
|
25
|
+
event: item->Ecosystem.getItemEvent(~ecosystem=runtime->HandlerRuntime.ecosystem),
|
|
26
|
+
context: runtime.contractRegisterContext,
|
|
27
|
+
})
|
|
28
|
+
}
|
|
50
29
|
|
|
51
30
|
let runContractRegistersOrThrow = async (
|
|
52
31
|
~itemsWithContractRegister: array<Internal.item>,
|
|
@@ -57,11 +36,8 @@ let runContractRegistersOrThrow = async (
|
|
|
57
36
|
// materialise the selected fields onto the payloads before running them. All
|
|
58
37
|
// items belong to the chain being fetched, and both stores are the chain's
|
|
59
38
|
// own, which this response's pages have already been merged into.
|
|
60
|
-
// A subgraph's block register passes ride along; their blocks have no page.
|
|
61
39
|
await ChainState.materializePageItems(
|
|
62
|
-
~items=
|
|
63
|
-
? itemsWithContractRegister->Array.filter(item => item->Internal.getItemKind === 0)
|
|
64
|
-
: itemsWithContractRegister,
|
|
40
|
+
~items=itemsWithContractRegister,
|
|
65
41
|
~transactionStore=chainState->ChainState.transactionStore,
|
|
66
42
|
~blockStore=chainState->ChainState.blockStore,
|
|
67
43
|
~shouldChecksum=chainState->ChainState.shouldChecksum,
|
|
@@ -71,7 +47,6 @@ let runContractRegistersOrThrow = async (
|
|
|
71
47
|
let registrations: array<AddressStore.registration> = []
|
|
72
48
|
let chainLogger = chainState->ChainState.logger
|
|
73
49
|
let ecosystem = runtime->HandlerRuntime.ecosystem
|
|
74
|
-
let isSubgraph = Env.subgraphMode.contents
|
|
75
50
|
|
|
76
51
|
let _ = await itemsWithContractRegister
|
|
77
52
|
->Array.map(async item => {
|
|
@@ -81,32 +56,13 @@ let runContractRegistersOrThrow = async (
|
|
|
81
56
|
chainLogger,
|
|
82
57
|
ecosystem,
|
|
83
58
|
registrations,
|
|
84
|
-
creationRound: ?(
|
|
85
|
-
isSubgraph
|
|
86
|
-
? Some(
|
|
87
|
-
switch item {
|
|
88
|
-
// A block handler is one of its block's own triggers.
|
|
89
|
-
| Block(_) => 1
|
|
90
|
-
| Event(_) =>
|
|
91
|
-
chainState->ChainState.fetchState->FetchState.creationRoundOfRegistration(~item)
|
|
92
|
-
},
|
|
93
|
-
)
|
|
94
|
-
: None
|
|
95
|
-
),
|
|
96
59
|
}
|
|
97
60
|
let scope = RunScope.ContractRegister(run)
|
|
98
61
|
switch await RunScope.enter(scope, invokeContractRegister, runtime, item) {
|
|
99
62
|
| exception exn =>
|
|
100
63
|
scope->RunScope.resolve
|
|
101
64
|
exn->ErrorHandling.mkLogAndRaise(
|
|
102
|
-
~msg=
|
|
103
|
-
| Event(
|
|
104
|
-
_,
|
|
105
|
-
) => "Event contractRegister failed, please fix the error to keep the indexer running smoothly"
|
|
106
|
-
| Block(
|
|
107
|
-
_,
|
|
108
|
-
) => "Block handler contractRegister failed, please fix the error to keep the indexer running smoothly"
|
|
109
|
-
},
|
|
65
|
+
~msg="Event contractRegister failed, please fix the error to keep the indexer running smoothly",
|
|
110
66
|
~logger=run->RunScope.contractRegisterLogger,
|
|
111
67
|
)
|
|
112
68
|
| () => scope->RunScope.resolve
|
|
@@ -117,221 +73,6 @@ let runContractRegistersOrThrow = async (
|
|
|
117
73
|
registrations
|
|
118
74
|
}
|
|
119
75
|
|
|
120
|
-
// A response's events and the block passes of the same blocks, in the order
|
|
121
|
-
// graph-node runs their triggers: a `once` handler first in its block, the
|
|
122
|
-
// other block handlers after the block's logs and calls
|
|
123
|
-
// (chain/ethereum/src/trigger.rs, `impl Ord for EthereumTrigger`).
|
|
124
|
-
let mergeRegisterItems = (~eventItems: array<Internal.item>, ~blockItems: array<Internal.item>) => {
|
|
125
|
-
let merged = []
|
|
126
|
-
let i = ref(0)
|
|
127
|
-
let j = ref(0)
|
|
128
|
-
while i.contents < eventItems->Array.length || j.contents < blockItems->Array.length {
|
|
129
|
-
let takeBlock = switch (eventItems->Array.get(i.contents), blockItems->Array.get(j.contents)) {
|
|
130
|
-
| (None, _) => true
|
|
131
|
-
| (_, None) => false
|
|
132
|
-
| (Some(event), Some(block)) =>
|
|
133
|
-
let eventBlock = event->Internal.getItemBlockNumber
|
|
134
|
-
let blockBlock = block->Internal.getItemBlockNumber
|
|
135
|
-
blockBlock < eventBlock || (blockBlock === eventBlock && block->Internal.itemRunsFirst)
|
|
136
|
-
}
|
|
137
|
-
if takeBlock {
|
|
138
|
-
merged->Array.push(blockItems->Array.getUnsafe(j.contents))
|
|
139
|
-
j := j.contents + 1
|
|
140
|
-
} else {
|
|
141
|
-
merged->Array.push(eventItems->Array.getUnsafe(i.contents))
|
|
142
|
-
i := i.contents + 1
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
merged
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// An unfiltered handler has a pass for every block, so a run with block passes
|
|
149
|
-
// starts them a chunk at a time, in chain order: each chunk reads what the ones
|
|
150
|
-
// before it saved, and a pass is started before any later one of its chunk,
|
|
151
|
-
// which is the order the runtime hands out its slots in.
|
|
152
|
-
let blockRegisterChunk = 2048
|
|
153
|
-
// Block passes built at once: a response can span millions of blocks.
|
|
154
|
-
let blockRegisterWindow = 10_000
|
|
155
|
-
let maxResponseBlockPasses = 50_000
|
|
156
|
-
|
|
157
|
-
let runRegisterPassesOrThrow = async (
|
|
158
|
-
~eventItems: array<Internal.item>,
|
|
159
|
-
~blockItems: array<Internal.item>,
|
|
160
|
-
~runtime: HandlerRuntime.t,
|
|
161
|
-
~chainState: ChainState.t,
|
|
162
|
-
) => {
|
|
163
|
-
let items = mergeRegisterItems(~eventItems, ~blockItems)
|
|
164
|
-
let registrations = []
|
|
165
|
-
let start = ref(0)
|
|
166
|
-
while start.contents < items->Array.length {
|
|
167
|
-
let chunk = items->Array.slice(~start=start.contents, ~end=start.contents + blockRegisterChunk)
|
|
168
|
-
registrations
|
|
169
|
-
->Array.pushMany(
|
|
170
|
-
await runContractRegistersOrThrow(~itemsWithContractRegister=chunk, ~runtime, ~chainState),
|
|
171
|
-
)
|
|
172
|
-
->ignore
|
|
173
|
-
start := start.contents + blockRegisterChunk
|
|
174
|
-
}
|
|
175
|
-
registrations
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Passes of a chunk finish in any order, and of two registrations of one
|
|
179
|
-
// address the store keeps the first: it has to be the earlier block's.
|
|
180
|
-
let sortRegistrations = (registrations: array<AddressStore.registration>) =>
|
|
181
|
-
registrations->Array.toSorted((a, b) =>
|
|
182
|
-
switch Int.compare(a.registrationBlock, b.registrationBlock) {
|
|
183
|
-
| 0. => Int.compare(a.creationRound->Option.getOr(1), b.creationRound->Option.getOr(1))
|
|
184
|
-
| order => order
|
|
185
|
-
}
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
// A response's event passes with the block passes of the blocks after the last
|
|
189
|
-
// one passed, through `through`, a window of block passes at a time. Returns
|
|
190
|
-
// the registrations and the last block passed, if the block passes advanced.
|
|
191
|
-
let runResponsePassesOrThrow = async (
|
|
192
|
-
~eventItems: array<Internal.item>,
|
|
193
|
-
~through,
|
|
194
|
-
~runtime: HandlerRuntime.t,
|
|
195
|
-
~chainState: ChainState.t,
|
|
196
|
-
) => {
|
|
197
|
-
let registrations = []
|
|
198
|
-
let eventIdx = ref(0)
|
|
199
|
-
let passedThrough = ref(None)
|
|
200
|
-
let after = ref(chainState->ChainState.blockRegisterThrough->Option.getOr(through))
|
|
201
|
-
let isDone = ref(false)
|
|
202
|
-
while !isDone.contents {
|
|
203
|
-
let (blockItems, covered) = switch chainState->ChainState.blockRegisterItemsAfter(
|
|
204
|
-
~after=after.contents,
|
|
205
|
-
~through,
|
|
206
|
-
~limit=blockRegisterWindow,
|
|
207
|
-
) {
|
|
208
|
-
| Some((blockItems, covered)) => (blockItems, Some(covered))
|
|
209
|
-
| None => ([], None)
|
|
210
|
-
}
|
|
211
|
-
// The events up to the window's last block go with it, and the last
|
|
212
|
-
// window takes the rest.
|
|
213
|
-
let eventEnd = switch covered {
|
|
214
|
-
| Some(covered) if covered < through =>
|
|
215
|
-
let idx = ref(eventIdx.contents)
|
|
216
|
-
while (
|
|
217
|
-
idx.contents < eventItems->Array.length &&
|
|
218
|
-
eventItems->Array.getUnsafe(idx.contents)->Internal.getItemBlockNumber <= covered
|
|
219
|
-
) {
|
|
220
|
-
idx := idx.contents + 1
|
|
221
|
-
}
|
|
222
|
-
idx.contents
|
|
223
|
-
| _ => eventItems->Array.length
|
|
224
|
-
}
|
|
225
|
-
let startedAt = Date.now()
|
|
226
|
-
let windowRegistrations = await runRegisterPassesOrThrow(
|
|
227
|
-
~eventItems=eventItems->Array.slice(~start=eventIdx.contents, ~end=eventEnd),
|
|
228
|
-
~blockItems,
|
|
229
|
-
~runtime,
|
|
230
|
-
~chainState,
|
|
231
|
-
)
|
|
232
|
-
chainState
|
|
233
|
-
->ChainState.logger
|
|
234
|
-
->Logger.trace(
|
|
235
|
-
"Ran register passes with block passes",
|
|
236
|
-
~params={
|
|
237
|
-
"after": after.contents,
|
|
238
|
-
"through": covered,
|
|
239
|
-
"blockPasses": blockItems->Array.length,
|
|
240
|
-
"eventPasses": eventEnd - eventIdx.contents,
|
|
241
|
-
"registrations": windowRegistrations->Array.length,
|
|
242
|
-
"ms": Date.now() -. startedAt,
|
|
243
|
-
},
|
|
244
|
-
)
|
|
245
|
-
registrations->Array.pushMany(windowRegistrations)->ignore
|
|
246
|
-
eventIdx := eventEnd
|
|
247
|
-
switch covered {
|
|
248
|
-
| Some(covered) =>
|
|
249
|
-
passedThrough := Some(covered)
|
|
250
|
-
after := covered
|
|
251
|
-
isDone := covered >= through && eventIdx.contents >= eventItems->Array.length
|
|
252
|
-
| None => isDone := true
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
(registrations->sortRegistrations, passedThrough.contents)
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// A subgraph's register pass for one event can cost a dozen contract calls, and
|
|
259
|
-
// a response is applied only when every pass of it is done: a 5,000-event
|
|
260
|
-
// response of PairCreated made PancakeSwap v2 wait for ~15,000 calls before it
|
|
261
|
-
// committed anything. A response with more register passes than the calls can
|
|
262
|
-
// answer promptly is cut after a block and the rest fetched again; HyperSync
|
|
263
|
-
// answers that far faster than the RPC does. The runtime reports the calls its
|
|
264
|
-
// finished passes made (`__envioSubgraphRegisterCostPerItem`); until it has
|
|
265
|
-
// seen enough passes the cost is assumed to be high, and a run whose passes
|
|
266
|
-
// make no calls is never cut.
|
|
267
|
-
let registerCallsPerItem: unit => option<float> = %raw(`() => {
|
|
268
|
-
const cost = globalThis.__envioSubgraphRegisterCostPerItem
|
|
269
|
-
const value = cost ? cost() : undefined
|
|
270
|
-
return value === undefined ? undefined : value
|
|
271
|
-
}`)
|
|
272
|
-
|
|
273
|
-
// A subgraph's register store keeps an entity's past versions for the passes
|
|
274
|
-
// still to read them, and none starts below the lowest partition frontier.
|
|
275
|
-
let reportRegisterFrontier: (int, int) => unit = %raw(`(chainId, block) => {
|
|
276
|
-
const report = globalThis.__envioSubgraphRegisterFrontier
|
|
277
|
-
if (report) report(chainId, block)
|
|
278
|
-
}`)
|
|
279
|
-
|
|
280
|
-
let registerCallsPerChunk = 3000.
|
|
281
|
-
let unknownCostChunk = 100
|
|
282
|
-
let minRegisterChunk = 100
|
|
283
|
-
|
|
284
|
-
let registerChunkLimit = () =>
|
|
285
|
-
if !Env.subgraphMode.contents {
|
|
286
|
-
None
|
|
287
|
-
} else {
|
|
288
|
-
switch Env.subgraphRegisterChunk {
|
|
289
|
-
| Some(limit) => limit > 0 ? Some(limit) : None
|
|
290
|
-
| None =>
|
|
291
|
-
switch registerCallsPerItem() {
|
|
292
|
-
| None => Some(unknownCostChunk)
|
|
293
|
-
| Some(cost) if cost < 0.5 => None
|
|
294
|
-
| Some(cost) =>
|
|
295
|
-
Some(Pervasives.max(minRegisterChunk, (registerCallsPerChunk /. cost)->Float.toInt))
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// The items and last block of `response` up to the block holding the `limit`th
|
|
301
|
-
// item that has a register pass. Whole blocks only: a block's items are never
|
|
302
|
-
// split between two responses.
|
|
303
|
-
let cutAtRegisterLimit = (items: array<Internal.item>, ~latestFetchedBlock, ~limit) => {
|
|
304
|
-
let seen = ref(0)
|
|
305
|
-
let cutIdx = ref(-1)
|
|
306
|
-
let idx = ref(0)
|
|
307
|
-
while cutIdx.contents < 0 && idx.contents < items->Array.length {
|
|
308
|
-
if items->Array.getUnsafe(idx.contents)->hasContractRegister {
|
|
309
|
-
seen := seen.contents + 1
|
|
310
|
-
if seen.contents >= limit {
|
|
311
|
-
cutIdx := idx.contents
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
idx := idx.contents + 1
|
|
315
|
-
}
|
|
316
|
-
if cutIdx.contents < 0 {
|
|
317
|
-
(items, latestFetchedBlock)
|
|
318
|
-
} else {
|
|
319
|
-
let cutBlock = items->Array.getUnsafe(cutIdx.contents)->Internal.getItemBlockNumber
|
|
320
|
-
let last = ref(cutIdx.contents)
|
|
321
|
-
while (
|
|
322
|
-
last.contents + 1 < items->Array.length &&
|
|
323
|
-
items->Array.getUnsafe(last.contents + 1)->Internal.getItemBlockNumber <= cutBlock
|
|
324
|
-
) {
|
|
325
|
-
last := last.contents + 1
|
|
326
|
-
}
|
|
327
|
-
if last.contents + 1 >= items->Array.length && cutBlock >= latestFetchedBlock {
|
|
328
|
-
(items, latestFetchedBlock)
|
|
329
|
-
} else {
|
|
330
|
-
(items->Array.slice(~start=0, ~end=last.contents + 1), cutBlock)
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
76
|
let rec onQueryResponse = async (
|
|
336
77
|
state: IndexerState.t,
|
|
337
78
|
{chainId, response, query}: partitionQueryResponse,
|
|
@@ -353,11 +94,6 @@ let rec onQueryResponse = async (
|
|
|
353
94
|
stats,
|
|
354
95
|
knownHeight,
|
|
355
96
|
} = response
|
|
356
|
-
let (parsedQueueItems, latestFetchedBlockNumber) = switch registerChunkLimit() {
|
|
357
|
-
| Some(limit) =>
|
|
358
|
-
parsedQueueItems->cutAtRegisterLimit(~latestFetchedBlock=latestFetchedBlockNumber, ~limit)
|
|
359
|
-
| None => (parsedQueueItems, latestFetchedBlockNumber)
|
|
360
|
-
}
|
|
361
97
|
|
|
362
98
|
chainState->ChainState.recordBlockRangeFetch(
|
|
363
99
|
~totalTimeElapsed=stats.totalTimeElapsed,
|
|
@@ -480,12 +216,7 @@ let rec onQueryResponse = async (
|
|
|
480
216
|
|
|
481
217
|
// Re-check staleness: contract registration is async, so the chain state
|
|
482
218
|
// may have rolled back by the time we apply the fetched items.
|
|
483
|
-
let proceed = (
|
|
484
|
-
~newRegistrations,
|
|
485
|
-
~blockRegisterThrough=?,
|
|
486
|
-
~newItems=newItems,
|
|
487
|
-
~latestFetchedBlock=latestFetchedBlockNumber,
|
|
488
|
-
) =>
|
|
219
|
+
let proceed = (~newRegistrations) =>
|
|
489
220
|
if !(state->IndexerState.isStale(~stateId)) {
|
|
490
221
|
applyQueryResponse(
|
|
491
222
|
state,
|
|
@@ -493,93 +224,17 @@ let rec onQueryResponse = async (
|
|
|
493
224
|
~newItems,
|
|
494
225
|
~newRegistrations,
|
|
495
226
|
~knownHeight,
|
|
496
|
-
~latestFetchedBlock,
|
|
227
|
+
~latestFetchedBlock=latestFetchedBlockNumber,
|
|
497
228
|
~query,
|
|
498
229
|
)
|
|
499
|
-
switch blockRegisterThrough {
|
|
500
|
-
| Some(through) => chainState->ChainState.markBlockRegistered(~through)
|
|
501
|
-
| None => ()
|
|
502
|
-
}
|
|
503
230
|
ChainMetadata.stage(state)
|
|
504
231
|
scheduleFetch()
|
|
505
232
|
scheduleProcessing()
|
|
506
233
|
}
|
|
507
234
|
|
|
508
|
-
// The block passes run with the response that first fetches their
|
|
509
|
-
// blocks, among its events in chain order, and after every earlier unit
|
|
510
|
-
// of the chain's register work.
|
|
511
|
-
let blockRegisterCeiling = Pervasives.min(
|
|
512
|
-
latestFetchedBlockNumber,
|
|
513
|
-
Pervasives.max(knownHeight, chainState->ChainState.knownHeight),
|
|
514
|
-
)
|
|
515
|
-
let withBlockPasses =
|
|
516
|
-
chainState->ChainState.hasBlockRegisters &&
|
|
517
|
-
(itemsWithContractRegister->Utils.Array.notEmpty ||
|
|
518
|
-
chainState->ChainState.canAdvanceBlockRegisters(~through=blockRegisterCeiling))
|
|
519
|
-
|
|
520
235
|
switch itemsWithContractRegister {
|
|
521
|
-
| _ if withBlockPasses =>
|
|
522
|
-
let (previous, finish) = chainState->ChainState.queueBlockRegisterRun
|
|
523
|
-
let held =
|
|
524
|
-
chainState->ChainState.holdExtraBudget(
|
|
525
|
-
~items=Pervasives.max(0, newItems->Array.length - query.itemsEst),
|
|
526
|
-
)
|
|
527
|
-
await previous
|
|
528
|
-
if state->IndexerState.isStale(~stateId) {
|
|
529
|
-
chainState->ChainState.releaseExtraBudget(held)
|
|
530
|
-
finish()
|
|
531
|
-
scheduleFetch()
|
|
532
|
-
} else {
|
|
533
|
-
// A response spanning millions of blocks of an unfiltered handler is
|
|
534
|
-
// applied only once all their passes ran, so it carries at most
|
|
535
|
-
// `maxResponseBlockPasses` past its first block and is cut after
|
|
536
|
-
// them; the partition fetches the rest again.
|
|
537
|
-
let cutAt = switch chainState->ChainState.blockRegisterItemsAfter(
|
|
538
|
-
~after=Pervasives.max(
|
|
539
|
-
chainState->ChainState.blockRegisterThrough->Option.getOr(blockRegisterCeiling),
|
|
540
|
-
query.fromBlock - 1,
|
|
541
|
-
),
|
|
542
|
-
~through=blockRegisterCeiling,
|
|
543
|
-
~limit=maxResponseBlockPasses,
|
|
544
|
-
) {
|
|
545
|
-
| Some((_, covered)) if covered < blockRegisterCeiling => Some(covered)
|
|
546
|
-
| _ => None
|
|
547
|
-
}
|
|
548
|
-
let through = cutAt->Option.getOr(blockRegisterCeiling)
|
|
549
|
-
let (newItems, eventItems, latestFetchedBlock) = if cutAt !== None {
|
|
550
|
-
let isKept = item => item->Internal.getItemBlockNumber <= through
|
|
551
|
-
(
|
|
552
|
-
newItems->Array.filter(isKept),
|
|
553
|
-
itemsWithContractRegister->Array.filter(isKept),
|
|
554
|
-
through,
|
|
555
|
-
)
|
|
556
|
-
} else {
|
|
557
|
-
(newItems, itemsWithContractRegister, latestFetchedBlockNumber)
|
|
558
|
-
}
|
|
559
|
-
switch await runResponsePassesOrThrow(~eventItems, ~through, ~runtime, ~chainState) {
|
|
560
|
-
| exception exn =>
|
|
561
|
-
finish()
|
|
562
|
-
IndexerState.errorExit(
|
|
563
|
-
state,
|
|
564
|
-
exn->ErrorHandling.make(~logger=chainState->ChainState.logger),
|
|
565
|
-
)
|
|
566
|
-
| (newRegistrations, blockRegisterThrough) =>
|
|
567
|
-
chainState->ChainState.releaseExtraBudget(held)
|
|
568
|
-
proceed(~newRegistrations, ~blockRegisterThrough?, ~newItems, ~latestFetchedBlock)
|
|
569
|
-
finish()
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
236
|
| [] => proceed(~newRegistrations=[])
|
|
573
237
|
| _ =>
|
|
574
|
-
// A subgraph's register passes run in chunks, long enough for the pool
|
|
575
|
-
// to admit queries on top of a response it doesn't count yet.
|
|
576
|
-
let held = Env.subgraphMode.contents
|
|
577
|
-
? Some(
|
|
578
|
-
chainState->ChainState.holdExtraBudget(
|
|
579
|
-
~items=Pervasives.max(0, newItems->Array.length - query.itemsEst),
|
|
580
|
-
),
|
|
581
|
-
)
|
|
582
|
-
: None
|
|
583
238
|
switch await runContractRegistersOrThrow(
|
|
584
239
|
~itemsWithContractRegister,
|
|
585
240
|
~runtime,
|
|
@@ -590,9 +245,7 @@ let rec onQueryResponse = async (
|
|
|
590
245
|
state,
|
|
591
246
|
exn->ErrorHandling.make(~logger=chainState->ChainState.logger),
|
|
592
247
|
)
|
|
593
|
-
| newRegistrations =>
|
|
594
|
-
held->Option.forEach(held => chainState->ChainState.releaseExtraBudget(held))
|
|
595
|
-
proceed(~newRegistrations)
|
|
248
|
+
| newRegistrations => proceed(~newRegistrations)
|
|
596
249
|
}
|
|
597
250
|
}
|
|
598
251
|
}
|
|
@@ -617,21 +270,6 @@ and applyQueryResponse = (
|
|
|
617
270
|
~knownHeight,
|
|
618
271
|
)
|
|
619
272
|
|
|
620
|
-
if Env.subgraphMode.contents {
|
|
621
|
-
let fetchState = chainState->ChainState.fetchState
|
|
622
|
-
switch fetchState.optimizedPartitions->FetchState.OptimizedPartitions.getLatestFullyFetchedBlock {
|
|
623
|
-
| Some(frontier) =>
|
|
624
|
-
// A block pass still to run reads at its own block, which can be below
|
|
625
|
-
// every partition.
|
|
626
|
-
let frontier = switch fetchState.blockRegisterThrough {
|
|
627
|
-
| Some(through) => Pervasives.min(frontier, through)
|
|
628
|
-
| None => frontier
|
|
629
|
-
}
|
|
630
|
-
reportRegisterFrontier(chainId->ChainId.toInt, frontier)
|
|
631
|
-
| None => ()
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
|
|
635
273
|
// In auto-exit mode, set endBlock to the first event's block when events arrive.
|
|
636
274
|
if state->IndexerState.exitAfterFirstEventBlock {
|
|
637
275
|
switch newItems->Array.find(item =>
|
|
@@ -667,68 +305,6 @@ let finishWaitingForNewBlock = (
|
|
|
667
305
|
scheduleProcessing()
|
|
668
306
|
}
|
|
669
307
|
|
|
670
|
-
// Block passes no response will run: the blocks every partition has already
|
|
671
|
-
// fetched (or, with no partition, the blocks up to the head), up to a limit per
|
|
672
|
-
// run. Owns its error boundary, as it isn't awaited.
|
|
673
|
-
let catchUpBlockRegisters = async (
|
|
674
|
-
state: IndexerState.t,
|
|
675
|
-
~chainId,
|
|
676
|
-
~runtime,
|
|
677
|
-
~stateId,
|
|
678
|
-
~scheduleFetch,
|
|
679
|
-
~scheduleProcessing,
|
|
680
|
-
) => {
|
|
681
|
-
let chainState = state->IndexerState.getChainState(~chainId)
|
|
682
|
-
if chainState->ChainState.isBlockRegisterIdle {
|
|
683
|
-
switch chainState->ChainState.nextBlockRegisterItems(
|
|
684
|
-
~through=chainState->ChainState.blockRegisterFrontier,
|
|
685
|
-
~limit=blockRegisterWindow,
|
|
686
|
-
) {
|
|
687
|
-
| None => ()
|
|
688
|
-
| Some((blockItems, through)) =>
|
|
689
|
-
let (_, finish) = chainState->ChainState.queueBlockRegisterRun
|
|
690
|
-
let startedAt = Date.now()
|
|
691
|
-
switch await runRegisterPassesOrThrow(~eventItems=[], ~blockItems, ~runtime, ~chainState) {
|
|
692
|
-
| exception exn =>
|
|
693
|
-
finish()
|
|
694
|
-
IndexerState.errorExit(
|
|
695
|
-
state,
|
|
696
|
-
exn->ErrorHandling.make(~logger=chainState->ChainState.logger),
|
|
697
|
-
)
|
|
698
|
-
| registrations =>
|
|
699
|
-
let isStale = state->IndexerState.isStale(~stateId)
|
|
700
|
-
chainState
|
|
701
|
-
->ChainState.logger
|
|
702
|
-
->Logger.trace(
|
|
703
|
-
"Ran block passes",
|
|
704
|
-
~params={
|
|
705
|
-
"through": through,
|
|
706
|
-
"blockPasses": blockItems->Array.length,
|
|
707
|
-
"registrations": registrations->Array.length,
|
|
708
|
-
"stale": isStale,
|
|
709
|
-
"ms": Date.now() -. startedAt,
|
|
710
|
-
},
|
|
711
|
-
)
|
|
712
|
-
if !isStale {
|
|
713
|
-
chainState->ChainState.applyBlockRegisters(
|
|
714
|
-
~registrations=registrations->sortRegistrations,
|
|
715
|
-
~through,
|
|
716
|
-
)
|
|
717
|
-
}
|
|
718
|
-
finish()
|
|
719
|
-
|
|
720
|
-
// A run dropped as stale is run again: the fetch tick that would have
|
|
721
|
-
// started it found this one in flight and passed.
|
|
722
|
-
if !isStale {
|
|
723
|
-
ChainMetadata.stage(state)
|
|
724
|
-
scheduleProcessing()
|
|
725
|
-
}
|
|
726
|
-
scheduleFetch()
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
|
|
732
308
|
let fetchChain = async (
|
|
733
309
|
state: IndexerState.t,
|
|
734
310
|
chainId,
|
|
@@ -741,16 +317,6 @@ let fetchChain = async (
|
|
|
741
317
|
) => {
|
|
742
318
|
let chainState = state->IndexerState.getChainState(~chainId)
|
|
743
319
|
if !(state->IndexerState.isResolvingReorg) && !(state->IndexerState.isStopped) {
|
|
744
|
-
if chainState->ChainState.hasBlockRegisters {
|
|
745
|
-
catchUpBlockRegisters(
|
|
746
|
-
state,
|
|
747
|
-
~chainId,
|
|
748
|
-
~runtime,
|
|
749
|
-
~stateId,
|
|
750
|
-
~scheduleFetch,
|
|
751
|
-
~scheduleProcessing,
|
|
752
|
-
)->Promise.ignore
|
|
753
|
-
}
|
|
754
320
|
let isRealtime = state->IndexerState.isRealtime
|
|
755
321
|
let sourceManager = chainState->ChainState.sourceManager
|
|
756
322
|
|
|
@@ -767,12 +333,7 @@ let fetchChain = async (
|
|
|
767
333
|
try {
|
|
768
334
|
await chainState->ChainState.dispatch(
|
|
769
335
|
~waitForNewBlock=(~knownHeight) =>
|
|
770
|
-
sourceManager->SourceManager.waitForNewBlock(
|
|
771
|
-
~knownHeight,
|
|
772
|
-
~isRealtime,
|
|
773
|
-
~reducedPolling,
|
|
774
|
-
~blockThrottle=(chainState->ChainState.chainConfig).blockThrottle,
|
|
775
|
-
),
|
|
336
|
+
sourceManager->SourceManager.waitForNewBlock(~knownHeight, ~isRealtime, ~reducedPolling),
|
|
776
337
|
~onNewBlock=(~knownHeight) =>
|
|
777
338
|
finishWaitingForNewBlock(
|
|
778
339
|
state,
|