envio 3.0.2 → 3.1.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/evm.schema.json +15 -8
- package/fuel.schema.json +19 -12
- package/index.d.ts +0 -2
- package/package.json +6 -7
- package/rescript.json +1 -1
- package/src/Batch.res +4 -214
- package/src/Batch.res.mjs +6 -165
- package/src/ChainFetcher.res +4 -5
- package/src/ChainFetcher.res.mjs +6 -7
- package/src/ChainManager.res +10 -9
- package/src/ChainManager.res.mjs +6 -10
- package/src/Config.res +9 -25
- package/src/Config.res.mjs +17 -27
- package/src/Core.res +7 -0
- package/src/Ctx.res +1 -0
- package/src/Env.res +0 -1
- package/src/Env.res.mjs +0 -3
- package/src/EventConfigBuilder.res +13 -123
- package/src/EventConfigBuilder.res.mjs +6 -73
- package/src/EventProcessing.res +5 -29
- package/src/EventProcessing.res.mjs +11 -20
- package/src/EventUtils.res +0 -27
- package/src/EventUtils.res.mjs +0 -24
- package/src/FetchState.res +1 -11
- package/src/FetchState.res.mjs +2 -16
- package/src/GlobalState.res +23 -37
- package/src/GlobalState.res.mjs +10 -38
- package/src/HandlerLoader.res +6 -5
- package/src/HandlerLoader.res.mjs +27 -9
- package/src/HandlerRegister.res +1 -12
- package/src/HandlerRegister.res.mjs +1 -6
- package/src/HandlerRegister.resi +1 -1
- package/src/Hasura.res +96 -32
- package/src/Hasura.res.mjs +93 -38
- package/src/InMemoryStore.res +181 -45
- package/src/InMemoryStore.res.mjs +143 -40
- package/src/InMemoryTable.res +147 -247
- package/src/InMemoryTable.res.mjs +131 -230
- package/src/Internal.res +10 -34
- package/src/Internal.res.mjs +9 -3
- package/src/LoadLayer.res +5 -5
- package/src/LoadLayer.res.mjs +5 -5
- package/src/Main.res +4 -6
- package/src/Main.res.mjs +26 -15
- package/src/Persistence.res +7 -132
- package/src/Persistence.res.mjs +1 -102
- package/src/PgStorage.res +57 -40
- package/src/PgStorage.res.mjs +60 -34
- package/src/ReorgDetection.res +35 -58
- package/src/ReorgDetection.res.mjs +21 -29
- package/src/SimulateItems.res.mjs +21 -3
- package/src/Sink.res +2 -2
- package/src/Sink.res.mjs +1 -1
- package/src/TableIndices.res +9 -2
- package/src/TableIndices.res.mjs +7 -1
- package/src/TestIndexer.res +53 -60
- package/src/TestIndexer.res.mjs +77 -63
- package/src/TestIndexerProxyStorage.res +4 -14
- package/src/TestIndexerProxyStorage.res.mjs +1 -5
- package/src/UserContext.res +2 -4
- package/src/UserContext.res.mjs +4 -5
- package/src/Utils.res +0 -2
- package/src/Utils.res.mjs +0 -3
- package/src/bindings/ClickHouse.res +45 -38
- package/src/bindings/ClickHouse.res.mjs +16 -17
- package/src/bindings/Vitest.res +3 -0
- package/src/db/InternalTable.res +59 -18
- package/src/db/InternalTable.res.mjs +82 -51
- package/src/db/Table.res +9 -2
- package/src/db/Table.res.mjs +10 -7
- package/src/sources/EvmChain.res +32 -9
- package/src/sources/EvmChain.res.mjs +31 -4
- package/src/sources/HyperFuelSource.res +14 -57
- package/src/sources/HyperFuelSource.res.mjs +18 -38
- package/src/sources/HyperSync.res +36 -101
- package/src/sources/HyperSync.res.mjs +42 -96
- package/src/sources/HyperSync.resi +4 -22
- package/src/sources/HyperSyncClient.res +67 -245
- package/src/sources/HyperSyncClient.res.mjs +47 -46
- package/src/sources/HyperSyncSource.res +76 -147
- package/src/sources/HyperSyncSource.res.mjs +61 -114
- package/src/sources/RpcSource.res +43 -22
- package/src/sources/RpcSource.res.mjs +50 -35
- package/src/sources/SimulateSource.res +1 -7
- package/src/sources/SimulateSource.res.mjs +1 -7
- package/src/sources/Source.res +8 -1
- package/src/sources/SourceManager.res +9 -0
- package/src/sources/SourceManager.res.mjs +10 -0
- package/src/sources/SourceManager.resi +2 -0
- package/svm.schema.json +11 -4
package/src/Main.res
CHANGED
|
@@ -24,7 +24,6 @@ type state =
|
|
|
24
24
|
chains: array<chainData>,
|
|
25
25
|
indexerStartTime: Date.t,
|
|
26
26
|
isPreRegisteringDynamicContracts: bool,
|
|
27
|
-
isUnorderedMultichainMode: bool,
|
|
28
27
|
rollbackOnReorg: bool,
|
|
29
28
|
})
|
|
30
29
|
|
|
@@ -51,7 +50,6 @@ let stateSchema = S.union([
|
|
|
51
50
|
indexerStartTime: s.matches(S.datetime(S.string)),
|
|
52
51
|
// Keep the field, since Dev Console expects it to be present
|
|
53
52
|
isPreRegisteringDynamicContracts: false,
|
|
54
|
-
isUnorderedMultichainMode: s.matches(S.bool),
|
|
55
53
|
rollbackOnReorg: s.matches(S.bool),
|
|
56
54
|
})),
|
|
57
55
|
])
|
|
@@ -692,6 +690,10 @@ let start = async (
|
|
|
692
690
|
Ctx.registrations,
|
|
693
691
|
config,
|
|
694
692
|
persistence,
|
|
693
|
+
inMemoryStore: InMemoryStore.make(
|
|
694
|
+
~entities=persistence.allEntities,
|
|
695
|
+
~committedCheckpointId=(persistence->Persistence.getInitializedState).checkpointId,
|
|
696
|
+
),
|
|
695
697
|
}
|
|
696
698
|
|
|
697
699
|
let envioVersion = Utils.EnvioPackage.value.version
|
|
@@ -744,10 +746,6 @@ let start = async (
|
|
|
744
746
|
indexerStartTime: state.indexerStartTime,
|
|
745
747
|
isPreRegisteringDynamicContracts: false,
|
|
746
748
|
rollbackOnReorg: ctx.config.shouldRollbackOnReorg,
|
|
747
|
-
isUnorderedMultichainMode: switch ctx.config.multichain {
|
|
748
|
-
| Unordered => true
|
|
749
|
-
| Ordered => false
|
|
750
|
-
},
|
|
751
749
|
})
|
|
752
750
|
}
|
|
753
751
|
}
|
package/src/Main.res.mjs
CHANGED
|
@@ -19,6 +19,7 @@ import Yargs from "yargs/yargs";
|
|
|
19
19
|
import * as ChainFetcher from "./ChainFetcher.res.mjs";
|
|
20
20
|
import * as ChainManager from "./ChainManager.res.mjs";
|
|
21
21
|
import * as HandlerLoader from "./HandlerLoader.res.mjs";
|
|
22
|
+
import * as InMemoryStore from "./InMemoryStore.res.mjs";
|
|
22
23
|
import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
23
24
|
import * as SourceManager from "./sources/SourceManager.res.mjs";
|
|
24
25
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
@@ -58,7 +59,6 @@ let stateSchema = S$RescriptSchema.union([
|
|
|
58
59
|
chains: s.m(S$RescriptSchema.array(chainDataSchema)),
|
|
59
60
|
indexerStartTime: s.m(S$RescriptSchema.datetime(S$RescriptSchema.string, undefined)),
|
|
60
61
|
isPreRegisteringDynamicContracts: false,
|
|
61
|
-
isUnorderedMultichainMode: s.m(S$RescriptSchema.bool),
|
|
62
62
|
rollbackOnReorg: s.m(S$RescriptSchema.bool)
|
|
63
63
|
}))
|
|
64
64
|
]);
|
|
@@ -501,19 +501,34 @@ async function start(persistence, resetOpt, isTestOpt, exitAfterFirstEventBlockO
|
|
|
501
501
|
let match = await HandlerLoader.registerAllHandlers(configWithoutRegistrations);
|
|
502
502
|
let registrations = match[1];
|
|
503
503
|
let config = match[0];
|
|
504
|
-
let config$1
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
504
|
+
let config$1 = isTest ? ({
|
|
505
|
+
name: config.name,
|
|
506
|
+
description: config.description,
|
|
507
|
+
handlers: config.handlers,
|
|
508
|
+
contractHandlers: config.contractHandlers,
|
|
509
|
+
shouldRollbackOnReorg: false,
|
|
510
|
+
shouldSaveFullHistory: config.shouldSaveFullHistory,
|
|
511
|
+
storage: config.storage,
|
|
512
|
+
chainMap: config.chainMap,
|
|
513
|
+
defaultChain: config.defaultChain,
|
|
514
|
+
ecosystem: config.ecosystem,
|
|
515
|
+
enableRawEvents: config.enableRawEvents,
|
|
516
|
+
maxAddrInPartition: config.maxAddrInPartition,
|
|
517
|
+
batchSize: config.batchSize,
|
|
518
|
+
lowercaseAddresses: config.lowercaseAddresses,
|
|
519
|
+
isDev: config.isDev,
|
|
520
|
+
userEntitiesByName: config.userEntitiesByName,
|
|
521
|
+
userEntities: config.userEntities,
|
|
522
|
+
allEntities: config.allEntities,
|
|
523
|
+
allEnums: config.allEnums
|
|
524
|
+
}) : config;
|
|
512
525
|
let config$2 = patchConfig !== undefined ? patchConfig(config$1, registrations) : config$1;
|
|
526
|
+
let ctx_inMemoryStore = InMemoryStore.make(persistence$1.allEntities, Persistence.getInitializedState(persistence$1).checkpointId);
|
|
513
527
|
let ctx = {
|
|
514
528
|
registrations: registrations,
|
|
515
529
|
config: config$2,
|
|
516
|
-
persistence: persistence$1
|
|
530
|
+
persistence: persistence$1,
|
|
531
|
+
inMemoryStore: ctx_inMemoryStore
|
|
517
532
|
};
|
|
518
533
|
let envioVersion = Utils.EnvioPackage.value.version;
|
|
519
534
|
Prometheus.Info.set(envioVersion);
|
|
@@ -546,21 +561,17 @@ async function start(persistence, resetOpt, isTestOpt, exitAfterFirstEventBlockO
|
|
|
546
561
|
numAddresses: FetchState.numAddresses(cf.fetchState)
|
|
547
562
|
};
|
|
548
563
|
});
|
|
549
|
-
let match = config$2.multichain;
|
|
550
|
-
let tmp;
|
|
551
|
-
tmp = match !== "ordered";
|
|
552
564
|
return {
|
|
553
565
|
status: "active",
|
|
554
566
|
envioVersion: envioVersion,
|
|
555
567
|
chains: chains,
|
|
556
568
|
indexerStartTime: state.indexerStartTime,
|
|
557
569
|
isPreRegisteringDynamicContracts: false,
|
|
558
|
-
isUnorderedMultichainMode: tmp,
|
|
559
570
|
rollbackOnReorg: config$2.shouldRollbackOnReorg
|
|
560
571
|
};
|
|
561
572
|
}, ctx, isDevelopmentMode);
|
|
562
573
|
}
|
|
563
|
-
let chainManager = ChainManager.makeFromDbState(Persistence.getInitializedState(persistence$1), config$2, registrations);
|
|
574
|
+
let chainManager = ChainManager.makeFromDbState(Persistence.getInitializedState(persistence$1), config$2, registrations, undefined);
|
|
564
575
|
let globalState = GlobalState.make(ctx, chainManager, isDevelopmentMode, shouldUseTui, exitAfterFirstEventBlock);
|
|
565
576
|
let gsManager = GlobalStateManager.make(globalState, undefined);
|
|
566
577
|
if (shouldUseTui) {
|
package/src/Persistence.res
CHANGED
|
@@ -48,9 +48,14 @@ type updatedEffectCache = {
|
|
|
48
48
|
shouldInitialize: bool,
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
type rollback = {
|
|
52
|
+
targetCheckpointId: Internal.checkpointId,
|
|
53
|
+
diffCheckpointId: Internal.checkpointId,
|
|
54
|
+
}
|
|
55
|
+
|
|
51
56
|
type updatedEntity = {
|
|
52
57
|
entityConfig: Internal.entityConfig,
|
|
53
|
-
|
|
58
|
+
changes: array<Change.t<Internal.entity>>,
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
type storage = {
|
|
@@ -122,7 +127,7 @@ type storage = {
|
|
|
122
127
|
writeBatch: (
|
|
123
128
|
~batch: Batch.t,
|
|
124
129
|
~rawEvents: array<InternalTable.RawEvents.t>,
|
|
125
|
-
~
|
|
130
|
+
~rollback: option<rollback>,
|
|
126
131
|
~isInReorgThreshold: bool,
|
|
127
132
|
~config: Config.t,
|
|
128
133
|
~allEntities: array<Internal.entityConfig>,
|
|
@@ -263,133 +268,3 @@ let getInitializedState = persistence => {
|
|
|
263
268
|
| Ready(initialState) => initialState
|
|
264
269
|
}
|
|
265
270
|
}
|
|
266
|
-
|
|
267
|
-
let writeBatch = (
|
|
268
|
-
persistence,
|
|
269
|
-
~batch,
|
|
270
|
-
~config,
|
|
271
|
-
~inMemoryStore: InMemoryStore.t,
|
|
272
|
-
~isInReorgThreshold,
|
|
273
|
-
) =>
|
|
274
|
-
switch persistence.storageStatus {
|
|
275
|
-
| Unknown
|
|
276
|
-
| Initializing(_) =>
|
|
277
|
-
JsError.throwWithMessage(`Failed to access the indexer storage. The Persistence layer is not initialized.`)
|
|
278
|
-
| Ready({cache}) =>
|
|
279
|
-
let updatedEntities = persistence.allEntities->Belt.Array.keepMap(entityConfig => {
|
|
280
|
-
let updates =
|
|
281
|
-
inMemoryStore
|
|
282
|
-
->InMemoryStore.getInMemTable(~entityConfig)
|
|
283
|
-
->InMemoryTable.Entity.updates
|
|
284
|
-
if updates->Utils.Array.isEmpty {
|
|
285
|
-
None
|
|
286
|
-
} else {
|
|
287
|
-
Some({entityConfig, updates})
|
|
288
|
-
}
|
|
289
|
-
})
|
|
290
|
-
persistence.storage.writeBatch(
|
|
291
|
-
~batch,
|
|
292
|
-
~rawEvents=inMemoryStore.rawEvents->InMemoryTable.values,
|
|
293
|
-
~rollbackTargetCheckpointId=inMemoryStore.rollbackTargetCheckpointId,
|
|
294
|
-
~isInReorgThreshold,
|
|
295
|
-
~config,
|
|
296
|
-
~allEntities=persistence.allEntities,
|
|
297
|
-
~updatedEntities,
|
|
298
|
-
~updatedEffectsCache={
|
|
299
|
-
let acc = []
|
|
300
|
-
inMemoryStore.effects->Utils.Dict.forEach(inMemTable => {
|
|
301
|
-
let {idsToStore, dict, effect, invalidationsCount} = inMemTable
|
|
302
|
-
switch idsToStore {
|
|
303
|
-
| [] => ()
|
|
304
|
-
| ids =>
|
|
305
|
-
let items = Belt.Array.makeUninitializedUnsafe(ids->Belt.Array.length)
|
|
306
|
-
ids->Belt.Array.forEachWithIndex((index, id) => {
|
|
307
|
-
items->Array.setUnsafe(
|
|
308
|
-
index,
|
|
309
|
-
(
|
|
310
|
-
{
|
|
311
|
-
id,
|
|
312
|
-
output: dict->Dict.getUnsafe(id),
|
|
313
|
-
}: Internal.effectCacheItem
|
|
314
|
-
),
|
|
315
|
-
)
|
|
316
|
-
})
|
|
317
|
-
let effectName = effect.name
|
|
318
|
-
let effectCacheRecord = switch cache->Utils.Dict.dangerouslyGetNonOption(effectName) {
|
|
319
|
-
| Some(c) => c
|
|
320
|
-
| None =>
|
|
321
|
-
let c = {effectName, count: 0}
|
|
322
|
-
cache->Dict.set(effectName, c)
|
|
323
|
-
c
|
|
324
|
-
}
|
|
325
|
-
let shouldInitialize = effectCacheRecord.count === 0
|
|
326
|
-
effectCacheRecord.count =
|
|
327
|
-
effectCacheRecord.count + items->Array.length - invalidationsCount
|
|
328
|
-
Prometheus.EffectCacheCount.set(~count=effectCacheRecord.count, ~effectName)
|
|
329
|
-
acc->Array.push({effect, items, shouldInitialize})->ignore
|
|
330
|
-
}
|
|
331
|
-
})
|
|
332
|
-
acc
|
|
333
|
-
},
|
|
334
|
-
)
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
let prepareRollbackDiff = async (
|
|
338
|
-
persistence: t,
|
|
339
|
-
~rollbackTargetCheckpointId,
|
|
340
|
-
~rollbackDiffCheckpointId,
|
|
341
|
-
) => {
|
|
342
|
-
let inMemStore = InMemoryStore.make(
|
|
343
|
-
~entities=persistence.allEntities,
|
|
344
|
-
~rollbackTargetCheckpointId,
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
let deletedEntities = Dict.make()
|
|
348
|
-
let setEntities = Dict.make()
|
|
349
|
-
|
|
350
|
-
let _ = await persistence.allEntities
|
|
351
|
-
->Belt.Array.map(async entityConfig => {
|
|
352
|
-
let entityTable = inMemStore->InMemoryStore.getInMemTable(~entityConfig)
|
|
353
|
-
|
|
354
|
-
let (removedIdsResult, restoredEntitiesResult) = await persistence.storage.getRollbackData(
|
|
355
|
-
~entityConfig,
|
|
356
|
-
~rollbackTargetCheckpointId,
|
|
357
|
-
)
|
|
358
|
-
|
|
359
|
-
// Process removed IDs
|
|
360
|
-
removedIdsResult->Array.forEach(data => {
|
|
361
|
-
deletedEntities->Utils.Dict.push(entityConfig.name, data["id"])
|
|
362
|
-
entityTable->InMemoryTable.Entity.set(
|
|
363
|
-
Delete({
|
|
364
|
-
entityId: data["id"],
|
|
365
|
-
checkpointId: rollbackDiffCheckpointId,
|
|
366
|
-
}),
|
|
367
|
-
~shouldSaveHistory=false,
|
|
368
|
-
~containsRollbackDiffChange=true,
|
|
369
|
-
)
|
|
370
|
-
})
|
|
371
|
-
|
|
372
|
-
let restoredEntities = restoredEntitiesResult->S.parseOrThrow(entityConfig.rowsSchema)
|
|
373
|
-
|
|
374
|
-
// Process restored entities
|
|
375
|
-
restoredEntities->Belt.Array.forEach((entity: Internal.entity) => {
|
|
376
|
-
setEntities->Utils.Dict.push(entityConfig.name, entity.id)
|
|
377
|
-
entityTable->InMemoryTable.Entity.set(
|
|
378
|
-
Set({
|
|
379
|
-
entityId: entity.id,
|
|
380
|
-
checkpointId: rollbackDiffCheckpointId,
|
|
381
|
-
entity,
|
|
382
|
-
}),
|
|
383
|
-
~shouldSaveHistory=false,
|
|
384
|
-
~containsRollbackDiffChange=true,
|
|
385
|
-
)
|
|
386
|
-
})
|
|
387
|
-
})
|
|
388
|
-
->Promise.all
|
|
389
|
-
|
|
390
|
-
{
|
|
391
|
-
"inMemStore": inMemStore,
|
|
392
|
-
"deletedEntities": deletedEntities,
|
|
393
|
-
"setEntities": setEntities,
|
|
394
|
-
}
|
|
395
|
-
}
|
package/src/Persistence.res.mjs
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
-
import * as Utils from "./Utils.res.mjs";
|
|
4
3
|
import * as Config from "./Config.res.mjs";
|
|
5
4
|
import * as Logging from "./Logging.res.mjs";
|
|
6
|
-
import * as Belt_Array from "@rescript/runtime/lib/es6/Belt_Array.js";
|
|
7
|
-
import * as Prometheus from "./Prometheus.res.mjs";
|
|
8
5
|
import * as EntityHistory from "./db/EntityHistory.res.mjs";
|
|
9
6
|
import * as ErrorHandling from "./ErrorHandling.res.mjs";
|
|
10
|
-
import * as InMemoryStore from "./InMemoryStore.res.mjs";
|
|
11
|
-
import * as InMemoryTable from "./InMemoryTable.res.mjs";
|
|
12
7
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
13
|
-
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
14
8
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
15
9
|
|
|
16
10
|
let StorageError = /* @__PURE__ */Primitive_exceptions.create("Persistence.StorageError");
|
|
@@ -122,106 +116,11 @@ function getInitializedState(persistence) {
|
|
|
122
116
|
}
|
|
123
117
|
}
|
|
124
118
|
|
|
125
|
-
function writeBatch(persistence, batch, config, inMemoryStore, isInReorgThreshold) {
|
|
126
|
-
let match = persistence.storageStatus;
|
|
127
|
-
if (typeof match !== "object") {
|
|
128
|
-
return Stdlib_JsError.throwWithMessage(`Failed to access the indexer storage. The Persistence layer is not initialized.`);
|
|
129
|
-
}
|
|
130
|
-
if (match.TAG === "Initializing") {
|
|
131
|
-
return Stdlib_JsError.throwWithMessage(`Failed to access the indexer storage. The Persistence layer is not initialized.`);
|
|
132
|
-
}
|
|
133
|
-
let cache = match._0.cache;
|
|
134
|
-
let updatedEntities = Belt_Array.keepMap(persistence.allEntities, entityConfig => {
|
|
135
|
-
let updates = InMemoryTable.Entity.updates(InMemoryStore.getInMemTable(inMemoryStore, entityConfig));
|
|
136
|
-
if (Utils.$$Array.isEmpty(updates)) {
|
|
137
|
-
return;
|
|
138
|
-
} else {
|
|
139
|
-
return {
|
|
140
|
-
entityConfig: entityConfig,
|
|
141
|
-
updates: updates
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
let acc = [];
|
|
146
|
-
return persistence.storage.writeBatch(batch, InMemoryTable.values(inMemoryStore.rawEvents), inMemoryStore.rollbackTargetCheckpointId, isInReorgThreshold, config, persistence.allEntities, (Utils.Dict.forEach(inMemoryStore.effects, inMemTable => {
|
|
147
|
-
let idsToStore = inMemTable.idsToStore;
|
|
148
|
-
let invalidationsCount = inMemTable.invalidationsCount;
|
|
149
|
-
let effect = inMemTable.effect;
|
|
150
|
-
let dict = inMemTable.dict;
|
|
151
|
-
if (idsToStore.length === 0) {
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
let items = new Array(idsToStore.length);
|
|
155
|
-
Belt_Array.forEachWithIndex(idsToStore, (index, id) => {
|
|
156
|
-
items[index] = {
|
|
157
|
-
id: id,
|
|
158
|
-
output: dict[id]
|
|
159
|
-
};
|
|
160
|
-
});
|
|
161
|
-
let effectName = effect.name;
|
|
162
|
-
let c = cache[effectName];
|
|
163
|
-
let effectCacheRecord;
|
|
164
|
-
if (c !== undefined) {
|
|
165
|
-
effectCacheRecord = c;
|
|
166
|
-
} else {
|
|
167
|
-
let c$1 = {
|
|
168
|
-
effectName: effectName,
|
|
169
|
-
count: 0
|
|
170
|
-
};
|
|
171
|
-
cache[effectName] = c$1;
|
|
172
|
-
effectCacheRecord = c$1;
|
|
173
|
-
}
|
|
174
|
-
let shouldInitialize = effectCacheRecord.count === 0;
|
|
175
|
-
effectCacheRecord.count = (effectCacheRecord.count + items.length | 0) - invalidationsCount | 0;
|
|
176
|
-
Prometheus.EffectCacheCount.set(effectCacheRecord.count, effectName);
|
|
177
|
-
acc.push({
|
|
178
|
-
effect: effect,
|
|
179
|
-
items: items,
|
|
180
|
-
shouldInitialize: shouldInitialize
|
|
181
|
-
});
|
|
182
|
-
}), acc), updatedEntities);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
async function prepareRollbackDiff(persistence, rollbackTargetCheckpointId, rollbackDiffCheckpointId) {
|
|
186
|
-
let inMemStore = InMemoryStore.make(persistence.allEntities, rollbackTargetCheckpointId);
|
|
187
|
-
let deletedEntities = {};
|
|
188
|
-
let setEntities = {};
|
|
189
|
-
await Promise.all(Belt_Array.map(persistence.allEntities, async entityConfig => {
|
|
190
|
-
let entityTable = InMemoryStore.getInMemTable(inMemStore, entityConfig);
|
|
191
|
-
let match = await persistence.storage.getRollbackData(entityConfig, rollbackTargetCheckpointId);
|
|
192
|
-
match[0].forEach(data => {
|
|
193
|
-
Utils.Dict.push(deletedEntities, entityConfig.name, data.id);
|
|
194
|
-
InMemoryTable.Entity.set(entityTable, {
|
|
195
|
-
type: "DELETE",
|
|
196
|
-
entityId: data.id,
|
|
197
|
-
checkpointId: rollbackDiffCheckpointId
|
|
198
|
-
}, false, true);
|
|
199
|
-
});
|
|
200
|
-
let restoredEntities = S$RescriptSchema.parseOrThrow(match[1], entityConfig.rowsSchema);
|
|
201
|
-
return Belt_Array.forEach(restoredEntities, entity => {
|
|
202
|
-
Utils.Dict.push(setEntities, entityConfig.name, entity.id);
|
|
203
|
-
InMemoryTable.Entity.set(entityTable, {
|
|
204
|
-
type: "SET",
|
|
205
|
-
entityId: entity.id,
|
|
206
|
-
entity: entity,
|
|
207
|
-
checkpointId: rollbackDiffCheckpointId
|
|
208
|
-
}, false, true);
|
|
209
|
-
});
|
|
210
|
-
}));
|
|
211
|
-
return {
|
|
212
|
-
inMemStore: inMemStore,
|
|
213
|
-
deletedEntities: deletedEntities,
|
|
214
|
-
setEntities: setEntities
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
|
|
218
119
|
export {
|
|
219
120
|
StorageError,
|
|
220
121
|
make,
|
|
221
122
|
init,
|
|
222
123
|
getInitializedStorageOrThrow,
|
|
223
124
|
getInitializedState,
|
|
224
|
-
writeBatch,
|
|
225
|
-
prepareRollbackDiff,
|
|
226
125
|
}
|
|
227
|
-
/*
|
|
126
|
+
/* Config Not a pure module */
|
package/src/PgStorage.res
CHANGED
|
@@ -717,7 +717,7 @@ let rec writeBatch = async (
|
|
|
717
717
|
~batch: Batch.t,
|
|
718
718
|
~rawEvents,
|
|
719
719
|
~pgSchema,
|
|
720
|
-
~
|
|
720
|
+
~rollback: option<Persistence.rollback>,
|
|
721
721
|
~isInReorgThreshold,
|
|
722
722
|
~config: Config.t,
|
|
723
723
|
~allEntities: array<Internal.entityConfig>,
|
|
@@ -745,14 +745,55 @@ let rec writeBatch = async (
|
|
|
745
745
|
~items=rawEvents,
|
|
746
746
|
)
|
|
747
747
|
|
|
748
|
-
let setEntities = updatedEntities->Belt.Array.map(({entityConfig,
|
|
748
|
+
let setEntities = updatedEntities->Belt.Array.map(({entityConfig, changes}) => {
|
|
749
749
|
let entitiesToSet = []
|
|
750
750
|
let idsToDelete = []
|
|
751
751
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
752
|
+
// The rollback-diff change is written to the entity table only, never the
|
|
753
|
+
// history table; when present it is an id's oldest change.
|
|
754
|
+
let diffCheckpointId = rollback->Option.map(r => r.diffCheckpointId)
|
|
755
|
+
|
|
756
|
+
// History batches, populated only when saving history.
|
|
757
|
+
let batchSetUpdates = []
|
|
758
|
+
let batchDeleteEntityIds = []
|
|
759
|
+
let batchDeleteCheckpointIds = []
|
|
760
|
+
let idsWithDiff = Utils.Set.make()
|
|
761
|
+
|
|
762
|
+
// Single pass over the change log: track each id's latest change (the last
|
|
763
|
+
// one seen) and, when saving history, fan every non-diff change out to the
|
|
764
|
+
// history-table batches.
|
|
765
|
+
let latestChangeById = Dict.make()
|
|
766
|
+
let orderedIds = []
|
|
767
|
+
changes->Belt.Array.forEach(change => {
|
|
768
|
+
let entityId = change->Change.getEntityId
|
|
769
|
+
if latestChangeById->Utils.Dict.dangerouslyGetNonOption(entityId)->Option.isNone {
|
|
770
|
+
orderedIds->Belt.Array.push(entityId)
|
|
771
|
+
}
|
|
772
|
+
latestChangeById->Dict.set(entityId, change)
|
|
773
|
+
if shouldSaveHistory {
|
|
774
|
+
if Some(change->Change.getCheckpointId) === diffCheckpointId {
|
|
775
|
+
idsWithDiff->Utils.Set.add(entityId)->ignore
|
|
776
|
+
} else {
|
|
777
|
+
switch change {
|
|
778
|
+
| Delete({entityId, checkpointId}) =>
|
|
779
|
+
batchDeleteEntityIds->Belt.Array.push(entityId)->ignore
|
|
780
|
+
batchDeleteCheckpointIds->Belt.Array.push(checkpointId)->ignore
|
|
781
|
+
| Set(_) => batchSetUpdates->Belt.Array.push(change)->ignore
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
})
|
|
786
|
+
|
|
787
|
+
let backfillHistoryIds = Utils.Set.make()
|
|
788
|
+
orderedIds->Belt.Array.forEach(entityId => {
|
|
789
|
+
switch latestChangeById->Dict.getUnsafe(entityId) {
|
|
790
|
+
| Set({entity}) => entitiesToSet->Belt.Array.push(entity)
|
|
791
|
+
| Delete({entityId}) => idsToDelete->Belt.Array.push(entityId)
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// An id needs a history backfill iff none of its changes is the diff.
|
|
795
|
+
if shouldSaveHistory && !(idsWithDiff->Utils.Set.has(entityId)) {
|
|
796
|
+
backfillHistoryIds->Utils.Set.add(entityId)->ignore
|
|
756
797
|
}
|
|
757
798
|
})
|
|
758
799
|
|
|
@@ -766,34 +807,6 @@ let rec writeBatch = async (
|
|
|
766
807
|
let promises = []
|
|
767
808
|
|
|
768
809
|
if shouldSaveHistory {
|
|
769
|
-
let backfillHistoryIds = Utils.Set.make()
|
|
770
|
-
let batchSetUpdates = []
|
|
771
|
-
// Use unnest approach
|
|
772
|
-
let batchDeleteCheckpointIds = []
|
|
773
|
-
let batchDeleteEntityIds = []
|
|
774
|
-
|
|
775
|
-
updates->Array.forEach(update => {
|
|
776
|
-
switch update {
|
|
777
|
-
| {history, containsRollbackDiffChange} =>
|
|
778
|
-
history->Array.forEach(
|
|
779
|
-
(change: Change.t<'a>) => {
|
|
780
|
-
if !containsRollbackDiffChange {
|
|
781
|
-
backfillHistoryIds->Utils.Set.add(change->Change.getEntityId)->ignore
|
|
782
|
-
}
|
|
783
|
-
switch change {
|
|
784
|
-
| Delete({entityId}) => {
|
|
785
|
-
batchDeleteEntityIds->Belt.Array.push(entityId)->ignore
|
|
786
|
-
batchDeleteCheckpointIds
|
|
787
|
-
->Belt.Array.push(change->Change.getCheckpointId)
|
|
788
|
-
->ignore
|
|
789
|
-
}
|
|
790
|
-
| Set(_) => batchSetUpdates->Array.push(change)->ignore
|
|
791
|
-
}
|
|
792
|
-
},
|
|
793
|
-
)
|
|
794
|
-
}
|
|
795
|
-
})
|
|
796
|
-
|
|
797
810
|
if backfillHistoryIds->Utils.Set.size !== 0 {
|
|
798
811
|
// This must run before updating entity or entity history tables
|
|
799
812
|
await EntityHistory.backfillHistory(
|
|
@@ -913,8 +926,8 @@ let rec writeBatch = async (
|
|
|
913
926
|
//In the event of a rollback, rollback all meta tables based on the given
|
|
914
927
|
//valid event identifier, where all rows created after this eventIdentifier should
|
|
915
928
|
//be deleted
|
|
916
|
-
let rollbackTables = switch
|
|
917
|
-
| Some(rollbackTargetCheckpointId) =>
|
|
929
|
+
let rollbackTables = switch rollback {
|
|
930
|
+
| Some({targetCheckpointId: rollbackTargetCheckpointId}) =>
|
|
918
931
|
Some(
|
|
919
932
|
sql => {
|
|
920
933
|
let promises = allEntities->Array.map(entityConfig => {
|
|
@@ -1026,7 +1039,7 @@ let rec writeBatch = async (
|
|
|
1026
1039
|
~rawEvents,
|
|
1027
1040
|
~batch,
|
|
1028
1041
|
~pgSchema,
|
|
1029
|
-
~
|
|
1042
|
+
~rollback,
|
|
1030
1043
|
~isInReorgThreshold,
|
|
1031
1044
|
~config,
|
|
1032
1045
|
~setEffectCacheOrThrow,
|
|
@@ -1619,7 +1632,7 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
|
|
|
1619
1632
|
let writeBatchMethod = async (
|
|
1620
1633
|
~batch,
|
|
1621
1634
|
~rawEvents,
|
|
1622
|
-
~
|
|
1635
|
+
~rollback,
|
|
1623
1636
|
~isInReorgThreshold,
|
|
1624
1637
|
~config,
|
|
1625
1638
|
~allEntities,
|
|
@@ -1665,7 +1678,7 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
|
|
|
1665
1678
|
~batch,
|
|
1666
1679
|
~rawEvents,
|
|
1667
1680
|
~pgSchema,
|
|
1668
|
-
~
|
|
1681
|
+
~rollback,
|
|
1669
1682
|
~isInReorgThreshold,
|
|
1670
1683
|
~config,
|
|
1671
1684
|
~allEntities,
|
|
@@ -1789,7 +1802,11 @@ let makeStorageFromEnv = (
|
|
|
1789
1802
|
secret: Env.Hasura.secret,
|
|
1790
1803
|
},
|
|
1791
1804
|
~pgSchema,
|
|
1792
|
-
~tableNames
|
|
1805
|
+
~tableConfigs=tableNames->Array.map(tableName => {
|
|
1806
|
+
Hasura.tableName,
|
|
1807
|
+
description: None,
|
|
1808
|
+
columnDescriptions: dict{},
|
|
1809
|
+
}),
|
|
1793
1810
|
)->Promise.catch(err => {
|
|
1794
1811
|
Logging.errorWithExn(
|
|
1795
1812
|
err->Utils.prettifyExn,
|