1- type progressedChain = {
2- chainId : int ,
1+ open Belt
2+
3+ type chainAfterBatch = {
34 batchSize : int ,
45 progressBlockNumber : int ,
56 totalEventsProcessed : int ,
7+ fetchState : FetchState .t ,
8+ dcsToStore : option <array <FetchState .indexingContract >>,
9+ isProgressAtHeadWhenBatchCreated : bool ,
10+ }
11+
12+ type chainBeforeBatch = {
13+ fetchState : FetchState .t ,
14+ progressBlockNumber : int ,
15+ sourceBlockNumber : int ,
16+ totalEventsProcessed : int ,
617}
718
819type t = {
920 items : array <Internal .item >,
10- progressedChains : array <progressedChain >,
11- updatedFetchStates : ChainMap .t <FetchState .t >,
12- dcsToStoreByChainId : dict <array <FetchState .indexingContract >>,
13- creationTimeMs : int ,
21+ progressedChainsById : dict <chainAfterBatch >,
1422}
1523
1624/**
@@ -21,7 +29,7 @@ let getOrderedNextChain = (fetchStates: ChainMap.t<FetchState.t>, ~batchSizePerC
2129 let earliestChainTimestamp = ref (0 )
2230 let chainKeys = fetchStates -> ChainMap .keys
2331 for idx in 0 to chainKeys -> Array .length - 1 {
24- let chain = chainKeys -> Array .get (idx )
32+ let chain = chainKeys -> Array .getUnsafe (idx )
2533 let fetchState = fetchStates -> ChainMap .get (chain )
2634 if fetchState -> FetchState .isActivelyIndexing {
2735 let timestamp = fetchState -> FetchState .getTimestampAt (
@@ -74,14 +82,116 @@ let hasMultichainReadyItem = (
7482 }
7583}
7684
77- let prepareOrderedBatch = (
78- ~batchSizeTarget ,
79- ~fetchStates : ChainMap .t <FetchState .t >,
80- ~mutBatchSizePerChain : dict <int >,
81- ) => {
85+ let getProgressedChainsById = {
86+ let getChainAfterBatchIfProgressed = (
87+ ~chainBeforeBatch : chainBeforeBatch ,
88+ ~updatedFetchState ,
89+ ~batchSize ,
90+ ~dcsToStore ,
91+ ) => {
92+ let nextProgressBlockNumber = updatedFetchState -> FetchState .getProgressBlockNumber
93+
94+ // The check is sufficient, since we guarantee to include a full block in a batch
95+ // Also, this might be true even if batchSize is 0,
96+ // eg when indexing at the head and chain doesn't have items in a block
97+ if chainBeforeBatch .progressBlockNumber < nextProgressBlockNumber {
98+ Some (
99+ (
100+ {
101+ batchSize ,
102+ progressBlockNumber : nextProgressBlockNumber ,
103+ totalEventsProcessed : chainBeforeBatch .totalEventsProcessed + batchSize ,
104+ dcsToStore ,
105+ fetchState : updatedFetchState ,
106+ isProgressAtHeadWhenBatchCreated : nextProgressBlockNumber >=
107+ chainBeforeBatch .sourceBlockNumber ,
108+ }: chainAfterBatch
109+ ),
110+ )
111+ } else {
112+ None
113+ }
114+ }
115+
116+ (~chainsBeforeBatch : ChainMap .t <chainBeforeBatch >, ~batchSizePerChain : dict <int >) => {
117+ let progressedChainsById = Js .Dict .empty ()
118+
119+ // Needed to:
120+ // - Recalculate the computed queue sizes
121+ // - Accumulate registered dynamic contracts to store in the db
122+ // - Trigger onBlock pointer update
123+ chainsBeforeBatch
124+ -> ChainMap .values
125+ -> Array .forEachU (chainBeforeBatch => {
126+ let fetchState = chainBeforeBatch .fetchState
127+ switch switch batchSizePerChain -> Utils .Dict .dangerouslyGetNonOption (
128+ fetchState .chainId -> Int .toString ,
129+ ) {
130+ | Some (batchSize ) =>
131+ let leftItems = fetchState .buffer -> Js .Array2 .sliceFrom (batchSize )
132+ switch fetchState .dcsToStore {
133+ | [] =>
134+ getChainAfterBatchIfProgressed (
135+ ~chainBeforeBatch ,
136+ ~batchSize ,
137+ ~dcsToStore = None ,
138+ ~updatedFetchState = fetchState -> FetchState .updateInternal (~mutItems = leftItems ),
139+ )
140+
141+ | dcs => {
142+ let leftDcsToStore = []
143+ let batchDcs = []
144+ let updatedFetchState =
145+ fetchState -> FetchState .updateInternal (~mutItems = leftItems , ~dcsToStore = leftDcsToStore )
146+ let nextProgressBlockNumber = updatedFetchState -> FetchState .getProgressBlockNumber
147+
148+ dcs -> Array .forEach (dc => {
149+ // Important: This should be a registering block number.
150+ // This works for now since dc.startBlock is a registering block number.
151+ if dc .startBlock <= nextProgressBlockNumber {
152+ batchDcs -> Array .push (dc )
153+ } else {
154+ // Mutate the array we passed to the updateInternal beforehand
155+ leftDcsToStore -> Array .push (dc )
156+ }
157+ })
158+
159+ getChainAfterBatchIfProgressed (
160+ ~chainBeforeBatch ,
161+ ~batchSize ,
162+ ~dcsToStore = Some (batchDcs ),
163+ ~updatedFetchState ,
164+ )
165+ }
166+ }
167+ // Skip not affected chains
168+ | None =>
169+ getChainAfterBatchIfProgressed (
170+ ~chainBeforeBatch ,
171+ ~batchSize = 0 ,
172+ ~dcsToStore = None ,
173+ ~updatedFetchState = chainBeforeBatch .fetchState ,
174+ )
175+ } {
176+ | Some (progressedChain ) =>
177+ progressedChainsById -> Utils .Dict .setByInt (
178+ chainBeforeBatch .fetchState .chainId ,
179+ progressedChain ,
180+ )
181+ | None => ()
182+ }
183+ })
184+
185+ progressedChainsById
186+ }
187+ }
188+
189+ let prepareOrderedBatch = (~chainsBeforeBatch : ChainMap .t <chainBeforeBatch >, ~batchSizeTarget ) => {
82190 let batchSize = ref (0 )
83191 let isFinished = ref (false )
192+ let mutBatchSizePerChain = Js .Dict .empty ()
84193 let items = []
194+ let fetchStates = chainsBeforeBatch -> ChainMap .map (chainBeforeBatch => chainBeforeBatch .fetchState )
85195
86196 while batchSize .contents < batchSizeTarget && ! isFinished .contents {
87197 switch fetchStates -> getOrderedNextChain (~batchSizePerChain = mutBatchSizePerChain ) {
@@ -116,23 +226,30 @@ let prepareOrderedBatch = (
116226 }
117227 }
118228
119- items
229+ {
230+ items ,
231+ progressedChainsById : getProgressedChainsById (
232+ ~chainsBeforeBatch ,
233+ ~batchSizePerChain = mutBatchSizePerChain ,
234+ ),
235+ }
120236}
121237
122238let prepareUnorderedBatch = (
239+ ~chainsBeforeBatch : ChainMap .t <chainBeforeBatch >,
123240 ~batchSizeTarget ,
124- ~fetchStates : ChainMap .t <FetchState .t >,
125- ~mutBatchSizePerChain : dict <int >,
126241) => {
127242 let preparedFetchStates =
128- fetchStates
243+ chainsBeforeBatch
129244 -> ChainMap .values
245+ -> Js .Array2 .map (chainBeforeBatch => chainBeforeBatch .fetchState )
130246 -> FetchState .filterAndSortForUnorderedBatch (~batchSizeTarget )
131247
132248 let chainIdx = ref (0 )
133249 let preparedNumber = preparedFetchStates -> Array .length
134250 let batchSize = ref (0 )
135251
252+ let mutBatchSizePerChain = Js .Dict .empty ()
136253 let items = []
137254
138255 // Accumulate items for all actively indexing chains
@@ -156,5 +273,28 @@ let prepareUnorderedBatch = (
156273 chainIdx := chainIdx .contents + 1
157274 }
158275
159- items
160- }
276+ {
277+ items ,
278+ progressedChainsById : getProgressedChainsById (
279+ ~chainsBeforeBatch ,
280+ ~batchSizePerChain = mutBatchSizePerChain ,
281+ ),
282+ }
283+ }
284+
285+ let make = (
286+ ~chainsBeforeBatch : ChainMap .t <chainBeforeBatch >,
287+ ~multichain : InternalConfig .multichain ,
288+ ~batchSizeTarget ,
289+ ) => {
290+ if (
291+ switch multichain {
292+ | Unordered => true
293+ | Ordered => chainsBeforeBatch -> ChainMap .size === 1
294+ }
295+ ) {
296+ prepareUnorderedBatch (~chainsBeforeBatch , ~batchSizeTarget )
297+ } else {
298+ prepareOrderedBatch (~chainsBeforeBatch , ~batchSizeTarget )
299+ }
300+ }
0 commit comments