@subsquid/batch-processor 0.1.0 → 0.2.0-portal-api.493495

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/lib/database.d.ts CHANGED
@@ -10,9 +10,11 @@ export interface FinalTxInfo {
10
10
  }
11
11
  export interface FinalDatabase<S> {
12
12
  supportsHotBlocks?: false;
13
- connect(): Promise<HashAndHeight>;
13
+ connect(): Promise<FinalDatabaseState>;
14
14
  transact(info: FinalTxInfo, cb: (store: S) => Promise<void>): Promise<void>;
15
15
  }
16
+ export interface FinalDatabaseState extends HashAndHeight {
17
+ }
16
18
  export interface HotTxInfo {
17
19
  finalizedHead: HashAndHeight;
18
20
  baseHead: HashAndHeight;
@@ -22,11 +24,7 @@ export interface HotDatabase<S> {
22
24
  supportsHotBlocks: true;
23
25
  connect(): Promise<HotDatabaseState>;
24
26
  transact(info: FinalTxInfo, cb: (store: S) => Promise<void>): Promise<void>;
25
- /**
26
- * @deprecated
27
- */
28
- transactHot(info: HotTxInfo, cb: (store: S, block: HashAndHeight) => Promise<void>): Promise<void>;
29
- transactHot2?(info: HotTxInfo, cb: (store: S, blockSliceStart: number, blockSliceEnd: number) => Promise<void>): Promise<void>;
27
+ transactHot2(info: HotTxInfo, cb: (store: S, blockSliceStart: number, blockSliceEnd: number) => Promise<void>): Promise<void>;
30
28
  }
31
29
  export interface HotDatabaseState extends HashAndHeight {
32
30
  top: HashAndHeight[];
@@ -1 +1 @@
1
- {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;AAG3D,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,aAAa,CAAA;IACvB,QAAQ,EAAE,aAAa,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;CACnB;AAGD,MAAM,WAAW,aAAa,CAAC,CAAC;IAC5B,iBAAiB,CAAC,EAAE,KAAK,CAAA;IACzB,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC,CAAA;IACjC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9E;AAGD,MAAM,WAAW,SAAS;IACtB,aAAa,EAAE,aAAa,CAAA;IAC5B,QAAQ,EAAE,aAAa,CAAA;IACvB,SAAS,EAAE,aAAa,EAAE,CAAA;CAC7B;AAGD,MAAM,WAAW,WAAW,CAAC,CAAC;IAC1B,iBAAiB,EAAE,IAAI,CAAA;IACvB,OAAO,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACpC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3E;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAElG,YAAY,CAAC,CACT,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAChF,OAAO,CAAC,IAAI,CAAC,CAAA;CACnB;AAGD,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACnD,GAAG,EAAE,aAAa,EAAE,CAAA;CACvB;AAGD,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACf"}
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;AAG3D,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,aAAa,CAAA;IACvB,QAAQ,EAAE,aAAa,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;CACnB;AAGD,MAAM,WAAW,aAAa,CAAC,CAAC;IAC5B,iBAAiB,CAAC,EAAE,KAAK,CAAA;IACzB,OAAO,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACtC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9E;AAGD,MAAM,WAAW,kBAAmB,SAAQ,aAAa;CAAG;AAG5D,MAAM,WAAW,SAAS;IACtB,aAAa,EAAE,aAAa,CAAA;IAC5B,QAAQ,EAAE,aAAa,CAAA;IACvB,SAAS,EAAE,aAAa,EAAE,CAAA;CAC7B;AAGD,MAAM,WAAW,WAAW,CAAC,CAAC;IAC1B,iBAAiB,EAAE,IAAI,CAAA;IACvB,OAAO,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACpC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE3E,YAAY,CACR,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAChF,OAAO,CAAC,IAAI,CAAC,CAAA;CACnB;AAGD,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACnD,GAAG,EAAE,aAAa,EAAE,CAAA;CACvB;AAGD,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACf"}
package/lib/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
1
  export * from './database';
2
- export * from './datasource';
3
2
  export * from './run';
4
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,OAAO,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,OAAO,CAAA"}
package/lib/index.js CHANGED
@@ -15,6 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./database"), exports);
18
- __exportStar(require("./datasource"), exports);
19
18
  __exportStar(require("./run"), exports);
20
19
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA0B;AAC1B,+CAA4B;AAC5B,wCAAqB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA0B;AAC1B,wCAAqB"}
package/lib/run.d.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import { Database } from './database';
2
+ import { DataSource, BlockRef } from '@subsquid/util-internal-data-source';
1
3
  import { PrometheusServer } from '@subsquid/util-internal-processor-tools';
2
- import { Database, HashAndHeight } from './database';
3
- import { DataSource } from './datasource';
4
4
  export { PrometheusServer };
5
5
  export interface DataHandlerContext<Block, Store> {
6
6
  /**
@@ -16,8 +16,8 @@ export interface DataHandlerContext<Block, Store> {
16
16
  */
17
17
  isHead: boolean;
18
18
  }
19
- interface BlockBase {
20
- header: HashAndHeight;
19
+ export interface BlockBase {
20
+ header: BlockRef;
21
21
  }
22
22
  interface RunOptions {
23
23
  prometheus?: PrometheusServer;
package/lib/run.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,gBAAgB,EAAgB,MAAM,yCAAyC,CAAA;AACvF,OAAO,EAAC,QAAQ,EAAE,aAAa,EAAC,MAAM,YAAY,CAAA;AAClD,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAA;AAGvC,OAAO,EAAC,gBAAgB,EAAC,CAAA;AAMzB,MAAM,WAAW,kBAAkB,CAAC,KAAK,EAAE,KAAK;IAC5C;;OAEG;IACH,KAAK,EAAE,KAAK,CAAA;IACZ;;OAEG;IACH,MAAM,EAAE,KAAK,EAAE,CAAA;IACf;;OAEG;IACH,MAAM,EAAE,OAAO,CAAA;CAClB;AAGD,UAAU,SAAS;IACf,MAAM,EAAE,aAAa,CAAA;CACxB;AAED,UAAU,UAAU;IAChB,UAAU,CAAC,EAAE,gBAAgB,CAAA;CAChC;AAGD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,GAAG,CAAC,KAAK,SAAS,SAAS,EAAE,KAAK,EAC9C,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,EACtB,EAAE,EAAE,QAAQ,CAAC,KAAK,CAAC,EACnB,WAAW,EAAE,CAAC,GAAG,EAAE,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,EACrE,IAAI,CAAC,EAAE,UAAU,GAClB,IAAI,CAMN"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,QAAQ,EAAC,MAAM,YAAY,CAAA;AAClD,OAAO,EAAC,UAAU,EAAmB,QAAQ,EAAkB,MAAM,qCAAqC,CAAA;AAE1G,OAAO,EAAC,gBAAgB,EAAgB,MAAM,yCAAyC,CAAA;AAIvF,OAAO,EAAC,gBAAgB,EAAC,CAAA;AAKzB,MAAM,WAAW,kBAAkB,CAAC,KAAK,EAAE,KAAK;IAC5C;;OAEG;IACH,KAAK,EAAE,KAAK,CAAA;IACZ;;OAEG;IACH,MAAM,EAAE,KAAK,EAAE,CAAA;IACf;;OAEG;IACH,MAAM,EAAE,OAAO,CAAA;CAClB;AAGD,MAAM,WAAW,SAAS;IACtB,MAAM,EAAE,QAAQ,CAAA;CACnB;AASD,UAAU,UAAU;IAChB,UAAU,CAAC,EAAE,gBAAgB,CAAA;CAChC;AAGD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,GAAG,CAAC,KAAK,SAAS,SAAS,EAAE,KAAK,EAC9C,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,EACtB,EAAE,EAAE,QAAQ,CAAC,KAAK,CAAC,EACnB,WAAW,EAAE,CAAC,GAAG,EAAE,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,EACrE,IAAI,CAAC,EAAE,UAAU,GAClB,IAAI,CAMN"}
package/lib/run.js CHANGED
@@ -1,9 +1,14 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.PrometheusServer = void 0;
4
7
  exports.run = run;
5
8
  const logger_1 = require("@subsquid/logger");
6
9
  const util_internal_1 = require("@subsquid/util-internal");
10
+ const util_internal_data_source_1 = require("@subsquid/util-internal-data-source");
11
+ const assert_1 = __importDefault(require("assert"));
7
12
  const util_internal_processor_tools_1 = require("@subsquid/util-internal-processor-tools");
8
13
  Object.defineProperty(exports, "PrometheusServer", { enumerable: true, get: function () { return util_internal_processor_tools_1.PrometheusServer; } });
9
14
  const util_1 = require("./util");
@@ -37,32 +42,63 @@ class Processor {
37
42
  this.opts = opts;
38
43
  this.hasStatusNews = false;
39
44
  this.metrics = new util_internal_processor_tools_1.RunnerMetrics(src.getBlocksCountInRange?.bind(src) ?? ((range) => Math.max(0, range.to - range.from + 1)));
40
- this.chainHeight = new util_internal_1.Throttler(() => this.src.getFinalizedHeight(), 30000);
41
45
  }
42
46
  async run() {
43
- let state = await this.db.connect();
44
- if (state.height >= 0) {
45
- log.info(`last processed final block was ${state.height}`);
46
- }
47
- await this.assertWeAreOnTheSameChain(state);
48
- await this.initMetrics(state);
49
- for await (let blocks of this.src.getBlockStream(state.height + 1)) {
50
- if (blocks.length > 0) {
51
- state = await this.processBatch(state, blocks);
47
+ let getHead = this.db.supportsHotBlocks ? this.src.getHead.bind(this.src) : this.src.getFinalizedHead.bind(this.src);
48
+ let chainHeight = new util_internal_1.Throttler(() => getHead()?.then((r) => r?.number ?? -1), 10000);
49
+ let state = {
50
+ finalizedHead: undefined,
51
+ unfinalizedHeads: [],
52
+ };
53
+ if (this.db.supportsHotBlocks) {
54
+ let dbState = await this.db.connect();
55
+ state.finalizedHead = dbState.height < 0 ? undefined : toBlockRef(dbState);
56
+ state.unfinalizedHeads = dbState.top.map(toBlockRef);
57
+ }
58
+ else {
59
+ let dbState = await this.db.connect();
60
+ state.finalizedHead = dbState.height < 0 ? undefined : toBlockRef(dbState);
61
+ }
62
+ let head = getStateHead(state);
63
+ if (head != null) {
64
+ log.info(`last processed block was ${head.number}`);
65
+ }
66
+ await this.initMetrics(head?.number ?? -1, await chainHeight.get());
67
+ while (true) {
68
+ let getStream = this.db.supportsHotBlocks
69
+ ? this.src.getStream.bind(this.src)
70
+ : this.src.getFinalizedStream.bind(this.src);
71
+ head = getStateHead(state);
72
+ try {
73
+ for await (let data of getStream({ after: head })) {
74
+ state = await this.processBatch(state, data, await chainHeight.get());
75
+ }
76
+ break; // Stream completed successfully, exit loop
77
+ }
78
+ catch (e) {
79
+ if (!(0, util_internal_data_source_1.isForkException)(e) || !this.db.supportsHotBlocks)
80
+ throw e;
81
+ // Handle fork and continue loop to retry
82
+ let chain = state.finalizedHead
83
+ ? [state.finalizedHead, ...state.unfinalizedHeads]
84
+ : state.unfinalizedHeads;
85
+ let rollbackIndex = findRollbackIndex(chain, e.previousBlocks);
86
+ if (rollbackIndex === -1) {
87
+ if (state.finalizedHead != null)
88
+ throw new Error('Unable to process fork');
89
+ state.unfinalizedHeads = [];
90
+ }
91
+ else {
92
+ const rollbackHead = chain[rollbackIndex];
93
+ log.info(`navigating a fork on a common base ${(0, util_1.formatHead)(rollbackHead)}`);
94
+ state.unfinalizedHeads = chain.slice(1, rollbackIndex + 1);
95
+ }
52
96
  }
53
97
  }
54
98
  this.reportFinalStatus();
55
99
  }
56
- async assertWeAreOnTheSameChain(state) {
57
- if (state.height < 0)
58
- return;
59
- let hash = await this.src.getBlockHash(state.height);
60
- if (state.hash === hash)
61
- return;
62
- throw new Error(`already indexed block ${(0, util_1.formatHead)(state)} was not found on chain`);
63
- }
64
- async initMetrics(state) {
65
- this.updateProgressMetrics(await this.chainHeight.get(), state);
100
+ async initMetrics(state, chainHeight) {
101
+ this.updateProgressMetrics(chainHeight, state);
66
102
  let port = process.env.PROCESSOR_PROMETHEUS_PORT || process.env.PROMETHEUS_PORT;
67
103
  let prometheusServer;
68
104
  if (this.opts?.prometheus != null) {
@@ -78,35 +114,87 @@ class Processor {
78
114
  let listening = await prometheusServer.serve();
79
115
  log.info(`prometheus metrics are served on port ${listening.port}`);
80
116
  }
81
- updateProgressMetrics(chainHeight, state, time) {
117
+ updateProgressMetrics(chainHeight, indexerHeight, time) {
82
118
  this.metrics.setChainHeight(chainHeight);
83
- this.metrics.setLastProcessedBlock(state.height);
119
+ this.metrics.setLastProcessedBlock(indexerHeight);
84
120
  this.metrics.updateProgress(time);
85
121
  }
86
- async processBatch(prevHead, blocks) {
87
- let chainHeight = await this.chainHeight.get();
88
- let nextHead = {
89
- hash: (0, util_internal_1.last)(blocks).header.hash,
90
- height: (0, util_internal_1.last)(blocks).header.height
91
- };
92
- let isOnTop = nextHead.height >= chainHeight;
122
+ async processBatch(state, data, chainHeight) {
123
+ let { blocks, finalizedHead: finalizedHeadData } = data;
124
+ if (blocks.length === 0)
125
+ return state;
126
+ let prevHead = getStateHead(state);
127
+ // Validate data continuity
128
+ if (prevHead && prevHead.number >= blocks[0].header.number) {
129
+ throw new Error('Data is not continuous');
130
+ }
131
+ if (finalizedHeadData != null && state.finalizedHead != null && finalizedHeadData.number <= state.finalizedHead.number) {
132
+ finalizedHeadData = state.finalizedHead;
133
+ }
134
+ let unfinalizedIndex = 0;
135
+ if (finalizedHeadData != null) {
136
+ unfinalizedIndex = blocks.findIndex((b) => b.header.number > finalizedHeadData.number);
137
+ }
138
+ let nextHead = (0, util_internal_1.last)(blocks).header;
139
+ let isOnTop = nextHead.number >= chainHeight;
93
140
  let mappingStartTime = process.hrtime.bigint();
94
- await this.db.transact({
95
- prevHead,
96
- nextHead,
97
- isOnTop
98
- }, store => {
99
- return this.handler({
100
- store,
101
- blocks,
102
- isHead: isOnTop
141
+ if (this.db.supportsHotBlocks) {
142
+ let finalizedRef;
143
+ if (unfinalizedIndex < 0) {
144
+ finalizedRef = blocks[blocks.length - 1].header;
145
+ }
146
+ else {
147
+ finalizedRef = blocks[unfinalizedIndex - 1]?.header;
148
+ if (finalizedHeadData != null) {
149
+ finalizedRef = { hash: finalizedHeadData.hash, number: finalizedHeadData.number };
150
+ }
151
+ }
152
+ let finalizedHead = maxBlockRef(finalizedRef, state.finalizedHead);
153
+ await this.db.transactHot2({
154
+ finalizedHead: toHashAndHeight(finalizedHead),
155
+ baseHead: toHashAndHeight(prevHead),
156
+ newBlocks: blocks.map((b) => toHashAndHeight(b.header)),
157
+ }, (store, start, end) => {
158
+ return this.handler({
159
+ store,
160
+ blocks: (start === 0 && end === blocks.length) ? blocks : blocks.slice(start, end),
161
+ isHead: isOnTop,
162
+ });
103
163
  });
104
- });
164
+ if (finalizedHead) {
165
+ state.finalizedHead = finalizedHead;
166
+ }
167
+ if (state.finalizedHead) {
168
+ let idx = state.unfinalizedHeads.findIndex((h) => h.number > state.finalizedHead.number);
169
+ state.unfinalizedHeads = idx < 0 ? [] : state.unfinalizedHeads.slice(idx);
170
+ }
171
+ if (unfinalizedIndex >= 0) {
172
+ for (let i = unfinalizedIndex; i < blocks.length; i++) {
173
+ state.unfinalizedHeads.push({ number: blocks[i].header.number, hash: blocks[i].header.hash });
174
+ }
175
+ }
176
+ }
177
+ else {
178
+ (0, assert_1.default)(unfinalizedIndex < 0, 'non-hot database received unfinalized blocks');
179
+ await this.db.transact({
180
+ prevHead: prevHead ? toHashAndHeight(prevHead) : { height: -1, hash: '0x' },
181
+ nextHead: toHashAndHeight(nextHead),
182
+ isOnTop,
183
+ }, (store) => {
184
+ return this.handler({
185
+ store,
186
+ blocks,
187
+ isHead: isOnTop,
188
+ });
189
+ });
190
+ state.finalizedHead = { number: nextHead.number, hash: nextHead.hash };
191
+ state.unfinalizedHeads = [];
192
+ }
105
193
  let mappingEndTime = process.hrtime.bigint();
106
- this.updateProgressMetrics(chainHeight, nextHead, mappingEndTime);
194
+ this.updateProgressMetrics(chainHeight, nextHead.number, mappingEndTime);
107
195
  this.metrics.registerBatch(blocks.length, (0, util_1.getItemsCount)(blocks), mappingStartTime, mappingEndTime);
108
196
  this.reportStatus();
109
- return nextHead;
197
+ return state;
110
198
  }
111
199
  reportStatus() {
112
200
  if (this.statusReportTimer == null) {
@@ -133,4 +221,46 @@ class Processor {
133
221
  }
134
222
  }
135
223
  }
224
+ function findRollbackIndex(currentChain, forkChain) {
225
+ let currentIndex = 0;
226
+ let forkIndex = 0;
227
+ let lastCommonIndex = -1;
228
+ while (currentIndex < currentChain.length && forkIndex < forkChain.length) {
229
+ const currentBlock = currentChain[currentIndex];
230
+ const forkBlock = forkChain[forkIndex];
231
+ if (currentBlock.number > forkBlock.number) {
232
+ forkIndex++;
233
+ continue;
234
+ }
235
+ if (currentBlock.number < forkBlock.number) {
236
+ currentIndex++;
237
+ continue;
238
+ }
239
+ if (currentBlock.hash !== forkBlock.hash) {
240
+ return lastCommonIndex;
241
+ }
242
+ lastCommonIndex = currentIndex;
243
+ currentIndex++;
244
+ forkIndex++;
245
+ }
246
+ return lastCommonIndex;
247
+ }
248
+ function toHashAndHeight(ref) {
249
+ if (ref == null)
250
+ return { height: -1, hash: '0x' };
251
+ return { height: ref.number, hash: ref.hash };
252
+ }
253
+ function toBlockRef(hashAndHeight) {
254
+ return { number: hashAndHeight.height, hash: hashAndHeight.hash };
255
+ }
256
+ function getStateHead(state) {
257
+ return (0, util_internal_1.maybeLast)(state.unfinalizedHeads) ?? state.finalizedHead;
258
+ }
259
+ function maxBlockRef(a, b) {
260
+ if (a == null)
261
+ return b;
262
+ if (b == null)
263
+ return a;
264
+ return a.number >= b.number ? a : b;
265
+ }
136
266
  //# sourceMappingURL=run.js.map
package/lib/run.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
package/lib/util.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { HashAndHeight } from './database';
1
+ import type { BlockRef } from '@subsquid/util-internal-data-source';
2
2
  export declare function timeInterval(seconds: number): string;
3
3
  export declare function getItemsCount(blocks: any[]): number;
4
- export declare function formatHead(head: HashAndHeight): string;
4
+ export declare function formatHead(head: BlockRef): string;
5
5
  export declare function shortHash(hash: string): string;
6
6
  //# sourceMappingURL=util.d.ts.map
package/lib/util.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,YAAY,CAAA;AAGxC,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAWpD;AAGD,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,CAWnD;AAGD,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAEtD;AAGD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM9C"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,qCAAqC,CAAA;AAIjE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAWpD;AAGD,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,CAWnD;AAGD,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAEjD;AAGD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM9C"}
package/lib/util.js CHANGED
@@ -29,7 +29,7 @@ function getItemsCount(blocks) {
29
29
  return count;
30
30
  }
31
31
  function formatHead(head) {
32
- return `${head.height}#${shortHash(head.hash)}`;
32
+ return `${head.number}#${shortHash(head.hash)}`;
33
33
  }
34
34
  function shortHash(hash) {
35
35
  if (hash.startsWith('0x')) {
package/lib/util.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;AAGA,oCAWC;AAGD,sCAWC;AAGD,gCAEC;AAGD,8BAMC;AAvCD,SAAgB,YAAY,CAAC,OAAe;IACxC,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QACf,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,GAAG,CAAA;IACpC,CAAC;IACD,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,GAAC,EAAE,CAAC,CAAA;IACnC,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QACf,OAAQ,OAAO,GAAC,GAAG,CAAA;IACvB,CAAC;IACD,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAA;IACpC,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,EAAE,CAAA;IAC9B,OAAO,KAAK,GAAG,IAAI,GAAG,OAAO,GAAG,GAAG,CAAA;AACvC,CAAC;AAGD,SAAgB,aAAa,CAAC,MAAa;IACvC,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;QACvB,KAAK,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;YACpB,IAAI,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;YACpB,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,KAAK,IAAI,GAAG,CAAC,MAAM,CAAA;YACvB,CAAC;QACL,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAA;AAChB,CAAC;AAGD,SAAgB,UAAU,CAAC,IAAmB;IAC1C,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;AACnD,CAAC;AAGD,SAAgB,SAAS,CAAC,IAAY;IAClC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC3B,CAAC;SAAM,CAAC;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC3B,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;AAIA,oCAWC;AAGD,sCAWC;AAGD,gCAEC;AAGD,8BAMC;AAvCD,SAAgB,YAAY,CAAC,OAAe;IACxC,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QACf,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,GAAG,CAAA;IACpC,CAAC;IACD,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,GAAC,EAAE,CAAC,CAAA;IACnC,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QACf,OAAQ,OAAO,GAAC,GAAG,CAAA;IACvB,CAAC;IACD,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAA;IACpC,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,EAAE,CAAA;IAC9B,OAAO,KAAK,GAAG,IAAI,GAAG,OAAO,GAAG,GAAG,CAAA;AACvC,CAAC;AAGD,SAAgB,aAAa,CAAC,MAAa;IACvC,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;QACvB,KAAK,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;YACpB,IAAI,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;YACpB,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,KAAK,IAAI,GAAG,CAAC,MAAM,CAAA;YACvB,CAAC;QACL,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAA;AAChB,CAAC;AAGD,SAAgB,UAAU,CAAC,IAAc;IACrC,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;AACnD,CAAC;AAGD,SAAgB,SAAS,CAAC,IAAY;IAClC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC3B,CAAC;SAAM,CAAC;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC3B,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@subsquid/batch-processor",
3
- "version": "0.1.0",
3
+ "version": "0.2.0-portal-api.493495",
4
4
  "description": "ETL processor",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "repository": "git@github.com:subsquid/squid-sdk.git",
@@ -18,7 +18,9 @@
18
18
  "@subsquid/util-internal": "^3.2.0",
19
19
  "@subsquid/util-internal-processor-tools": "^4.4.0",
20
20
  "@subsquid/util-internal-counters": "^1.3.2",
21
- "@subsquid/util-internal-range": "^0.3.0"
21
+ "@subsquid/util-internal-prometheus-server": "^1.3.0",
22
+ "@subsquid/util-internal-range": "^0.3.0",
23
+ "@subsquid/util-internal-data-source": "0.0.1-portal-api.493495"
22
24
  },
23
25
  "devDependencies": {
24
26
  "@types/node": "^18.18.14",
package/src/database.ts CHANGED
@@ -14,11 +14,14 @@ export interface FinalTxInfo {
14
14
 
15
15
  export interface FinalDatabase<S> {
16
16
  supportsHotBlocks?: false
17
- connect(): Promise<HashAndHeight>
17
+ connect(): Promise<FinalDatabaseState>
18
18
  transact(info: FinalTxInfo, cb: (store: S) => Promise<void>): Promise<void>
19
19
  }
20
20
 
21
21
 
22
+ export interface FinalDatabaseState extends HashAndHeight {}
23
+
24
+
22
25
  export interface HotTxInfo {
23
26
  finalizedHead: HashAndHeight
24
27
  baseHead: HashAndHeight
@@ -30,12 +33,8 @@ export interface HotDatabase<S> {
30
33
  supportsHotBlocks: true
31
34
  connect(): Promise<HotDatabaseState>
32
35
  transact(info: FinalTxInfo, cb: (store: S) => Promise<void>): Promise<void>
33
- /**
34
- * @deprecated
35
- */
36
- transactHot(info: HotTxInfo, cb: (store: S, block: HashAndHeight) => Promise<void>): Promise<void>
37
36
 
38
- transactHot2?(
37
+ transactHot2(
39
38
  info: HotTxInfo,
40
39
  cb: (store: S, blockSliceStart: number, blockSliceEnd: number) => Promise<void>
41
40
  ): Promise<void>
@@ -50,4 +49,4 @@ export interface HotDatabaseState extends HashAndHeight {
50
49
  export interface HashAndHeight {
51
50
  height: number
52
51
  hash: string
53
- }
52
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,2 @@
1
1
  export * from './database'
2
- export * from './datasource'
3
2
  export * from './run'
package/src/run.ts CHANGED
@@ -1,16 +1,17 @@
1
1
  import {createLogger} from '@subsquid/logger'
2
- import {last, runProgram, Throttler} from '@subsquid/util-internal'
2
+ import {last, maybeLast, runProgram, Throttler} from '@subsquid/util-internal'
3
+ import {HashAndHeight, Database} from './database'
4
+ import {DataSource, isForkException, BlockRef, type BlockBatch} from '@subsquid/util-internal-data-source'
5
+ import assert from 'assert'
3
6
  import {PrometheusServer, RunnerMetrics} from '@subsquid/util-internal-processor-tools'
4
- import {Database, HashAndHeight} from './database'
5
- import {DataSource} from './datasource'
6
7
  import {formatHead, getItemsCount} from './util'
7
8
 
9
+
8
10
  export {PrometheusServer}
9
11
 
10
12
 
11
13
  const log = createLogger('sqd:batch-processor')
12
14
 
13
-
14
15
  export interface DataHandlerContext<Block, Store> {
15
16
  /**
16
17
  * Storage interface provided by the database
@@ -27,10 +28,17 @@ export interface DataHandlerContext<Block, Store> {
27
28
  }
28
29
 
29
30
 
30
- interface BlockBase {
31
- header: HashAndHeight
31
+ export interface BlockBase {
32
+ header: BlockRef
32
33
  }
33
34
 
35
+
36
+ interface ProcessorState {
37
+ finalizedHead: BlockRef | undefined
38
+ unfinalizedHeads: BlockRef[]
39
+ }
40
+
41
+
34
42
  interface RunOptions {
35
43
  prometheus?: PrometheusServer
36
44
  }
@@ -63,10 +71,8 @@ export function run<Block extends BlockBase, Store>(
63
71
  })
64
72
  }
65
73
 
66
-
67
74
  class Processor<B extends BlockBase, S> {
68
75
  private metrics: RunnerMetrics
69
- private chainHeight: Throttler<number>
70
76
  private statusReportTimer?: any
71
77
  private hasStatusNews = false
72
78
 
@@ -79,38 +85,67 @@ class Processor<B extends BlockBase, S> {
79
85
  this.metrics = new RunnerMetrics(
80
86
  src.getBlocksCountInRange?.bind(src) ?? ((range) => Math.max(0, range.to - range.from + 1)),
81
87
  )
82
- this.chainHeight = new Throttler(() => this.src.getFinalizedHeight(), 30_000)
83
88
  }
84
89
 
85
90
  async run(): Promise<void> {
86
- let state = await this.db.connect()
87
- if (state.height >= 0) {
88
- log.info(`last processed final block was ${state.height}`)
91
+ let getHead = this.db.supportsHotBlocks ? this.src.getHead.bind(this.src) : this.src.getFinalizedHead.bind(this.src)
92
+ let chainHeight = new Throttler(() => getHead()?.then((r) => r?.number ?? -1), 10_000)
93
+
94
+ let state: ProcessorState = {
95
+ finalizedHead: undefined,
96
+ unfinalizedHeads: [],
97
+ }
98
+ if (this.db.supportsHotBlocks) {
99
+ let dbState = await this.db.connect()
100
+ state.finalizedHead = dbState.height < 0 ? undefined : toBlockRef(dbState)
101
+ state.unfinalizedHeads = dbState.top.map(toBlockRef)
102
+ } else {
103
+ let dbState = await this.db.connect()
104
+ state.finalizedHead = dbState.height < 0 ? undefined : toBlockRef(dbState)
89
105
  }
90
106
 
91
- await this.assertWeAreOnTheSameChain(state)
92
- await this.initMetrics(state)
107
+ let head = getStateHead(state)
108
+ if (head != null) {
109
+ log.info(`last processed block was ${head.number}`)
110
+ }
111
+ await this.initMetrics(head?.number ?? -1, await chainHeight.get())
93
112
 
94
- for await (let blocks of this.src.getBlockStream(state.height + 1)) {
95
- if (blocks.length > 0) {
96
- state = await this.processBatch(state, blocks)
113
+ while (true) {
114
+ let getStream = this.db.supportsHotBlocks
115
+ ? this.src.getStream.bind(this.src)
116
+ : this.src.getFinalizedStream.bind(this.src)
117
+
118
+ head = getStateHead(state)
119
+ try {
120
+ for await (let data of getStream({after: head})) {
121
+ state = await this.processBatch(state, data, await chainHeight.get())
122
+ }
123
+ break // Stream completed successfully, exit loop
124
+ } catch (e) {
125
+ if (!isForkException(e) || !this.db.supportsHotBlocks) throw e
126
+
127
+ // Handle fork and continue loop to retry
128
+ let chain = state.finalizedHead
129
+ ? [state.finalizedHead, ...state.unfinalizedHeads]
130
+ : state.unfinalizedHeads
131
+ let rollbackIndex = findRollbackIndex(chain, e.previousBlocks)
132
+ if (rollbackIndex === -1) {
133
+ if (state.finalizedHead != null) throw new Error('Unable to process fork')
134
+ state.unfinalizedHeads = []
135
+ } else {
136
+ const rollbackHead = chain[rollbackIndex]
137
+ log.info(`navigating a fork on a common base ${formatHead(rollbackHead)}`)
138
+
139
+ state.unfinalizedHeads = chain.slice(1, rollbackIndex + 1)
140
+ }
97
141
  }
98
142
  }
99
143
 
100
144
  this.reportFinalStatus()
101
145
  }
102
146
 
103
- private async assertWeAreOnTheSameChain(state: HashAndHeight): Promise<void> {
104
- if (state.height < 0) return
105
- let hash = await this.src.getBlockHash(state.height)
106
- if (state.hash === hash) return
107
- throw new Error(
108
- `already indexed block ${formatHead(state)} was not found on chain`
109
- )
110
- }
111
-
112
- private async initMetrics(state: HashAndHeight): Promise<void> {
113
- this.updateProgressMetrics(await this.chainHeight.get(), state)
147
+ private async initMetrics(state: number, chainHeight: number): Promise<void> {
148
+ this.updateProgressMetrics(chainHeight, state)
114
149
  let port = process.env.PROCESSOR_PROMETHEUS_PORT || process.env.PROMETHEUS_PORT
115
150
 
116
151
  let prometheusServer: PrometheusServer | undefined
@@ -127,49 +162,110 @@ class Processor<B extends BlockBase, S> {
127
162
  log.info(`prometheus metrics are served on port ${listening.port}`)
128
163
  }
129
164
 
130
- private updateProgressMetrics(chainHeight: number, state: HashAndHeight, time?: bigint): void {
165
+ private updateProgressMetrics(chainHeight: number, indexerHeight: number, time?: bigint): void {
131
166
  this.metrics.setChainHeight(chainHeight)
132
- this.metrics.setLastProcessedBlock(state.height)
167
+ this.metrics.setLastProcessedBlock(indexerHeight)
133
168
  this.metrics.updateProgress(time)
134
169
  }
135
170
 
136
- private async processBatch(prevHead: HashAndHeight, blocks: B[]): Promise<HashAndHeight> {
137
- let chainHeight = await this.chainHeight.get()
171
+ private async processBatch(
172
+ state: ProcessorState,
173
+ data: BlockBatch<B>,
174
+ chainHeight: number
175
+ ): Promise<ProcessorState> {
176
+ let {blocks, finalizedHead: finalizedHeadData} = data
177
+
178
+ if (blocks.length === 0) return state
179
+
180
+ let prevHead = getStateHead(state)
181
+
182
+ // Validate data continuity
183
+ if (prevHead && prevHead.number >= blocks[0].header.number) {
184
+ throw new Error('Data is not continuous')
185
+ }
186
+
187
+ if (finalizedHeadData != null && state.finalizedHead != null && finalizedHeadData.number <= state.finalizedHead.number) {
188
+ finalizedHeadData = state.finalizedHead
189
+ }
138
190
 
139
- let nextHead = {
140
- hash: last(blocks).header.hash,
141
- height: last(blocks).header.height
191
+ let unfinalizedIndex = 0
192
+ if (finalizedHeadData != null) {
193
+ unfinalizedIndex = blocks.findIndex((b) => b.header.number > finalizedHeadData!.number)
142
194
  }
143
195
 
144
- let isOnTop = nextHead.height >= chainHeight
196
+ let nextHead = last(blocks).header
197
+ let isOnTop = nextHead.number >= chainHeight
145
198
 
146
199
  let mappingStartTime = process.hrtime.bigint()
147
200
 
148
- await this.db.transact({
149
- prevHead,
150
- nextHead,
151
- isOnTop
152
- }, store => {
153
- return this.handler({
154
- store,
155
- blocks,
156
- isHead: isOnTop
157
- })
158
- })
201
+ if (this.db.supportsHotBlocks) {
202
+ let finalizedRef: BlockRef | undefined
203
+ if (unfinalizedIndex < 0) {
204
+ finalizedRef = blocks[blocks.length - 1].header
205
+ } else {
206
+ finalizedRef = blocks[unfinalizedIndex - 1]?.header
207
+ if (finalizedHeadData != null) {
208
+ finalizedRef = {hash: finalizedHeadData.hash, number: finalizedHeadData.number}
209
+ }
210
+ }
211
+ let finalizedHead = maxBlockRef(finalizedRef, state.finalizedHead)
212
+ await this.db.transactHot2(
213
+ {
214
+ finalizedHead: toHashAndHeight(finalizedHead),
215
+ baseHead: toHashAndHeight(prevHead),
216
+ newBlocks: blocks.map((b) => toHashAndHeight(b.header)),
217
+ },
218
+ (store, start, end) => {
219
+ return this.handler({
220
+ store,
221
+ blocks: (start === 0 && end === blocks.length) ? blocks : blocks.slice(start, end),
222
+ isHead: isOnTop,
223
+ })
224
+ }
225
+ )
226
+
227
+ if (finalizedHead) {
228
+ state.finalizedHead = finalizedHead
229
+ }
230
+ if (state.finalizedHead) {
231
+ let idx = state.unfinalizedHeads.findIndex((h) => h.number > state.finalizedHead!.number)
232
+ state.unfinalizedHeads = idx < 0 ? [] : state.unfinalizedHeads.slice(idx)
233
+ }
234
+ if (unfinalizedIndex >= 0) {
235
+ for (let i = unfinalizedIndex; i < blocks.length; i++) {
236
+ state.unfinalizedHeads.push({number: blocks[i].header.number, hash: blocks[i].header.hash})
237
+ }
238
+ }
239
+ } else {
240
+ assert(unfinalizedIndex < 0, 'non-hot database received unfinalized blocks')
241
+
242
+ await this.db.transact(
243
+ {
244
+ prevHead: prevHead ? toHashAndHeight(prevHead) : {height: -1, hash: '0x'},
245
+ nextHead: toHashAndHeight(nextHead),
246
+ isOnTop,
247
+ },
248
+ (store) => {
249
+ return this.handler({
250
+ store,
251
+ blocks,
252
+ isHead: isOnTop,
253
+ })
254
+ }
255
+ )
256
+
257
+ state.finalizedHead = {number: nextHead.number, hash: nextHead.hash}
258
+ state.unfinalizedHeads = []
259
+ }
159
260
 
160
261
  let mappingEndTime = process.hrtime.bigint()
161
262
 
162
- this.updateProgressMetrics(chainHeight, nextHead, mappingEndTime)
163
- this.metrics.registerBatch(
164
- blocks.length,
165
- getItemsCount(blocks),
166
- mappingStartTime,
167
- mappingEndTime
168
- )
263
+ this.updateProgressMetrics(chainHeight, nextHead.number, mappingEndTime)
264
+ this.metrics.registerBatch(blocks.length, getItemsCount(blocks), mappingStartTime, mappingEndTime)
169
265
 
170
266
  this.reportStatus()
171
267
 
172
- return nextHead
268
+ return state
173
269
  }
174
270
 
175
271
  private reportStatus(): void {
@@ -181,7 +277,7 @@ class Processor<B extends BlockBase, S> {
181
277
  this.hasStatusNews = false
182
278
  this.reportStatus()
183
279
  }
184
- }, 5000)
280
+ }, 5_000)
185
281
  } else {
186
282
  this.hasStatusNews = true
187
283
  }
@@ -197,3 +293,53 @@ class Processor<B extends BlockBase, S> {
197
293
  }
198
294
  }
199
295
  }
296
+
297
+ function findRollbackIndex(currentChain: BlockRef[], forkChain: BlockRef[]): number {
298
+ let currentIndex = 0
299
+ let forkIndex = 0
300
+ let lastCommonIndex = -1
301
+
302
+ while (currentIndex < currentChain.length && forkIndex < forkChain.length) {
303
+ const currentBlock = currentChain[currentIndex]
304
+ const forkBlock = forkChain[forkIndex]
305
+
306
+ if (currentBlock.number > forkBlock.number) {
307
+ forkIndex++
308
+ continue
309
+ }
310
+
311
+ if (currentBlock.number < forkBlock.number) {
312
+ currentIndex++
313
+ continue
314
+ }
315
+
316
+ if (currentBlock.hash !== forkBlock.hash) {
317
+ return lastCommonIndex
318
+ }
319
+
320
+ lastCommonIndex = currentIndex
321
+ currentIndex++
322
+ forkIndex++
323
+ }
324
+
325
+ return lastCommonIndex
326
+ }
327
+
328
+ function toHashAndHeight(ref: BlockRef | undefined): HashAndHeight {
329
+ if (ref == null) return {height: -1, hash: '0x'}
330
+ return {height: ref.number, hash: ref.hash}
331
+ }
332
+
333
+ function toBlockRef(hashAndHeight: HashAndHeight): BlockRef {
334
+ return {number: hashAndHeight.height, hash: hashAndHeight.hash}
335
+ }
336
+
337
+ function getStateHead(state: ProcessorState): BlockRef | undefined {
338
+ return maybeLast(state.unfinalizedHeads) ?? state.finalizedHead
339
+ }
340
+
341
+ function maxBlockRef(a: BlockRef | undefined, b: BlockRef | undefined): BlockRef | undefined {
342
+ if (a == null) return b
343
+ if (b == null) return a
344
+ return a.number >= b.number ? a : b
345
+ }
package/src/util.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type {BlockRef} from '@subsquid/util-internal-data-source'
1
2
  import {HashAndHeight} from './database'
2
3
 
3
4
 
@@ -29,8 +30,8 @@ export function getItemsCount(blocks: any[]): number {
29
30
  }
30
31
 
31
32
 
32
- export function formatHead(head: HashAndHeight): string {
33
- return `${head.height}#${shortHash(head.hash)}`
33
+ export function formatHead(head: BlockRef): string {
34
+ return `${head.number}#${shortHash(head.hash)}`
34
35
  }
35
36
 
36
37
 
@@ -1,8 +0,0 @@
1
- import type { FiniteRange } from '@subsquid/util-internal-range';
2
- export interface DataSource<B> {
3
- getFinalizedHeight(): Promise<number>;
4
- getBlockHash(height: number): Promise<string | undefined>;
5
- getBlockStream(fromBlock?: number): AsyncIterable<B[]>;
6
- getBlocksCountInRange?(range: FiniteRange): number;
7
- }
8
- //# sourceMappingURL=datasource.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"datasource.d.ts","sourceRoot":"","sources":["../src/datasource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,+BAA+B,CAAA;AAG9D,MAAM,WAAW,UAAU,CAAC,CAAC;IACzB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;IACrC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IACzD,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC,EAAE,CAAC,CAAA;IACtD,qBAAqB,CAAC,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAAA;CACrD"}
package/lib/datasource.js DELETED
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=datasource.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"datasource.js","sourceRoot":"","sources":["../src/datasource.ts"],"names":[],"mappings":""}
package/src/datasource.ts DELETED
@@ -1,9 +0,0 @@
1
- import type {FiniteRange} from '@subsquid/util-internal-range'
2
-
3
-
4
- export interface DataSource<B> {
5
- getFinalizedHeight(): Promise<number>
6
- getBlockHash(height: number): Promise<string | undefined>
7
- getBlockStream(fromBlock?: number): AsyncIterable<B[]>
8
- getBlocksCountInRange?(range: FiniteRange): number
9
- }