@subsquid/batch-processor 0.0.0 → 0.1.0-portal-api.d0738f
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 +4 -6
- package/lib/database.d.ts.map +1 -1
- package/lib/index.d.ts +0 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +0 -1
- package/lib/index.js.map +1 -1
- package/lib/run.d.ts +4 -5
- package/lib/run.d.ts.map +1 -1
- package/lib/run.js +155 -59
- package/lib/run.js.map +1 -1
- package/lib/util.d.ts +2 -2
- package/lib/util.d.ts.map +1 -1
- package/lib/util.js +5 -6
- package/lib/util.js.map +1 -1
- package/package.json +5 -4
- package/src/database.ts +6 -7
- package/src/index.ts +0 -1
- package/src/run.ts +194 -80
- package/src/util.ts +3 -2
- package/lib/datasource.d.ts +0 -8
- package/lib/datasource.d.ts.map +0 -1
- package/lib/datasource.js +0 -3
- package/lib/datasource.js.map +0 -1
- package/src/datasource.ts +0 -9
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<
|
|
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[];
|
package/lib/database.d.ts.map
CHANGED
|
@@ -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,
|
|
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
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,
|
|
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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA0B;AAC1B,wCAAqB"}
|
package/lib/run.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Database
|
|
2
|
-
import { DataSource } from '
|
|
1
|
+
import { Database } from './database';
|
|
2
|
+
import { DataSource, BlockRef } from '@subsquid/util-internal-data-source';
|
|
3
3
|
export interface DataHandlerContext<Block, Store> {
|
|
4
4
|
/**
|
|
5
5
|
* Storage interface provided by the database
|
|
@@ -14,8 +14,8 @@ export interface DataHandlerContext<Block, Store> {
|
|
|
14
14
|
*/
|
|
15
15
|
isHead: boolean;
|
|
16
16
|
}
|
|
17
|
-
interface BlockBase {
|
|
18
|
-
header:
|
|
17
|
+
export interface BlockBase {
|
|
18
|
+
header: BlockRef;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Run data processing.
|
|
@@ -32,5 +32,4 @@ interface BlockBase {
|
|
|
32
32
|
* @param dataHandler - The data handler, see {@link DataHandlerContext} for an API available to the handler.
|
|
33
33
|
*/
|
|
34
34
|
export declare function run<Block extends BlockBase, Store>(src: DataSource<Block>, db: Database<Store>, dataHandler: (ctx: DataHandlerContext<Block, Store>) => Promise<void>): void;
|
|
35
|
-
export {};
|
|
36
35
|
//# sourceMappingURL=run.d.ts.map
|
package/lib/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAIA,OAAO,
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgB,QAAQ,EAAmB,MAAM,YAAY,CAAA;AAEpE,OAAO,EAAC,UAAU,EAAmB,QAAQ,EAAkB,MAAM,qCAAqC,CAAA;AAM1G,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;AAED,MAAM,WAAW,SAAS;IACtB,MAAM,EAAE,QAAQ,CAAA;CACnB;AAOD;;;;;;;;;;;;;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,GACtE,IAAI,CASN"}
|
package/lib/run.js
CHANGED
|
@@ -22,14 +22,19 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
25
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.run =
|
|
29
|
+
exports.run = run;
|
|
27
30
|
const logger_1 = require("@subsquid/logger");
|
|
28
31
|
const util_internal_1 = require("@subsquid/util-internal");
|
|
29
32
|
const util_internal_prometheus_server_1 = require("@subsquid/util-internal-prometheus-server");
|
|
30
33
|
const prom = __importStar(require("prom-client"));
|
|
31
34
|
const metrics_1 = require("./metrics");
|
|
35
|
+
const util_internal_data_source_1 = require("@subsquid/util-internal-data-source");
|
|
32
36
|
const util_1 = require("./util");
|
|
37
|
+
const assert_1 = __importDefault(require("assert"));
|
|
33
38
|
const log = (0, logger_1.createLogger)('sqd:batch-processor');
|
|
34
39
|
/**
|
|
35
40
|
* Run data processing.
|
|
@@ -48,11 +53,10 @@ const log = (0, logger_1.createLogger)('sqd:batch-processor');
|
|
|
48
53
|
function run(src, db, dataHandler) {
|
|
49
54
|
(0, util_internal_1.runProgram)(() => {
|
|
50
55
|
return new Processor(src, db, dataHandler).run();
|
|
51
|
-
}, err => {
|
|
56
|
+
}, (err) => {
|
|
52
57
|
log.fatal(err);
|
|
53
58
|
});
|
|
54
59
|
}
|
|
55
|
-
exports.run = run;
|
|
56
60
|
class Processor {
|
|
57
61
|
constructor(src, db, handler) {
|
|
58
62
|
this.src = src;
|
|
@@ -60,32 +64,63 @@ class Processor {
|
|
|
60
64
|
this.handler = handler;
|
|
61
65
|
this.metrics = new metrics_1.Metrics();
|
|
62
66
|
this.hasStatusNews = false;
|
|
63
|
-
this.chainHeight = new util_internal_1.Throttler(() => this.src.getFinalizedHeight(), 30000);
|
|
64
67
|
}
|
|
65
68
|
async run() {
|
|
66
|
-
let
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
let getHead = this.db.supportsHotBlocks ? this.src.getHead.bind(this.src) : this.src.getFinalizedHead.bind(this.src);
|
|
70
|
+
let chainHeight = new util_internal_1.Throttler(() => getHead()?.then((r) => r?.number ?? -1), 10000);
|
|
71
|
+
let state = {
|
|
72
|
+
finalizedHead: undefined,
|
|
73
|
+
unfinalizedHeads: [],
|
|
74
|
+
};
|
|
75
|
+
if (this.db.supportsHotBlocks) {
|
|
76
|
+
let dbState = await this.db.connect();
|
|
77
|
+
state.finalizedHead = dbState.height < 0 ? undefined : toBlockRef(dbState);
|
|
78
|
+
state.unfinalizedHeads = dbState.top.map(toBlockRef);
|
|
69
79
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
else {
|
|
81
|
+
let dbState = await this.db.connect();
|
|
82
|
+
state.finalizedHead = dbState.height < 0 ? undefined : toBlockRef(dbState);
|
|
83
|
+
}
|
|
84
|
+
let head = getStateHead(state);
|
|
85
|
+
if (head != null) {
|
|
86
|
+
log.info(`last processed block was ${head.number}`);
|
|
87
|
+
}
|
|
88
|
+
await this.initMetrics(head?.number ?? -1, await chainHeight.get());
|
|
89
|
+
while (true) {
|
|
90
|
+
let getStream = this.db.supportsHotBlocks
|
|
91
|
+
? this.src.getStream.bind(this.src)
|
|
92
|
+
: this.src.getFinalizedStream.bind(this.src);
|
|
93
|
+
head = getStateHead(state);
|
|
94
|
+
try {
|
|
95
|
+
for await (let data of getStream({ after: head })) {
|
|
96
|
+
state = await this.processBatch(state, data, await chainHeight.get());
|
|
97
|
+
}
|
|
98
|
+
break; // Stream completed successfully, exit loop
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
if (!(0, util_internal_data_source_1.isForkException)(e) || !this.db.supportsHotBlocks)
|
|
102
|
+
throw e;
|
|
103
|
+
// Handle fork and continue loop to retry
|
|
104
|
+
let chain = state.finalizedHead
|
|
105
|
+
? [state.finalizedHead, ...state.unfinalizedHeads]
|
|
106
|
+
: state.unfinalizedHeads;
|
|
107
|
+
let rollbackIndex = findRollbackIndex(chain, e.previousBlocks);
|
|
108
|
+
if (rollbackIndex === -1) {
|
|
109
|
+
if (state.finalizedHead != null)
|
|
110
|
+
throw new Error('Unable to process fork');
|
|
111
|
+
state.unfinalizedHeads = [];
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const rollbackHead = chain[rollbackIndex];
|
|
115
|
+
log.info(`navigating a fork on a common base ${(0, util_1.formatHead)(rollbackHead)}`);
|
|
116
|
+
state.unfinalizedHeads = chain.slice(1, rollbackIndex + 1);
|
|
117
|
+
}
|
|
75
118
|
}
|
|
76
119
|
}
|
|
77
120
|
this.reportFinalStatus();
|
|
78
121
|
}
|
|
79
|
-
async
|
|
80
|
-
|
|
81
|
-
return;
|
|
82
|
-
let hash = await this.src.getBlockHash(state.height);
|
|
83
|
-
if (state.hash === hash)
|
|
84
|
-
return;
|
|
85
|
-
throw new Error(`already indexed block ${(0, util_1.formatHead)(state)} was not found on chain`);
|
|
86
|
-
}
|
|
87
|
-
async initMetrics(state) {
|
|
88
|
-
await this.updateProgressMetrics(await this.chainHeight.get(), state);
|
|
122
|
+
async initMetrics(state, chainHeight) {
|
|
123
|
+
this.updateProgressMetrics(chainHeight, state);
|
|
89
124
|
let port = process.env.PROCESSOR_PROMETHEUS_PORT || process.env.PROMETHEUS_PORT;
|
|
90
125
|
if (port == null)
|
|
91
126
|
return;
|
|
@@ -94,51 +129,79 @@ class Processor {
|
|
|
94
129
|
let server = await (0, util_internal_prometheus_server_1.createPrometheusServer)(prom.register, port);
|
|
95
130
|
log.info(`prometheus metrics are served on port ${server.port}`);
|
|
96
131
|
}
|
|
97
|
-
updateProgressMetrics(chainHeight,
|
|
132
|
+
updateProgressMetrics(chainHeight, indexerHeight, time) {
|
|
98
133
|
this.metrics.setChainHeight(chainHeight);
|
|
99
|
-
this.metrics.setLastProcessedBlock(
|
|
100
|
-
let left;
|
|
101
|
-
let processed;
|
|
102
|
-
if (this.src.getBlocksCountInRange) {
|
|
103
|
-
left = this.src.getBlocksCountInRange({
|
|
104
|
-
from: this.metrics.getLastProcessedBlock() + 1,
|
|
105
|
-
to: this.metrics.getChainHeight()
|
|
106
|
-
});
|
|
107
|
-
processed = this.src.getBlocksCountInRange({
|
|
108
|
-
from: 0,
|
|
109
|
-
to: this.metrics.getChainHeight()
|
|
110
|
-
}) - left;
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
left = this.metrics.getChainHeight() - this.metrics.getLastProcessedBlock();
|
|
114
|
-
processed = this.metrics.getLastProcessedBlock();
|
|
115
|
-
}
|
|
134
|
+
this.metrics.setLastProcessedBlock(indexerHeight);
|
|
135
|
+
let left = this.metrics.getChainHeight() - this.metrics.getLastProcessedBlock();
|
|
136
|
+
let processed = this.metrics.getLastProcessedBlock();
|
|
116
137
|
this.metrics.updateProgress(processed, left, time);
|
|
117
138
|
}
|
|
118
|
-
async processBatch(
|
|
119
|
-
let
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
139
|
+
async processBatch(state, data, chainHeight) {
|
|
140
|
+
let { blocks, finalizedHead: finalizedHeadData } = data;
|
|
141
|
+
if (blocks.length === 0)
|
|
142
|
+
return state;
|
|
143
|
+
let prevHead = getStateHead(state);
|
|
144
|
+
// Validate data continuity
|
|
145
|
+
if (prevHead && prevHead.number >= blocks[0].header.number) {
|
|
146
|
+
throw new Error('Data is not continuous');
|
|
147
|
+
}
|
|
148
|
+
let unfinalizedIndex = 0;
|
|
149
|
+
if (finalizedHeadData != null) {
|
|
150
|
+
unfinalizedIndex = blocks.findIndex((b) => b.header.number > finalizedHeadData.number);
|
|
151
|
+
}
|
|
152
|
+
let nextHead = (0, util_internal_1.last)(blocks).header;
|
|
153
|
+
let isOnTop = nextHead.number >= chainHeight;
|
|
125
154
|
let mappingStartTime = process.hrtime.bigint();
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
155
|
+
// All new blocks are finalized
|
|
156
|
+
if (unfinalizedIndex < 0) {
|
|
157
|
+
const finalizedRef = blocks[blocks.length - 1].header;
|
|
158
|
+
state.finalizedHead = { number: finalizedRef.number, hash: finalizedRef.hash };
|
|
159
|
+
state.unfinalizedHeads = [];
|
|
160
|
+
await this.db.transact({
|
|
161
|
+
prevHead: prevHead ? toHashAndHeight(prevHead) : { height: -1, hash: '0x' },
|
|
162
|
+
nextHead: toHashAndHeight(nextHead),
|
|
163
|
+
isOnTop,
|
|
164
|
+
}, (store) => {
|
|
165
|
+
return this.handler({
|
|
166
|
+
store,
|
|
167
|
+
blocks,
|
|
168
|
+
isHead: isOnTop,
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
(0, assert_1.default)(this.db.supportsHotBlocks);
|
|
174
|
+
let finalizedRef = blocks[unfinalizedIndex - 1]?.header;
|
|
175
|
+
if (finalizedHeadData?.hash && finalizedHeadData?.number != null) {
|
|
176
|
+
finalizedRef = { hash: finalizedHeadData.hash, number: finalizedHeadData.number };
|
|
177
|
+
}
|
|
178
|
+
state.finalizedHead = finalizedRef ?? state.finalizedHead;
|
|
179
|
+
// Finalize all hot heads that are older than the cold head
|
|
180
|
+
if (state.finalizedHead) {
|
|
181
|
+
let finalizeIndex = state.unfinalizedHeads.findIndex((h) => h.number > state.finalizedHead.number);
|
|
182
|
+
state.unfinalizedHeads = finalizeIndex < 0 ? [] : state.unfinalizedHeads.slice(finalizeIndex);
|
|
183
|
+
}
|
|
184
|
+
// Process unfinalized blocks
|
|
185
|
+
for (let i = unfinalizedIndex; i < blocks.length; i++) {
|
|
186
|
+
state.unfinalizedHeads.push({ number: blocks[i].header.number, hash: blocks[i].header.hash });
|
|
187
|
+
}
|
|
188
|
+
await this.db.transactHot2({
|
|
189
|
+
finalizedHead: toHashAndHeight(finalizedHeadData ?? state.finalizedHead),
|
|
190
|
+
baseHead: toHashAndHeight(prevHead ?? state.finalizedHead),
|
|
191
|
+
newBlocks: blocks.map((b) => toHashAndHeight(b.header)),
|
|
192
|
+
}, (store, start, end) => {
|
|
193
|
+
return this.handler({
|
|
194
|
+
store,
|
|
195
|
+
blocks: blocks.slice(start, end),
|
|
196
|
+
isHead: isOnTop,
|
|
197
|
+
});
|
|
135
198
|
});
|
|
136
|
-
}
|
|
199
|
+
}
|
|
137
200
|
let mappingEndTime = process.hrtime.bigint();
|
|
138
|
-
this.updateProgressMetrics(chainHeight, nextHead, mappingEndTime);
|
|
201
|
+
this.updateProgressMetrics(chainHeight, nextHead.number, mappingEndTime);
|
|
139
202
|
this.metrics.registerBatch(blocks.length, (0, util_1.getItemsCount)(blocks), mappingStartTime, mappingEndTime);
|
|
140
203
|
this.reportStatus();
|
|
141
|
-
return
|
|
204
|
+
return state;
|
|
142
205
|
}
|
|
143
206
|
reportStatus() {
|
|
144
207
|
if (this.statusReportTimer == null) {
|
|
@@ -165,4 +228,37 @@ class Processor {
|
|
|
165
228
|
}
|
|
166
229
|
}
|
|
167
230
|
}
|
|
231
|
+
function findRollbackIndex(currentChain, forkChain) {
|
|
232
|
+
let currentIndex = 0;
|
|
233
|
+
let forkIndex = 0;
|
|
234
|
+
let lastCommonIndex = -1;
|
|
235
|
+
while (currentIndex < currentChain.length && forkIndex < forkChain.length) {
|
|
236
|
+
const currentBlock = currentChain[currentIndex];
|
|
237
|
+
const forkBlock = forkChain[forkIndex];
|
|
238
|
+
if (currentBlock.number > forkBlock.number) {
|
|
239
|
+
forkIndex++;
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
if (currentBlock.number < forkBlock.number) {
|
|
243
|
+
currentIndex++;
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
if (currentBlock.hash !== forkBlock.hash) {
|
|
247
|
+
return lastCommonIndex;
|
|
248
|
+
}
|
|
249
|
+
lastCommonIndex = currentIndex;
|
|
250
|
+
currentIndex++;
|
|
251
|
+
forkIndex++;
|
|
252
|
+
}
|
|
253
|
+
return lastCommonIndex;
|
|
254
|
+
}
|
|
255
|
+
function toHashAndHeight(ref) {
|
|
256
|
+
return { height: ref.number, hash: ref.hash };
|
|
257
|
+
}
|
|
258
|
+
function toBlockRef(hashAndHeight) {
|
|
259
|
+
return { number: hashAndHeight.height, hash: hashAndHeight.hash };
|
|
260
|
+
}
|
|
261
|
+
function getStateHead(state) {
|
|
262
|
+
return (0, util_internal_1.maybeLast)(state.unfinalizedHeads) ?? state.finalizedHead;
|
|
263
|
+
}
|
|
168
264
|
//# 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":"
|
|
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 {
|
|
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:
|
|
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,
|
|
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
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.timeInterval = timeInterval;
|
|
4
|
+
exports.getItemsCount = getItemsCount;
|
|
5
|
+
exports.formatHead = formatHead;
|
|
6
|
+
exports.shortHash = shortHash;
|
|
4
7
|
function timeInterval(seconds) {
|
|
5
8
|
if (seconds < 60) {
|
|
6
9
|
return Math.round(seconds) + 's';
|
|
@@ -13,7 +16,6 @@ function timeInterval(seconds) {
|
|
|
13
16
|
minutes = minutes - hours * 60;
|
|
14
17
|
return hours + 'h ' + minutes + 'm';
|
|
15
18
|
}
|
|
16
|
-
exports.timeInterval = timeInterval;
|
|
17
19
|
function getItemsCount(blocks) {
|
|
18
20
|
let count = 0;
|
|
19
21
|
for (let block of blocks) {
|
|
@@ -26,11 +28,9 @@ function getItemsCount(blocks) {
|
|
|
26
28
|
}
|
|
27
29
|
return count;
|
|
28
30
|
}
|
|
29
|
-
exports.getItemsCount = getItemsCount;
|
|
30
31
|
function formatHead(head) {
|
|
31
|
-
return `${head.
|
|
32
|
+
return `${head.number}#${shortHash(head.hash)}`;
|
|
32
33
|
}
|
|
33
|
-
exports.formatHead = formatHead;
|
|
34
34
|
function shortHash(hash) {
|
|
35
35
|
if (hash.startsWith('0x')) {
|
|
36
36
|
return hash.slice(2, 7);
|
|
@@ -39,5 +39,4 @@ function shortHash(hash) {
|
|
|
39
39
|
return hash.slice(0, 5);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
exports.shortHash = shortHash;
|
|
43
42
|
//# sourceMappingURL=util.js.map
|
package/lib/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"
|
|
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.0.
|
|
3
|
+
"version": "0.1.0-portal-api.d0738f",
|
|
4
4
|
"description": "ETL processor",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"repository": "git@github.com:subsquid/squid.git",
|
|
@@ -14,16 +14,17 @@
|
|
|
14
14
|
],
|
|
15
15
|
"main": "lib/index.js",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@subsquid/logger": "^1.
|
|
17
|
+
"@subsquid/logger": "^1.4.0",
|
|
18
18
|
"@subsquid/util-internal": "^3.2.0",
|
|
19
19
|
"@subsquid/util-internal-counters": "^1.3.2",
|
|
20
20
|
"@subsquid/util-internal-prometheus-server": "^1.3.0",
|
|
21
21
|
"@subsquid/util-internal-range": "^0.3.0",
|
|
22
|
-
"prom-client": "^14.2.0"
|
|
22
|
+
"prom-client": "^14.2.0",
|
|
23
|
+
"@subsquid/util-internal-data-source": "0.0.1-portal-api.d0738f"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
26
|
"@types/node": "^18.18.14",
|
|
26
|
-
"typescript": "~5.
|
|
27
|
+
"typescript": "~5.5.4"
|
|
27
28
|
},
|
|
28
29
|
"scripts": {
|
|
29
30
|
"build": "rm -rf lib && tsc"
|
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<
|
|
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
package/src/run.ts
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
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
3
|
import {createPrometheusServer} from '@subsquid/util-internal-prometheus-server'
|
|
4
4
|
import * as prom from 'prom-client'
|
|
5
|
-
import {Database,
|
|
6
|
-
import {DataSource} from './datasource'
|
|
5
|
+
import {HashAndHeight, Database, HotDatabaseState} from './database'
|
|
7
6
|
import {Metrics} from './metrics'
|
|
7
|
+
import {DataSource, isForkException, BlockRef, type BlockBatch} from '@subsquid/util-internal-data-source'
|
|
8
8
|
import {formatHead, getItemsCount} from './util'
|
|
9
|
-
|
|
9
|
+
import assert from 'assert'
|
|
10
10
|
|
|
11
11
|
const log = createLogger('sqd:batch-processor')
|
|
12
12
|
|
|
13
|
-
|
|
14
13
|
export interface DataHandlerContext<Block, Store> {
|
|
15
14
|
/**
|
|
16
15
|
* Storage interface provided by the database
|
|
@@ -26,11 +25,14 @@ export interface DataHandlerContext<Block, Store> {
|
|
|
26
25
|
isHead: boolean
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
header: HashAndHeight
|
|
28
|
+
export interface BlockBase {
|
|
29
|
+
header: BlockRef
|
|
32
30
|
}
|
|
33
31
|
|
|
32
|
+
interface ProcessorState {
|
|
33
|
+
finalizedHead: BlockRef | undefined
|
|
34
|
+
unfinalizedHeads: BlockRef[]
|
|
35
|
+
}
|
|
34
36
|
|
|
35
37
|
/**
|
|
36
38
|
* Run data processing.
|
|
@@ -51,17 +53,18 @@ export function run<Block extends BlockBase, Store>(
|
|
|
51
53
|
db: Database<Store>,
|
|
52
54
|
dataHandler: (ctx: DataHandlerContext<Block, Store>) => Promise<void>
|
|
53
55
|
): void {
|
|
54
|
-
runProgram(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
runProgram(
|
|
57
|
+
() => {
|
|
58
|
+
return new Processor(src, db, dataHandler).run()
|
|
59
|
+
},
|
|
60
|
+
(err) => {
|
|
61
|
+
log.fatal(err)
|
|
62
|
+
}
|
|
63
|
+
)
|
|
59
64
|
}
|
|
60
65
|
|
|
61
|
-
|
|
62
66
|
class Processor<B extends BlockBase, S> {
|
|
63
67
|
private metrics = new Metrics()
|
|
64
|
-
private chainHeight: Throttler<number>
|
|
65
68
|
private statusReportTimer?: any
|
|
66
69
|
private hasStatusNews = false
|
|
67
70
|
|
|
@@ -69,39 +72,67 @@ class Processor<B extends BlockBase, S> {
|
|
|
69
72
|
private src: DataSource<B>,
|
|
70
73
|
private db: Database<S>,
|
|
71
74
|
private handler: (ctx: DataHandlerContext<B, S>) => Promise<void>
|
|
72
|
-
) {
|
|
73
|
-
this.chainHeight = new Throttler(() => this.src.getFinalizedHeight(), 30_000)
|
|
74
|
-
}
|
|
75
|
+
) {}
|
|
75
76
|
|
|
76
77
|
async run(): Promise<void> {
|
|
77
|
-
let
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
let getHead = this.db.supportsHotBlocks ? this.src.getHead.bind(this.src) : this.src.getFinalizedHead.bind(this.src)
|
|
79
|
+
let chainHeight = new Throttler(() => getHead()?.then((r) => r?.number ?? -1), 10_000)
|
|
80
|
+
|
|
81
|
+
let state: ProcessorState = {
|
|
82
|
+
finalizedHead: undefined,
|
|
83
|
+
unfinalizedHeads: [],
|
|
84
|
+
}
|
|
85
|
+
if (this.db.supportsHotBlocks) {
|
|
86
|
+
let dbState = await this.db.connect()
|
|
87
|
+
state.finalizedHead = dbState.height < 0 ? undefined : toBlockRef(dbState)
|
|
88
|
+
state.unfinalizedHeads = dbState.top.map(toBlockRef)
|
|
89
|
+
} else {
|
|
90
|
+
let dbState = await this.db.connect()
|
|
91
|
+
state.finalizedHead = dbState.height < 0 ? undefined : toBlockRef(dbState)
|
|
80
92
|
}
|
|
81
93
|
|
|
82
|
-
|
|
83
|
-
|
|
94
|
+
let head = getStateHead(state)
|
|
95
|
+
if (head != null) {
|
|
96
|
+
log.info(`last processed block was ${head.number}`)
|
|
97
|
+
}
|
|
98
|
+
await this.initMetrics(head?.number ?? -1, await chainHeight.get())
|
|
99
|
+
|
|
100
|
+
while (true) {
|
|
101
|
+
let getStream = this.db.supportsHotBlocks
|
|
102
|
+
? this.src.getStream.bind(this.src)
|
|
103
|
+
: this.src.getFinalizedStream.bind(this.src)
|
|
104
|
+
|
|
105
|
+
head = getStateHead(state)
|
|
106
|
+
try {
|
|
107
|
+
for await (let data of getStream({after: head})) {
|
|
108
|
+
state = await this.processBatch(state, data, await chainHeight.get())
|
|
109
|
+
}
|
|
110
|
+
break // Stream completed successfully, exit loop
|
|
111
|
+
} catch (e) {
|
|
112
|
+
if (!isForkException(e) || !this.db.supportsHotBlocks) throw e
|
|
84
113
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
114
|
+
// Handle fork and continue loop to retry
|
|
115
|
+
let chain = state.finalizedHead
|
|
116
|
+
? [state.finalizedHead, ...state.unfinalizedHeads]
|
|
117
|
+
: state.unfinalizedHeads
|
|
118
|
+
let rollbackIndex = findRollbackIndex(chain, e.previousBlocks)
|
|
119
|
+
if (rollbackIndex === -1) {
|
|
120
|
+
if (state.finalizedHead != null) throw new Error('Unable to process fork')
|
|
121
|
+
state.unfinalizedHeads = []
|
|
122
|
+
} else {
|
|
123
|
+
const rollbackHead = chain[rollbackIndex]
|
|
124
|
+
log.info(`navigating a fork on a common base ${formatHead(rollbackHead)}`)
|
|
125
|
+
|
|
126
|
+
state.unfinalizedHeads = chain.slice(1, rollbackIndex + 1)
|
|
127
|
+
}
|
|
88
128
|
}
|
|
89
129
|
}
|
|
90
130
|
|
|
91
131
|
this.reportFinalStatus()
|
|
92
132
|
}
|
|
93
133
|
|
|
94
|
-
private async
|
|
95
|
-
|
|
96
|
-
let hash = await this.src.getBlockHash(state.height)
|
|
97
|
-
if (state.hash === hash) return
|
|
98
|
-
throw new Error(
|
|
99
|
-
`already indexed block ${formatHead(state)} was not found on chain`
|
|
100
|
-
)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
private async initMetrics(state: HashAndHeight): Promise<void> {
|
|
104
|
-
await this.updateProgressMetrics(await this.chainHeight.get(), state)
|
|
134
|
+
private async initMetrics(state: number, chainHeight: number): Promise<void> {
|
|
135
|
+
this.updateProgressMetrics(chainHeight, state)
|
|
105
136
|
let port = process.env.PROCESSOR_PROMETHEUS_PORT || process.env.PROMETHEUS_PORT
|
|
106
137
|
if (port == null) return
|
|
107
138
|
prom.collectDefaultMetrics()
|
|
@@ -110,64 +141,104 @@ class Processor<B extends BlockBase, S> {
|
|
|
110
141
|
log.info(`prometheus metrics are served on port ${server.port}`)
|
|
111
142
|
}
|
|
112
143
|
|
|
113
|
-
private updateProgressMetrics(chainHeight: number,
|
|
144
|
+
private updateProgressMetrics(chainHeight: number, indexerHeight: number, time?: bigint): void {
|
|
114
145
|
this.metrics.setChainHeight(chainHeight)
|
|
115
|
-
this.metrics.setLastProcessedBlock(
|
|
116
|
-
let left
|
|
117
|
-
let processed
|
|
118
|
-
if (this.src.getBlocksCountInRange) {
|
|
119
|
-
left = this.src.getBlocksCountInRange({
|
|
120
|
-
from: this.metrics.getLastProcessedBlock() + 1,
|
|
121
|
-
to: this.metrics.getChainHeight()
|
|
122
|
-
})
|
|
123
|
-
processed = this.src.getBlocksCountInRange({
|
|
124
|
-
from: 0,
|
|
125
|
-
to: this.metrics.getChainHeight()
|
|
126
|
-
}) - left
|
|
127
|
-
} else {
|
|
128
|
-
left = this.metrics.getChainHeight() - this.metrics.getLastProcessedBlock()
|
|
129
|
-
processed = this.metrics.getLastProcessedBlock()
|
|
130
|
-
}
|
|
146
|
+
this.metrics.setLastProcessedBlock(indexerHeight)
|
|
147
|
+
let left = this.metrics.getChainHeight() - this.metrics.getLastProcessedBlock()
|
|
148
|
+
let processed = this.metrics.getLastProcessedBlock()
|
|
131
149
|
this.metrics.updateProgress(processed, left, time)
|
|
132
150
|
}
|
|
133
151
|
|
|
134
|
-
private async processBatch(
|
|
135
|
-
|
|
152
|
+
private async processBatch(
|
|
153
|
+
state: ProcessorState,
|
|
154
|
+
data: BlockBatch<B>,
|
|
155
|
+
chainHeight: number
|
|
156
|
+
): Promise<ProcessorState> {
|
|
157
|
+
let {blocks, finalizedHead: finalizedHeadData} = data
|
|
158
|
+
|
|
159
|
+
if (blocks.length === 0) return state
|
|
136
160
|
|
|
137
|
-
let
|
|
138
|
-
|
|
139
|
-
|
|
161
|
+
let prevHead = getStateHead(state)
|
|
162
|
+
|
|
163
|
+
// Validate data continuity
|
|
164
|
+
if (prevHead && prevHead.number >= blocks[0].header.number) {
|
|
165
|
+
throw new Error('Data is not continuous')
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let unfinalizedIndex = 0
|
|
169
|
+
if (finalizedHeadData != null) {
|
|
170
|
+
unfinalizedIndex = blocks.findIndex((b) => b.header.number > finalizedHeadData!.number)
|
|
140
171
|
}
|
|
141
172
|
|
|
142
|
-
let
|
|
173
|
+
let nextHead = last(blocks).header
|
|
174
|
+
let isOnTop = nextHead.number >= chainHeight
|
|
143
175
|
|
|
144
176
|
let mappingStartTime = process.hrtime.bigint()
|
|
145
177
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
178
|
+
// All new blocks are finalized
|
|
179
|
+
if (unfinalizedIndex < 0) {
|
|
180
|
+
const finalizedRef = blocks[blocks.length - 1].header
|
|
181
|
+
state.finalizedHead = {number: finalizedRef.number, hash: finalizedRef.hash}
|
|
182
|
+
state.unfinalizedHeads = []
|
|
183
|
+
|
|
184
|
+
await this.db.transact(
|
|
185
|
+
{
|
|
186
|
+
prevHead: prevHead ? toHashAndHeight(prevHead) : {height: -1, hash: '0x'},
|
|
187
|
+
nextHead: toHashAndHeight(nextHead),
|
|
188
|
+
isOnTop,
|
|
189
|
+
},
|
|
190
|
+
(store) => {
|
|
191
|
+
return this.handler({
|
|
192
|
+
store,
|
|
193
|
+
blocks,
|
|
194
|
+
isHead: isOnTop,
|
|
195
|
+
})
|
|
196
|
+
}
|
|
197
|
+
)
|
|
198
|
+
} else {
|
|
199
|
+
assert(this.db.supportsHotBlocks)
|
|
200
|
+
|
|
201
|
+
let finalizedRef: BlockRef | undefined = blocks[unfinalizedIndex - 1]?.header
|
|
202
|
+
if (finalizedHeadData?.hash && finalizedHeadData?.number != null) {
|
|
203
|
+
finalizedRef = {hash: finalizedHeadData.hash, number: finalizedHeadData.number}
|
|
204
|
+
}
|
|
205
|
+
state.finalizedHead = finalizedRef ?? state.finalizedHead
|
|
206
|
+
|
|
207
|
+
// Finalize all hot heads that are older than the cold head
|
|
208
|
+
if (state.finalizedHead) {
|
|
209
|
+
let finalizeIndex = state.unfinalizedHeads.findIndex((h) => h.number > state.finalizedHead!.number)
|
|
210
|
+
state.unfinalizedHeads = finalizeIndex < 0 ? [] : state.unfinalizedHeads.slice(finalizeIndex)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Process unfinalized blocks
|
|
214
|
+
for (let i = unfinalizedIndex; i < blocks.length; i++) {
|
|
215
|
+
state.unfinalizedHeads.push({number: blocks[i].header.number, hash: blocks[i].header.hash})
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
await this.db.transactHot2(
|
|
219
|
+
{
|
|
220
|
+
finalizedHead: toHashAndHeight(finalizedHeadData ?? state.finalizedHead),
|
|
221
|
+
baseHead: toHashAndHeight(prevHead ?? state.finalizedHead),
|
|
222
|
+
newBlocks: blocks.map((b) => toHashAndHeight(b.header)),
|
|
223
|
+
},
|
|
224
|
+
(store, start, end) => {
|
|
225
|
+
return this.handler({
|
|
226
|
+
store,
|
|
227
|
+
blocks: blocks.slice(start, end),
|
|
228
|
+
isHead: isOnTop,
|
|
229
|
+
})
|
|
230
|
+
}
|
|
231
|
+
)
|
|
232
|
+
}
|
|
157
233
|
|
|
158
234
|
let mappingEndTime = process.hrtime.bigint()
|
|
159
235
|
|
|
160
|
-
this.updateProgressMetrics(chainHeight, nextHead, mappingEndTime)
|
|
161
|
-
this.metrics.registerBatch(
|
|
162
|
-
blocks.length,
|
|
163
|
-
getItemsCount(blocks),
|
|
164
|
-
mappingStartTime,
|
|
165
|
-
mappingEndTime
|
|
166
|
-
)
|
|
236
|
+
this.updateProgressMetrics(chainHeight, nextHead.number, mappingEndTime)
|
|
237
|
+
this.metrics.registerBatch(blocks.length, getItemsCount(blocks), mappingStartTime, mappingEndTime)
|
|
167
238
|
|
|
168
239
|
this.reportStatus()
|
|
169
240
|
|
|
170
|
-
return
|
|
241
|
+
return state
|
|
171
242
|
}
|
|
172
243
|
|
|
173
244
|
private reportStatus(): void {
|
|
@@ -179,7 +250,7 @@ class Processor<B extends BlockBase, S> {
|
|
|
179
250
|
this.hasStatusNews = false
|
|
180
251
|
this.reportStatus()
|
|
181
252
|
}
|
|
182
|
-
},
|
|
253
|
+
}, 5_000)
|
|
183
254
|
} else {
|
|
184
255
|
this.hasStatusNews = true
|
|
185
256
|
}
|
|
@@ -195,3 +266,46 @@ class Processor<B extends BlockBase, S> {
|
|
|
195
266
|
}
|
|
196
267
|
}
|
|
197
268
|
}
|
|
269
|
+
|
|
270
|
+
function findRollbackIndex(currentChain: BlockRef[], forkChain: BlockRef[]): number {
|
|
271
|
+
let currentIndex = 0
|
|
272
|
+
let forkIndex = 0
|
|
273
|
+
let lastCommonIndex = -1
|
|
274
|
+
|
|
275
|
+
while (currentIndex < currentChain.length && forkIndex < forkChain.length) {
|
|
276
|
+
const currentBlock = currentChain[currentIndex]
|
|
277
|
+
const forkBlock = forkChain[forkIndex]
|
|
278
|
+
|
|
279
|
+
if (currentBlock.number > forkBlock.number) {
|
|
280
|
+
forkIndex++
|
|
281
|
+
continue
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (currentBlock.number < forkBlock.number) {
|
|
285
|
+
currentIndex++
|
|
286
|
+
continue
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (currentBlock.hash !== forkBlock.hash) {
|
|
290
|
+
return lastCommonIndex
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
lastCommonIndex = currentIndex
|
|
294
|
+
currentIndex++
|
|
295
|
+
forkIndex++
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return lastCommonIndex
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function toHashAndHeight(ref: BlockRef): HashAndHeight {
|
|
302
|
+
return {height: ref.number, hash: ref.hash}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function toBlockRef(hashAndHeight: HashAndHeight): BlockRef {
|
|
306
|
+
return {number: hashAndHeight.height, hash: hashAndHeight.hash}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function getStateHead(state: ProcessorState): BlockRef | undefined {
|
|
310
|
+
return maybeLast(state.unfinalizedHeads) ?? state.finalizedHead
|
|
311
|
+
}
|
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:
|
|
33
|
-
return `${head.
|
|
33
|
+
export function formatHead(head: BlockRef): string {
|
|
34
|
+
return `${head.number}#${shortHash(head.hash)}`
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
|
package/lib/datasource.d.ts
DELETED
|
@@ -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
|
package/lib/datasource.d.ts.map
DELETED
|
@@ -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
package/lib/datasource.js.map
DELETED
|
@@ -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
|
-
}
|