envio 3.1.0-rc.2 → 3.1.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/index.d.ts +12 -0
- package/package.json +6 -6
- package/src/GlobalState.res +1 -0
- package/src/GlobalState.res.mjs +1 -1
- package/src/InMemoryStore.res +8 -0
- package/src/InMemoryStore.res.mjs +7 -2
- package/src/Main.res +17 -1
- package/src/Main.res.mjs +11 -2
- package/src/Persistence.res +3 -0
- package/src/RollbackCommit.res +32 -0
- package/src/RollbackCommit.res.mjs +35 -0
package/index.d.ts
CHANGED
|
@@ -1201,6 +1201,18 @@ export type IndexerFromConfig<Config extends IndexerConfigTypes = GlobalConfig>
|
|
|
1201
1201
|
readonly name: string;
|
|
1202
1202
|
/** The indexer description from config.yaml. */
|
|
1203
1203
|
readonly description: string | undefined;
|
|
1204
|
+
/**
|
|
1205
|
+
* Internal, unstable API that will be removed without notice. Registers a
|
|
1206
|
+
* callback fired once per chain affected by a reorg rollback, after the
|
|
1207
|
+
* rollback is durably written to the database. A throwing callback crashes
|
|
1208
|
+
* the indexer through the same path as a failed write.
|
|
1209
|
+
*/
|
|
1210
|
+
readonly "~internalAndWillBeRemovedSoon_onRollbackCommit": (
|
|
1211
|
+
callback: (args: {
|
|
1212
|
+
readonly chainId: number;
|
|
1213
|
+
readonly rollbackToBlock: number;
|
|
1214
|
+
}) => Promise<void>,
|
|
1215
|
+
) => void;
|
|
1204
1216
|
} & SingleEcosystemChains<Config>
|
|
1205
1217
|
>;
|
|
1206
1218
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envio",
|
|
3
|
-
"version": "3.1.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
|
|
6
6
|
"bin": "./bin.mjs",
|
|
@@ -70,10 +70,10 @@
|
|
|
70
70
|
"tsx": "4.21.0"
|
|
71
71
|
},
|
|
72
72
|
"optionalDependencies": {
|
|
73
|
-
"envio-linux-x64": "3.1.0
|
|
74
|
-
"envio-linux-x64-musl": "3.1.0
|
|
75
|
-
"envio-linux-arm64": "3.1.0
|
|
76
|
-
"envio-darwin-x64": "3.1.0
|
|
77
|
-
"envio-darwin-arm64": "3.1.0
|
|
73
|
+
"envio-linux-x64": "3.1.0",
|
|
74
|
+
"envio-linux-x64-musl": "3.1.0",
|
|
75
|
+
"envio-linux-arm64": "3.1.0",
|
|
76
|
+
"envio-darwin-x64": "3.1.0",
|
|
77
|
+
"envio-darwin-arm64": "3.1.0"
|
|
78
78
|
}
|
|
79
79
|
}
|
package/src/GlobalState.res
CHANGED
|
@@ -1159,6 +1159,7 @@ let injectedTaskReducer = (
|
|
|
1159
1159
|
~persistence=state.ctx.persistence,
|
|
1160
1160
|
~rollbackTargetCheckpointId,
|
|
1161
1161
|
~rollbackDiffCheckpointId=state.ctx.inMemoryStore.committedCheckpointId->BigInt.add(1n),
|
|
1162
|
+
~progressBlockNumberByChainId=newProgressBlockNumberPerChain,
|
|
1162
1163
|
)
|
|
1163
1164
|
|
|
1164
1165
|
let chainManager = {
|
package/src/GlobalState.res.mjs
CHANGED
|
@@ -1151,7 +1151,7 @@ function injectedTaskReducer(waitForNewBlock, executeQuery, getLastKnownValidBlo
|
|
|
1151
1151
|
};
|
|
1152
1152
|
});
|
|
1153
1153
|
await InMemoryStore.flush(state.ctx.inMemoryStore);
|
|
1154
|
-
let diff$1 = await InMemoryStore.prepareRollbackDiff(state.ctx.inMemoryStore, state.ctx.persistence, rollbackTargetCheckpointId, state.ctx.inMemoryStore.committedCheckpointId + 1n);
|
|
1154
|
+
let diff$1 = await InMemoryStore.prepareRollbackDiff(state.ctx.inMemoryStore, state.ctx.persistence, rollbackTargetCheckpointId, state.ctx.inMemoryStore.committedCheckpointId + 1n, newProgressBlockNumberPerChain);
|
|
1155
1155
|
let init = state.chainManager;
|
|
1156
1156
|
let chainManager_isInReorgThreshold = init.isInReorgThreshold;
|
|
1157
1157
|
let chainManager_isRealtime = init.isRealtime;
|
package/src/InMemoryStore.res
CHANGED
|
@@ -359,6 +359,12 @@ let runOneWrite = async (inMemoryStore: t, ~persistence: Persistence.t, ~config)
|
|
|
359
359
|
)
|
|
360
360
|
|
|
361
361
|
inMemoryStore.committedCheckpointId = upToCheckpointId
|
|
362
|
+
|
|
363
|
+
switch rollback {
|
|
364
|
+
| Some({progressBlockNumberByChainId}) if RollbackCommit.callbacks->Utils.Array.notEmpty =>
|
|
365
|
+
await RollbackCommit.fire(~progressBlockNumberByChainId)
|
|
366
|
+
| _ => ()
|
|
367
|
+
}
|
|
362
368
|
}
|
|
363
369
|
}
|
|
364
370
|
|
|
@@ -494,12 +500,14 @@ let prepareRollbackDiff = async (
|
|
|
494
500
|
~persistence: Persistence.t,
|
|
495
501
|
~rollbackTargetCheckpointId,
|
|
496
502
|
~rollbackDiffCheckpointId,
|
|
503
|
+
~progressBlockNumberByChainId,
|
|
497
504
|
) => {
|
|
498
505
|
inMemoryStore.entities = EntityTables.make(inMemoryStore.allEntities)
|
|
499
506
|
inMemoryStore.effects = Dict.make()
|
|
500
507
|
inMemoryStore.rollback = Some({
|
|
501
508
|
targetCheckpointId: rollbackTargetCheckpointId,
|
|
502
509
|
diffCheckpointId: rollbackDiffCheckpointId,
|
|
510
|
+
progressBlockNumberByChainId,
|
|
503
511
|
})
|
|
504
512
|
|
|
505
513
|
let deletedEntities = Dict.make()
|
|
@@ -11,6 +11,7 @@ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
|
11
11
|
import * as ErrorHandling from "./ErrorHandling.res.mjs";
|
|
12
12
|
import * as InMemoryTable from "./InMemoryTable.res.mjs";
|
|
13
13
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
14
|
+
import * as RollbackCommit from "./RollbackCommit.res.mjs";
|
|
14
15
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
15
16
|
import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
|
|
16
17
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
@@ -300,6 +301,9 @@ async function runOneWrite(inMemoryStore, persistence, config) {
|
|
|
300
301
|
let updatedEffectsCache = snapshotEffects(inMemoryStore, cache);
|
|
301
302
|
await persistence.storage.writeBatch(batch, rollback, batch.isInReorgThreshold, config, persistence.allEntities, updatedEffectsCache, updatedEntities, chainMetaData);
|
|
302
303
|
inMemoryStore.committedCheckpointId = upToCheckpointId;
|
|
304
|
+
if (rollback !== undefined && Utils.$$Array.notEmpty(RollbackCommit.callbacks)) {
|
|
305
|
+
return await RollbackCommit.fire(rollback.progressBlockNumberByChainId);
|
|
306
|
+
}
|
|
303
307
|
}
|
|
304
308
|
|
|
305
309
|
function hasPendingWrite(inMemoryStore) {
|
|
@@ -401,12 +405,13 @@ async function flush(inMemoryStore) {
|
|
|
401
405
|
}
|
|
402
406
|
}
|
|
403
407
|
|
|
404
|
-
async function prepareRollbackDiff(inMemoryStore, persistence, rollbackTargetCheckpointId, rollbackDiffCheckpointId) {
|
|
408
|
+
async function prepareRollbackDiff(inMemoryStore, persistence, rollbackTargetCheckpointId, rollbackDiffCheckpointId, progressBlockNumberByChainId) {
|
|
405
409
|
inMemoryStore.entities = make(inMemoryStore.allEntities);
|
|
406
410
|
inMemoryStore.effects = {};
|
|
407
411
|
inMemoryStore.rollback = {
|
|
408
412
|
targetCheckpointId: rollbackTargetCheckpointId,
|
|
409
|
-
diffCheckpointId: rollbackDiffCheckpointId
|
|
413
|
+
diffCheckpointId: rollbackDiffCheckpointId,
|
|
414
|
+
progressBlockNumberByChainId: progressBlockNumberByChainId
|
|
410
415
|
};
|
|
411
416
|
let deletedEntities = {};
|
|
412
417
|
let setEntities = {};
|
package/src/Main.res
CHANGED
|
@@ -312,6 +312,13 @@ let getGlobalIndexer = (): 'indexer => {
|
|
|
312
312
|
)
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
+
let onRollbackCommitFn = (callback: 'a) => {
|
|
316
|
+
HandlerRegister.throwIfFinishedRegistration(
|
|
317
|
+
~methodName="~internalAndWillBeRemovedSoon_onRollbackCommit",
|
|
318
|
+
)
|
|
319
|
+
let _ = RollbackCommit.register(callback->(Utils.magic: 'a => RollbackCommit.callback))
|
|
320
|
+
}
|
|
321
|
+
|
|
315
322
|
// Two-stage parse: first the ecosystem-specific outer schema unwraps the
|
|
316
323
|
// wrapper (`block.number` / `block.height` / `slot`) and surfaces the
|
|
317
324
|
// inner chunk as raw `unknown`; then the shared `blockRangeSchema`
|
|
@@ -453,8 +460,16 @@ let getGlobalIndexer = (): 'indexer => {
|
|
|
453
460
|
"onEvent",
|
|
454
461
|
"contractRegister",
|
|
455
462
|
"onBlock",
|
|
463
|
+
"~internalAndWillBeRemovedSoon_onRollbackCommit",
|
|
464
|
+
]
|
|
465
|
+
| Svm => [
|
|
466
|
+
"name",
|
|
467
|
+
"description",
|
|
468
|
+
"chainIds",
|
|
469
|
+
"chains",
|
|
470
|
+
"onSlot",
|
|
471
|
+
"~internalAndWillBeRemovedSoon_onRollbackCommit",
|
|
456
472
|
]
|
|
457
|
-
| Svm => ["name", "description", "chainIds", "chains", "onSlot"]
|
|
458
473
|
}
|
|
459
474
|
keysMemo := Some(keys)
|
|
460
475
|
keys
|
|
@@ -477,6 +492,7 @@ let getGlobalIndexer = (): 'indexer => {
|
|
|
477
492
|
| "onEvent" => onEventFn->Utils.magic
|
|
478
493
|
| "contractRegister" => contractRegisterFn->Utils.magic
|
|
479
494
|
| "onBlock" | "onSlot" => onBlockFn->Utils.magic
|
|
495
|
+
| "~internalAndWillBeRemovedSoon_onRollbackCommit" => onRollbackCommitFn->Utils.magic
|
|
480
496
|
| _ =>
|
|
481
497
|
JsError.throwWithMessage(
|
|
482
498
|
`Field \`${prop}\` does not exist on \`indexer\`. Available fields: ${getKeys()->Array.join(
|
package/src/Main.res.mjs
CHANGED
|
@@ -25,6 +25,7 @@ import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
|
25
25
|
import * as SourceManager from "./sources/SourceManager.res.mjs";
|
|
26
26
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
27
27
|
import * as Helpers from "yargs/helpers";
|
|
28
|
+
import * as RollbackCommit from "./RollbackCommit.res.mjs";
|
|
28
29
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
29
30
|
import * as HandlerRegister from "./HandlerRegister.res.mjs";
|
|
30
31
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
@@ -255,6 +256,10 @@ function getGlobalIndexer() {
|
|
|
255
256
|
let match = parseIdentityConfig(identityConfig);
|
|
256
257
|
HandlerRegister.setContractRegister(match[0], match[1], handler, match[2], undefined);
|
|
257
258
|
};
|
|
259
|
+
let onRollbackCommitFn = callback => {
|
|
260
|
+
HandlerRegister.throwIfFinishedRegistration("~internalAndWillBeRemovedSoon_onRollbackCommit");
|
|
261
|
+
RollbackCommit.register(callback);
|
|
262
|
+
};
|
|
258
263
|
let extractRange = (filter, name, ecosystem) => {
|
|
259
264
|
try {
|
|
260
265
|
let inner = S$RescriptSchema.parseOrThrow(filter, ecosystem.onBlockFilterSchema);
|
|
@@ -341,7 +346,8 @@ function getGlobalIndexer() {
|
|
|
341
346
|
"description",
|
|
342
347
|
"chainIds",
|
|
343
348
|
"chains",
|
|
344
|
-
"onSlot"
|
|
349
|
+
"onSlot",
|
|
350
|
+
"~internalAndWillBeRemovedSoon_onRollbackCommit"
|
|
345
351
|
];
|
|
346
352
|
break;
|
|
347
353
|
}
|
|
@@ -353,7 +359,8 @@ function getGlobalIndexer() {
|
|
|
353
359
|
"chains",
|
|
354
360
|
"onEvent",
|
|
355
361
|
"contractRegister",
|
|
356
|
-
"onBlock"
|
|
362
|
+
"onBlock",
|
|
363
|
+
"~internalAndWillBeRemovedSoon_onRollbackCommit"
|
|
357
364
|
];
|
|
358
365
|
}
|
|
359
366
|
keysMemo.contents = keys;
|
|
@@ -376,6 +383,8 @@ function getGlobalIndexer() {
|
|
|
376
383
|
case "onBlock" :
|
|
377
384
|
case "onSlot" :
|
|
378
385
|
return onBlockFn;
|
|
386
|
+
case "~internalAndWillBeRemovedSoon_onRollbackCommit" :
|
|
387
|
+
return onRollbackCommitFn;
|
|
379
388
|
default:
|
|
380
389
|
return Stdlib_JsError.throwWithMessage(`Field \`` + prop + `\` does not exist on \`indexer\`. Available fields: ` + getKeys().join(", ") + `.`);
|
|
381
390
|
}
|
package/src/Persistence.res
CHANGED
|
@@ -51,6 +51,9 @@ type updatedEffectCache = {
|
|
|
51
51
|
type rollback = {
|
|
52
52
|
targetCheckpointId: Internal.checkpointId,
|
|
53
53
|
diffCheckpointId: Internal.checkpointId,
|
|
54
|
+
// Last valid block per chain affected by the rollback. Read by
|
|
55
|
+
// `RollbackCommit.fire` once the diff is durably written.
|
|
56
|
+
progressBlockNumberByChainId: dict<int>,
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
type updatedEntity = {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Temporary, internal-only support for the unstable
|
|
2
|
+
// `indexer.~internalAndWillBeRemovedSoon_onRollbackCommit` API. The whole
|
|
3
|
+
// feature lives here plus two call sites: registration in `Main.res` and the
|
|
4
|
+
// fire on a successful rollback write in `InMemoryStore.res`. Delete those
|
|
5
|
+
// together with this module.
|
|
6
|
+
type args = {chainId: int, rollbackToBlock: int}
|
|
7
|
+
type callback = args => promise<unit>
|
|
8
|
+
|
|
9
|
+
let callbacks: array<callback> = []
|
|
10
|
+
|
|
11
|
+
let register = (callback: callback) => {
|
|
12
|
+
callbacks->Array.push(callback)
|
|
13
|
+
() =>
|
|
14
|
+
switch callbacks->Array.indexOf(callback) {
|
|
15
|
+
| -1 => ()
|
|
16
|
+
| index => callbacks->Array.splice(~start=index, ~remove=1, ~insert=[])
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Fired after a rollback diff is durably written, once per affected chain.
|
|
21
|
+
// `progressBlockNumberByChainId` is the last valid block per chain, taken from
|
|
22
|
+
// the in-memory store's rollback object. A throwing callback bubbles to the
|
|
23
|
+
// write loop's onError, crashing the indexer like a failed write.
|
|
24
|
+
let fire = async (~progressBlockNumberByChainId: dict<int>) => {
|
|
25
|
+
let _ = await progressBlockNumberByChainId
|
|
26
|
+
->Dict.toArray
|
|
27
|
+
->Array.flatMap(((chainIdKey, rollbackToBlock)) => {
|
|
28
|
+
let args = {chainId: chainIdKey->Int.fromString->Option.getUnsafe, rollbackToBlock}
|
|
29
|
+
callbacks->Array.map(callback => callback(args))
|
|
30
|
+
})
|
|
31
|
+
->Promise.all
|
|
32
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
|
|
4
|
+
|
|
5
|
+
let callbacks = [];
|
|
6
|
+
|
|
7
|
+
function register(callback) {
|
|
8
|
+
callbacks.push(callback);
|
|
9
|
+
return () => {
|
|
10
|
+
let index = callbacks.indexOf(callback);
|
|
11
|
+
if (index !== -1) {
|
|
12
|
+
callbacks.splice(index, 1);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function fire(progressBlockNumberByChainId) {
|
|
19
|
+
await Promise.all(Object.entries(progressBlockNumberByChainId).flatMap(param => {
|
|
20
|
+
let args_chainId = Stdlib_Int.fromString(param[0], undefined);
|
|
21
|
+
let args_rollbackToBlock = param[1];
|
|
22
|
+
let args = {
|
|
23
|
+
chainId: args_chainId,
|
|
24
|
+
rollbackToBlock: args_rollbackToBlock
|
|
25
|
+
};
|
|
26
|
+
return callbacks.map(callback => callback(args));
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
callbacks,
|
|
32
|
+
register,
|
|
33
|
+
fire,
|
|
34
|
+
}
|
|
35
|
+
/* No side effect */
|