envio 3.5.1 → 3.6.1
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/evm.schema.json +7 -0
- package/fuel.schema.json +7 -0
- package/index.d.ts +33 -10
- package/package.json +6 -6
- package/src/ChainState.res +22 -4
- package/src/ChainState.res.mjs +20 -3
- package/src/ChainState.resi +3 -0
- package/src/Config.res +60 -2
- package/src/Config.res.mjs +49 -13
- package/src/EffectState.res +2 -2
- package/src/EffectState.res.mjs +2 -2
- package/src/EntityTables.res +32 -0
- package/src/EntityTables.res.mjs +44 -0
- package/src/Envio.res +7 -7
- package/src/Envio.res.mjs +5 -6
- package/src/Hasura.res +37 -3
- package/src/Hasura.res.mjs +23 -5
- package/src/InMemoryStore.res +48 -8
- package/src/InMemoryStore.res.mjs +37 -7
- package/src/IndexerState.res +30 -24
- package/src/IndexerState.res.mjs +20 -35
- package/src/IndexerState.resi +8 -6
- package/src/Internal.res +29 -11
- package/src/Internal.res.mjs +27 -10
- package/src/LoadLayer.res +39 -8
- package/src/LoadLayer.res.mjs +36 -9
- package/src/LoadLayer.resi +2 -0
- package/src/Metrics.res +5 -5
- package/src/Metrics.res.mjs +5 -1
- package/src/Persistence.res +12 -1
- package/src/PgStorage.res +183 -37
- package/src/PgStorage.res.mjs +149 -34
- package/src/PruneStaleHistory.res +1 -0
- package/src/PruneStaleHistory.res.mjs +2 -1
- package/src/Sink.res +3 -3
- package/src/Sink.res.mjs +2 -2
- package/src/TestIndexer.res +128 -17
- package/src/TestIndexer.res.mjs +75 -9
- package/src/UserContext.res +19 -4
- package/src/UserContext.res.mjs +15 -9
- package/src/Writing.res +8 -16
- package/src/Writing.res.mjs +10 -10
- package/src/bindings/ClickHouse.res +40 -4
- package/src/bindings/ClickHouse.res.mjs +37 -5
- package/src/db/EntityHistory.res +64 -21
- package/src/db/EntityHistory.res.mjs +43 -22
- package/src/db/InternalTable.res.mjs +31 -31
- package/src/db/Table.res +24 -1
- package/src/db/Table.res.mjs +26 -4
- package/src/sources/SourceManager.res +6 -12
- package/src/sources/SourceManager.res.mjs +8 -5
- package/svm.schema.json +7 -0
package/evm.schema.json
CHANGED
|
@@ -49,6 +49,13 @@
|
|
|
49
49
|
}
|
|
50
50
|
]
|
|
51
51
|
},
|
|
52
|
+
"disable_default_cross_chain": {
|
|
53
|
+
"description": "Make entities and effect caches per-chain instead of shared across every chain (recommended). Sharing then becomes explicit — add `@crossChain` to an entity in schema.graphql or `crossChain: true` to an effect. (default: false)",
|
|
54
|
+
"type": [
|
|
55
|
+
"boolean",
|
|
56
|
+
"null"
|
|
57
|
+
]
|
|
58
|
+
},
|
|
52
59
|
"ecosystem": {
|
|
53
60
|
"description": "Ecosystem of the project.",
|
|
54
61
|
"anyOf": [
|
package/fuel.schema.json
CHANGED
|
@@ -49,6 +49,13 @@
|
|
|
49
49
|
}
|
|
50
50
|
]
|
|
51
51
|
},
|
|
52
|
+
"disable_default_cross_chain": {
|
|
53
|
+
"description": "Make entities and effect caches per-chain instead of shared across every chain (recommended). Sharing then becomes explicit — add `@crossChain` to an entity in schema.graphql or `crossChain: true` to an effect. (default: false)",
|
|
54
|
+
"type": [
|
|
55
|
+
"boolean",
|
|
56
|
+
"null"
|
|
57
|
+
]
|
|
58
|
+
},
|
|
52
59
|
"ecosystem": {
|
|
53
60
|
"description": "Ecosystem of the project.",
|
|
54
61
|
"$ref": "#/$defs/EcosystemTag"
|
package/index.d.ts
CHANGED
|
@@ -48,8 +48,7 @@ export type EffectCaller = <I, O>(
|
|
|
48
48
|
input: I extends undefined ? undefined : I
|
|
49
49
|
) => Promise<O>;
|
|
50
50
|
|
|
51
|
-
/** The chain an Effect was called on. Available only on chain-scoped effects
|
|
52
|
-
* (`crossChain: false`). */
|
|
51
|
+
/** The chain an Effect was called on. Available only on chain-scoped effects. */
|
|
53
52
|
export type EffectChain = {
|
|
54
53
|
/** The chain id the effect handler was called on. */
|
|
55
54
|
readonly id: number;
|
|
@@ -64,8 +63,8 @@ export type EffectContext = {
|
|
|
64
63
|
/** Whether to cache this call's result. Defaults to the effect's `cache`
|
|
65
64
|
* option; set to `false` to skip caching for this specific invocation. */
|
|
66
65
|
cache: boolean;
|
|
67
|
-
/** The chain the effect was called on. Only available on
|
|
68
|
-
*
|
|
66
|
+
/** The chain the effect was called on. Only available on chain-scoped
|
|
67
|
+
* effects; accessing it on a cross-chain effect throws. */
|
|
69
68
|
readonly chain: EffectChain;
|
|
70
69
|
};
|
|
71
70
|
|
|
@@ -93,9 +92,10 @@ export type EffectOptions<Input, Output> = {
|
|
|
93
92
|
/** Whether the effect should be cached. */
|
|
94
93
|
readonly cache?: boolean;
|
|
95
94
|
/** Whether the effect's cache is shared across all chains. Defaults to
|
|
96
|
-
* `true
|
|
97
|
-
*
|
|
98
|
-
*
|
|
95
|
+
* `true`, or to `false` when config.yaml sets
|
|
96
|
+
* `disable_default_cross_chain: true`. Set to `false` to isolate the cache
|
|
97
|
+
* and rate limiting per chain and enable `context.chain.id` inside the
|
|
98
|
+
* handler. Changing this changes the effect's cache identity. */
|
|
99
99
|
readonly crossChain?: boolean;
|
|
100
100
|
};
|
|
101
101
|
|
|
@@ -225,8 +225,10 @@ export function createEffect<
|
|
|
225
225
|
/** Whether the effect should be cached. */
|
|
226
226
|
readonly cache?: boolean;
|
|
227
227
|
/** Whether the effect's cache is shared across all chains. Defaults to
|
|
228
|
-
* `true
|
|
229
|
-
*
|
|
228
|
+
* `true`, or to `false` when config.yaml sets
|
|
229
|
+
* `disable_default_cross_chain: true`. Set to `false` to isolate the cache
|
|
230
|
+
* and rate limiting per chain and enable `context.chain.id` inside the
|
|
231
|
+
* handler. */
|
|
230
232
|
readonly crossChain?: boolean;
|
|
231
233
|
},
|
|
232
234
|
handler: (args: EffectArgs<I>) => Promise<R>
|
|
@@ -502,6 +504,8 @@ type IndexerConfigTypes = {
|
|
|
502
504
|
};
|
|
503
505
|
svm?: { chains: Record<string, { id: number }> };
|
|
504
506
|
entities?: Record<string, object>;
|
|
507
|
+
// Union of the entity names whose rows belong to a single chain, or `never`.
|
|
508
|
+
perChainEntities?: string;
|
|
505
509
|
enums?: Record<string, string>;
|
|
506
510
|
};
|
|
507
511
|
|
|
@@ -1529,6 +1533,21 @@ type AddressRegistration = {
|
|
|
1529
1533
|
type ConfigEntities<Config extends IndexerConfigTypes = GlobalConfig> =
|
|
1530
1534
|
Config["entities"] extends Record<string, object> ? Config["entities"] : {};
|
|
1531
1535
|
|
|
1536
|
+
/** Entity names whose rows belong to a single chain. */
|
|
1537
|
+
type PerChainEntityNames<Config extends IndexerConfigTypes = GlobalConfig> =
|
|
1538
|
+
Config extends { perChainEntities: infer Names extends string } ? Names : never;
|
|
1539
|
+
|
|
1540
|
+
/** The row shape the chain-agnostic test-indexer operations exchange. A
|
|
1541
|
+
* per-chain entity's row is only identified together with its chain, so the
|
|
1542
|
+
* chain id travels alongside the entity fields. */
|
|
1543
|
+
type TestIndexerEntityRow<
|
|
1544
|
+
Config extends IndexerConfigTypes,
|
|
1545
|
+
Name,
|
|
1546
|
+
Entity
|
|
1547
|
+
> = Name extends PerChainEntityNames<Config>
|
|
1548
|
+
? Entity & { readonly chainId: number }
|
|
1549
|
+
: Entity;
|
|
1550
|
+
|
|
1532
1551
|
/** Entity operations available on test indexer for direct entity manipulation. */
|
|
1533
1552
|
type TestIndexerEntityOperations<Entity> = {
|
|
1534
1553
|
/** Get an entity by ID. Returns undefined if not found. */
|
|
@@ -1537,6 +1556,10 @@ type TestIndexerEntityOperations<Entity> = {
|
|
|
1537
1556
|
readonly getOrThrow: (id: EntityId<Entity>, message?: string) => Promise<Entity>;
|
|
1538
1557
|
/** Get all entities. */
|
|
1539
1558
|
readonly getAll: () => Promise<Entity[]>;
|
|
1559
|
+
/** Get the entities matching a filter. For a per-chain entity the filter
|
|
1560
|
+
* accepts `chainId`, which is how an id present on several chains is
|
|
1561
|
+
* narrowed to one. */
|
|
1562
|
+
readonly getWhere: (filter: GetWhereFilter<Entity>) => Promise<Entity[]>;
|
|
1540
1563
|
/** Set (create or update) an entity. */
|
|
1541
1564
|
readonly set: (entity: Entity) => void;
|
|
1542
1565
|
};
|
|
@@ -1711,7 +1734,7 @@ export type TestIndexerFromConfig<Config extends IndexerConfigTypes = GlobalConf
|
|
|
1711
1734
|
} & SingleEcosystemTestChains<Config> & {
|
|
1712
1735
|
/** Entity operations for direct manipulation outside of handlers. */
|
|
1713
1736
|
readonly [K in keyof ConfigEntities<Config>]: TestIndexerEntityOperations<
|
|
1714
|
-
ConfigEntities<Config>[K]
|
|
1737
|
+
TestIndexerEntityRow<Config, K, ConfigEntities<Config>[K]>
|
|
1715
1738
|
>;
|
|
1716
1739
|
};
|
|
1717
1740
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envio",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
|
|
6
6
|
"bin": "./bin.mjs",
|
|
@@ -69,10 +69,10 @@
|
|
|
69
69
|
"tsx": "4.21.0"
|
|
70
70
|
},
|
|
71
71
|
"optionalDependencies": {
|
|
72
|
-
"envio-linux-x64": "3.
|
|
73
|
-
"envio-linux-x64-musl": "3.
|
|
74
|
-
"envio-linux-arm64": "3.
|
|
75
|
-
"envio-darwin-x64": "3.
|
|
76
|
-
"envio-darwin-arm64": "3.
|
|
72
|
+
"envio-linux-x64": "3.6.1",
|
|
73
|
+
"envio-linux-x64-musl": "3.6.1",
|
|
74
|
+
"envio-linux-arm64": "3.6.1",
|
|
75
|
+
"envio-darwin-x64": "3.6.1",
|
|
76
|
+
"envio-darwin-arm64": "3.6.1"
|
|
77
77
|
}
|
|
78
78
|
}
|
package/src/ChainState.res
CHANGED
|
@@ -31,6 +31,10 @@ type t = {
|
|
|
31
31
|
// then smoothed with an EMA on every batch (see applyBatchProgress). None
|
|
32
32
|
// until the chain has processed at least one event.
|
|
33
33
|
mutable chainDensity: option<float>,
|
|
34
|
+
// In-memory tables for the entities whose rows belong to a single chain.
|
|
35
|
+
// Empty in the default cross-chain mode, where every entity's table lives on
|
|
36
|
+
// the indexer instead.
|
|
37
|
+
mutable entities: EntityTables.t,
|
|
34
38
|
mutable reorgDetection: ReorgDetection.t,
|
|
35
39
|
mutable safeCheckpointTracking: option<SafeCheckpointTracking.t>,
|
|
36
40
|
// Holds this chain's transactions (kept in Rust) keyed by (blockNumber,
|
|
@@ -96,11 +100,13 @@ let make = (
|
|
|
96
100
|
~chainDensity=None,
|
|
97
101
|
~blockStore=BlockStore.make(~ecosystem=Ecosystem.Evm, ~shouldChecksum=false),
|
|
98
102
|
~reorgThresholdReadyTolerance=100,
|
|
103
|
+
~perChainEntities: array<Internal.entityConfig>=[],
|
|
99
104
|
~logger: Pino.t,
|
|
100
105
|
): t => {
|
|
101
106
|
validateOnEventRegistrations(~chainId=chainConfig.id, onEventRegistrations)
|
|
102
107
|
{
|
|
103
108
|
logger,
|
|
109
|
+
entities: EntityTables.make(perChainEntities),
|
|
104
110
|
onEventRegistrations,
|
|
105
111
|
fetchState,
|
|
106
112
|
addressStore,
|
|
@@ -318,6 +324,7 @@ let makeInternal = (
|
|
|
318
324
|
~chainReorgCheckpoints,
|
|
319
325
|
),
|
|
320
326
|
~committedProgressBlockNumber=progressBlockNumber,
|
|
327
|
+
~perChainEntities=config.allEntities->EntityTables.perChain,
|
|
321
328
|
~timestampCaughtUpToHeadOrEndblock,
|
|
322
329
|
~numEventsProcessed,
|
|
323
330
|
~transactionStore=TransactionStore.make(
|
|
@@ -408,6 +415,11 @@ let makeFromDbState = (
|
|
|
408
415
|
// --- Read accessors. ---
|
|
409
416
|
|
|
410
417
|
let logger = (cs: t) => cs.logger
|
|
418
|
+
let entities = (cs: t) => cs.entities
|
|
419
|
+
|
|
420
|
+
// Rollback discards every uncommitted change, so this chain's partition is
|
|
421
|
+
// rebuilt from scratch alongside the indexer's cross-chain one.
|
|
422
|
+
let resetEntities = (cs: t, ~perChainEntities) => cs.entities = EntityTables.make(perChainEntities)
|
|
411
423
|
let sourceManager = (cs: t) => cs.sourceManager
|
|
412
424
|
let chainConfig = (cs: t) => cs.chainConfig
|
|
413
425
|
let reorgDetection = (cs: t) => cs.reorgDetection
|
|
@@ -537,10 +549,16 @@ let targetBlock = (cs: t, ~chainTargetItems: float) => {
|
|
|
537
549
|
let bufferBlockNumber = fetchState->FetchState.bufferBlockNumber
|
|
538
550
|
switch cs->effectiveDensity {
|
|
539
551
|
| Some(density) if density > 0. =>
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
552
|
+
// Decided by comparison so no unbounded value is ever converted to int:
|
|
553
|
+
// at low densities chainTargetItems /. density exceeds the int range, and
|
|
554
|
+
// truncating it wraps negative — the target collapses below the frontier
|
|
555
|
+
// and the chain stops querying. The division only runs when its result is
|
|
556
|
+
// provably below the ceiling-bounded range.
|
|
557
|
+
if density *. (fetchCeiling - bufferBlockNumber)->Int.toFloat <= chainTargetItems {
|
|
558
|
+
fetchCeiling
|
|
559
|
+
} else {
|
|
560
|
+
bufferBlockNumber + Math.ceil(chainTargetItems /. density)->Float.toInt
|
|
561
|
+
}
|
|
544
562
|
| _ => Pervasives.min(bufferBlockNumber + coldTargetRange, fetchCeiling)
|
|
545
563
|
}
|
|
546
564
|
}
|
package/src/ChainState.res.mjs
CHANGED
|
@@ -13,6 +13,7 @@ import * as BlockStore from "./sources/BlockStore.res.mjs";
|
|
|
13
13
|
import * as FetchState from "./FetchState.res.mjs";
|
|
14
14
|
import * as Stdlib_Null from "@rescript/runtime/lib/es6/Stdlib_Null.js";
|
|
15
15
|
import * as AddressStore from "./sources/AddressStore.res.mjs";
|
|
16
|
+
import * as EntityTables from "./EntityTables.res.mjs";
|
|
16
17
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
17
18
|
import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
18
19
|
import * as SourceManager from "./sources/SourceManager.res.mjs";
|
|
@@ -49,7 +50,7 @@ function validateOnEventRegistrations(chainId, registrations) {
|
|
|
49
50
|
});
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
function make(chainConfig, fetchState, onEventRegistrationsOpt, addressStore, sourceManager, reorgDetection, committedProgressBlockNumber, safeCheckpointTrackingOpt, numEventsProcessedOpt, timestampCaughtUpToHeadOrEndblockOpt, isProgressAtHeadOpt, transactionStoreOpt, chainDensityOpt, blockStoreOpt, reorgThresholdReadyToleranceOpt, logger) {
|
|
53
|
+
function make(chainConfig, fetchState, onEventRegistrationsOpt, addressStore, sourceManager, reorgDetection, committedProgressBlockNumber, safeCheckpointTrackingOpt, numEventsProcessedOpt, timestampCaughtUpToHeadOrEndblockOpt, isProgressAtHeadOpt, transactionStoreOpt, chainDensityOpt, blockStoreOpt, reorgThresholdReadyToleranceOpt, perChainEntitiesOpt, logger) {
|
|
53
54
|
let onEventRegistrations = onEventRegistrationsOpt !== undefined ? onEventRegistrationsOpt : [];
|
|
54
55
|
let safeCheckpointTracking = safeCheckpointTrackingOpt !== undefined ? Primitive_option.valFromOption(safeCheckpointTrackingOpt) : undefined;
|
|
55
56
|
let numEventsProcessed = numEventsProcessedOpt !== undefined ? numEventsProcessedOpt : 0;
|
|
@@ -59,6 +60,7 @@ function make(chainConfig, fetchState, onEventRegistrationsOpt, addressStore, so
|
|
|
59
60
|
let chainDensity = chainDensityOpt !== undefined ? Primitive_option.valFromOption(chainDensityOpt) : undefined;
|
|
60
61
|
let blockStore = blockStoreOpt !== undefined ? Primitive_option.valFromOption(blockStoreOpt) : BlockStore.make("evm", false);
|
|
61
62
|
let reorgThresholdReadyTolerance = reorgThresholdReadyToleranceOpt !== undefined ? reorgThresholdReadyToleranceOpt : 100;
|
|
63
|
+
let perChainEntities = perChainEntitiesOpt !== undefined ? perChainEntitiesOpt : [];
|
|
62
64
|
validateOnEventRegistrations(chainConfig.id, onEventRegistrations);
|
|
63
65
|
return {
|
|
64
66
|
logger: logger,
|
|
@@ -74,6 +76,7 @@ function make(chainConfig, fetchState, onEventRegistrationsOpt, addressStore, so
|
|
|
74
76
|
numEventsProcessed: numEventsProcessed,
|
|
75
77
|
pendingBudget: 0,
|
|
76
78
|
chainDensity: chainDensity,
|
|
79
|
+
entities: EntityTables.make(perChainEntities),
|
|
77
80
|
reorgDetection: reorgDetection,
|
|
78
81
|
safeCheckpointTracking: safeCheckpointTracking,
|
|
79
82
|
transactionStore: transactionStore,
|
|
@@ -186,7 +189,7 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
|
|
|
186
189
|
}
|
|
187
190
|
let firstEventBlock$1 = fetchState.firstEventBlock;
|
|
188
191
|
let chainDensity = firstEventBlock$1 !== undefined && progressBlockNumber > firstEventBlock$1 && numEventsProcessed > 0 ? numEventsProcessed / (progressBlockNumber - firstEventBlock$1 | 0) : undefined;
|
|
189
|
-
return make(chainConfig, fetchState, onEventRegistrations, addressStore, SourceManager.make(sources$1, isRealtime, undefined, undefined, undefined, reducedPollingInterval, undefined, undefined), ReorgDetection.make(chainReorgCheckpoints, maxReorgDepth, config.shouldRollbackOnReorg), progressBlockNumber, Primitive_option.some(SafeCheckpointTracking.make(maxReorgDepth, config.shouldRollbackOnReorg, chainReorgCheckpoints)), numEventsProcessed, Primitive_option.some(timestampCaughtUpToHeadOrEndblock), undefined, Primitive_option.some(TransactionStore.make(config.ecosystem.name, !lowercaseAddresses)), Primitive_option.some(chainDensity), Primitive_option.some(BlockStore.make(config.ecosystem.name, !lowercaseAddresses)), config.reorgThresholdReadyTolerance, logger);
|
|
192
|
+
return make(chainConfig, fetchState, onEventRegistrations, addressStore, SourceManager.make(sources$1, isRealtime, undefined, undefined, undefined, reducedPollingInterval, undefined, undefined), ReorgDetection.make(chainReorgCheckpoints, maxReorgDepth, config.shouldRollbackOnReorg), progressBlockNumber, Primitive_option.some(SafeCheckpointTracking.make(maxReorgDepth, config.shouldRollbackOnReorg, chainReorgCheckpoints)), numEventsProcessed, Primitive_option.some(timestampCaughtUpToHeadOrEndblock), undefined, Primitive_option.some(TransactionStore.make(config.ecosystem.name, !lowercaseAddresses)), Primitive_option.some(chainDensity), Primitive_option.some(BlockStore.make(config.ecosystem.name, !lowercaseAddresses)), config.reorgThresholdReadyTolerance, EntityTables.perChain(config.allEntities), logger);
|
|
190
193
|
}
|
|
191
194
|
|
|
192
195
|
function makeFromConfig(chainConfig, config, registrationsByChainId, knownHeight) {
|
|
@@ -209,6 +212,14 @@ function logger(cs) {
|
|
|
209
212
|
return cs.logger;
|
|
210
213
|
}
|
|
211
214
|
|
|
215
|
+
function entities(cs) {
|
|
216
|
+
return cs.entities;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function resetEntities(cs, perChainEntities) {
|
|
220
|
+
cs.entities = EntityTables.make(perChainEntities);
|
|
221
|
+
}
|
|
222
|
+
|
|
212
223
|
function sourceManager(cs) {
|
|
213
224
|
return cs.sourceManager;
|
|
214
225
|
}
|
|
@@ -357,7 +368,11 @@ function targetBlock(cs, chainTargetItems) {
|
|
|
357
368
|
let bufferBlockNumber = FetchState.bufferBlockNumber(fetchState);
|
|
358
369
|
let density = effectiveDensity(cs);
|
|
359
370
|
if (density !== undefined && density > 0) {
|
|
360
|
-
|
|
371
|
+
if (density * (fetchCeiling$1 - bufferBlockNumber | 0) <= chainTargetItems) {
|
|
372
|
+
return fetchCeiling$1;
|
|
373
|
+
} else {
|
|
374
|
+
return bufferBlockNumber + (Math.ceil(chainTargetItems / density) | 0) | 0;
|
|
375
|
+
}
|
|
361
376
|
} else {
|
|
362
377
|
return Primitive_int.min(bufferBlockNumber + 20000 | 0, fetchCeiling$1);
|
|
363
378
|
}
|
|
@@ -841,6 +856,8 @@ export {
|
|
|
841
856
|
makeFromConfig,
|
|
842
857
|
makeFromDbState,
|
|
843
858
|
logger,
|
|
859
|
+
entities,
|
|
860
|
+
resetEntities,
|
|
844
861
|
sourceManager,
|
|
845
862
|
chainConfig,
|
|
846
863
|
reorgDetection,
|
package/src/ChainState.resi
CHANGED
|
@@ -21,6 +21,7 @@ let make: (
|
|
|
21
21
|
~chainDensity: option<float>=?,
|
|
22
22
|
~blockStore: BlockStore.t=?,
|
|
23
23
|
~reorgThresholdReadyTolerance: int=?,
|
|
24
|
+
~perChainEntities: array<Internal.entityConfig>=?,
|
|
24
25
|
~logger: Pino.t,
|
|
25
26
|
) => t
|
|
26
27
|
|
|
@@ -44,6 +45,8 @@ let makeFromDbState: (
|
|
|
44
45
|
|
|
45
46
|
// Accessors.
|
|
46
47
|
let logger: t => Pino.t
|
|
48
|
+
let entities: t => EntityTables.t
|
|
49
|
+
let resetEntities: (t, ~perChainEntities: array<Internal.entityConfig>) => unit
|
|
47
50
|
let sourceManager: t => SourceManager.t
|
|
48
51
|
let chainConfig: t => Config.chain
|
|
49
52
|
let reorgDetection: t => ReorgDetection.t
|
package/src/Config.res
CHANGED
|
@@ -59,11 +59,26 @@ type sourceSync = {
|
|
|
59
59
|
pollingInterval: int,
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
// How a backend spells column names, mirroring `column_name_format` in
|
|
63
|
+
// config.yaml. Only the internal columns the runtime appends need it — user
|
|
64
|
+
// field names arrive pre-resolved from the CLI.
|
|
65
|
+
type columnNameFormat = | @as("original") Original | @as("snake_case") SnakeCase
|
|
66
|
+
|
|
62
67
|
type storage = {
|
|
63
68
|
postgres: bool,
|
|
64
69
|
clickhouse: bool,
|
|
70
|
+
postgresColumnNameFormat: columnNameFormat,
|
|
71
|
+
clickhouseColumnNameFormat: columnNameFormat,
|
|
65
72
|
}
|
|
66
73
|
|
|
74
|
+
let chainIdFieldName = "chainId"
|
|
75
|
+
|
|
76
|
+
let chainIdColumnName = format =>
|
|
77
|
+
switch format {
|
|
78
|
+
| Original => chainIdFieldName
|
|
79
|
+
| SnakeCase => "chain_id"
|
|
80
|
+
}
|
|
81
|
+
|
|
67
82
|
type contractHandler = {
|
|
68
83
|
name: string,
|
|
69
84
|
handler: option<string>,
|
|
@@ -76,6 +91,10 @@ type t = {
|
|
|
76
91
|
contractHandlers: array<contractHandler>,
|
|
77
92
|
shouldRollbackOnReorg: bool,
|
|
78
93
|
shouldSaveFullHistory: bool,
|
|
94
|
+
// False when `disable_default_cross_chain: true` in config.yaml. Entities
|
|
95
|
+
// carry their own resolved `crossChain`; this only decides the default for
|
|
96
|
+
// effects that don't state one.
|
|
97
|
+
defaultCrossChain: bool,
|
|
79
98
|
storage: storage,
|
|
80
99
|
// Widest scalar the internal chain-id columns need, resolved by the CLI from
|
|
81
100
|
// the maximum active chain id. Older configs predate the field, and every id
|
|
@@ -161,6 +180,9 @@ module EnvioAddresses = {
|
|
|
161
180
|
// always required to have Postgres enabled (Storage::resolve forbids
|
|
162
181
|
// a Postgres-disabled global), so this is safe regardless of mode.
|
|
163
182
|
storage: {postgres: true, clickhouse: false},
|
|
183
|
+
// The table already keys rows by chain through the composite `id`, so the
|
|
184
|
+
// per-chain mode must not append a second chain-id column to it.
|
|
185
|
+
crossChain: true,
|
|
164
186
|
}->Internal.fromGenericEntityConfig
|
|
165
187
|
}
|
|
166
188
|
|
|
@@ -353,6 +375,7 @@ let entityStorageSchema = S.schema(s =>
|
|
|
353
375
|
let entityJsonSchema = S.schema(s =>
|
|
354
376
|
{
|
|
355
377
|
"name": s.matches(S.string),
|
|
378
|
+
"crossChain": s.matches(S.option(S.bool)),
|
|
356
379
|
"storage": s.matches(S.option(entityStorageSchema)),
|
|
357
380
|
"properties": s.matches(S.array(propertySchema)),
|
|
358
381
|
"derivedFields": s.matches(S.option(S.array(derivedFieldSchema))),
|
|
@@ -424,13 +447,30 @@ let parseEnumsFromJson = (enumsJson: dict<array<string>>): array<Table.enumConfi
|
|
|
424
447
|
)
|
|
425
448
|
}
|
|
426
449
|
|
|
450
|
+
// The chain-id column appended to a per-chain entity's table. It completes the
|
|
451
|
+
// primary key so the same id can exist independently on every chain, and it's
|
|
452
|
+
// spelled per backend because the two can be configured with different
|
|
453
|
+
// `column_name_format`s.
|
|
454
|
+
let makeChainIdField = (~globalStorage: storage) =>
|
|
455
|
+
Table.mkField(
|
|
456
|
+
chainIdFieldName,
|
|
457
|
+
ChainId,
|
|
458
|
+
~fieldSchema=ChainId.schema,
|
|
459
|
+
~isPrimaryKey=true,
|
|
460
|
+
~isChainId=true,
|
|
461
|
+
~postgresDbName=globalStorage.postgresColumnNameFormat->chainIdColumnName,
|
|
462
|
+
~clickhouseDbName=globalStorage.clickhouseColumnNameFormat->chainIdColumnName,
|
|
463
|
+
)
|
|
464
|
+
|
|
427
465
|
let parseEntitiesFromJson = (
|
|
428
466
|
entitiesJson: array<'entityJson>,
|
|
429
467
|
~enumConfigsByName: dict<Table.enumConfig<Table.enum>>,
|
|
430
468
|
~globalStorage: storage,
|
|
469
|
+
~defaultCrossChain: bool,
|
|
431
470
|
): array<Internal.entityConfig> => {
|
|
432
471
|
entitiesJson->Array.mapWithIndex((entityJson, index) => {
|
|
433
472
|
let entityName = entityJson["name"]
|
|
473
|
+
let crossChain = entityJson["crossChain"]->Option.getOr(defaultCrossChain)
|
|
434
474
|
|
|
435
475
|
let fields: array<Table.fieldOrDerived> = entityJson["properties"]->Array.map(prop => {
|
|
436
476
|
let (fieldType, fieldSchema, isNullable, isArray, isIndex) = getFieldTypeAndSchema(
|
|
@@ -478,7 +518,10 @@ let parseEntitiesFromJson = (
|
|
|
478
518
|
|
|
479
519
|
let table = Table.mkTable(
|
|
480
520
|
entityName,
|
|
481
|
-
~fields=Array.
|
|
521
|
+
~fields=Array.concatMany(
|
|
522
|
+
fields,
|
|
523
|
+
[crossChain ? [] : [makeChainIdField(~globalStorage)], derivedFields],
|
|
524
|
+
),
|
|
482
525
|
~compositeIndexes,
|
|
483
526
|
~description=?entityJson["description"],
|
|
484
527
|
)
|
|
@@ -536,14 +579,19 @@ let parseEntitiesFromJson = (
|
|
|
536
579
|
schema: schema->(Utils.magic: S.t<dict<unknown>> => S.t<Internal.entity>),
|
|
537
580
|
table,
|
|
538
581
|
storage,
|
|
582
|
+
crossChain,
|
|
539
583
|
}->Internal.fromGenericEntityConfig
|
|
540
584
|
})
|
|
541
585
|
}
|
|
542
586
|
|
|
587
|
+
let columnNameFormatSchema = S.enum([Original, SnakeCase])
|
|
588
|
+
|
|
543
589
|
let publicConfigStorageSchema = S.schema(s =>
|
|
544
590
|
{
|
|
545
591
|
"postgres": s.matches(S.bool),
|
|
546
592
|
"clickhouse": s.matches(S.option(S.bool)),
|
|
593
|
+
"postgresColumnNameFormat": s.matches(S.option(columnNameFormatSchema)),
|
|
594
|
+
"clickhouseColumnNameFormat": s.matches(S.option(columnNameFormatSchema)),
|
|
547
595
|
}
|
|
548
596
|
)
|
|
549
597
|
|
|
@@ -558,6 +606,7 @@ let publicConfigSchema = S.schema(s =>
|
|
|
558
606
|
"saveFullHistory": s.matches(S.option(S.bool)),
|
|
559
607
|
"rawEvents": s.matches(S.option(S.bool)),
|
|
560
608
|
"chainIdMode": s.matches(S.option(ChainId.modeSchema)),
|
|
609
|
+
"defaultCrossChain": s.matches(S.option(S.bool)),
|
|
561
610
|
"storage": s.matches(publicConfigStorageSchema),
|
|
562
611
|
"evm": s.matches(S.option(publicConfigEvmSchema)),
|
|
563
612
|
"fuel": s.matches(S.option(publicConfigEcosystemSchema)),
|
|
@@ -995,12 +1044,20 @@ let fromPublic = (publicConfigJson: JSON.t) => {
|
|
|
995
1044
|
let globalStorage: storage = {
|
|
996
1045
|
postgres: publicConfig["storage"]["postgres"],
|
|
997
1046
|
clickhouse: publicConfig["storage"]["clickhouse"]->Option.getOr(false),
|
|
1047
|
+
postgresColumnNameFormat: publicConfig["storage"]["postgresColumnNameFormat"]->Option.getOr(
|
|
1048
|
+
Original,
|
|
1049
|
+
),
|
|
1050
|
+
clickhouseColumnNameFormat: publicConfig["storage"]["clickhouseColumnNameFormat"]->Option.getOr(
|
|
1051
|
+
Original,
|
|
1052
|
+
),
|
|
998
1053
|
}
|
|
999
1054
|
|
|
1055
|
+
let defaultCrossChain = publicConfig["defaultCrossChain"]->Option.getOr(true)
|
|
1056
|
+
|
|
1000
1057
|
let userEntities =
|
|
1001
1058
|
publicConfig["entities"]
|
|
1002
1059
|
->Option.getOr([])
|
|
1003
|
-
->parseEntitiesFromJson(~enumConfigsByName, ~globalStorage)
|
|
1060
|
+
->parseEntitiesFromJson(~enumConfigsByName, ~globalStorage, ~defaultCrossChain)
|
|
1004
1061
|
|
|
1005
1062
|
let allEntities = userEntities->Array.concat([EnvioAddresses.entityConfig])
|
|
1006
1063
|
|
|
@@ -1036,6 +1093,7 @@ let fromPublic = (publicConfigJson: JSON.t) => {
|
|
|
1036
1093
|
contractHandlers,
|
|
1037
1094
|
shouldRollbackOnReorg: publicConfig["rollbackOnReorg"]->Option.getOr(true),
|
|
1038
1095
|
shouldSaveFullHistory: publicConfig["saveFullHistory"]->Option.getOr(false),
|
|
1096
|
+
defaultCrossChain,
|
|
1039
1097
|
storage: globalStorage,
|
|
1040
1098
|
chainIdMode: publicConfig["chainIdMode"]->Option.getOr(Int32),
|
|
1041
1099
|
chainMap,
|
package/src/Config.res.mjs
CHANGED
|
@@ -22,6 +22,16 @@ import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
|
22
22
|
import * as EventConfigBuilder from "./EventConfigBuilder.res.mjs";
|
|
23
23
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
24
24
|
|
|
25
|
+
let chainIdFieldName = "chainId";
|
|
26
|
+
|
|
27
|
+
function chainIdColumnName(format) {
|
|
28
|
+
if (format === "original") {
|
|
29
|
+
return chainIdFieldName;
|
|
30
|
+
} else {
|
|
31
|
+
return "chain_id";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
25
35
|
let name = "envio_addresses";
|
|
26
36
|
|
|
27
37
|
function makeId(chainId, address) {
|
|
@@ -42,11 +52,11 @@ let schema = S$RescriptSchema.schema(s => ({
|
|
|
42
52
|
}));
|
|
43
53
|
|
|
44
54
|
let table = Table.mkTable(name, undefined, [
|
|
45
|
-
Table.mkField("id", "String", S$RescriptSchema.string, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined),
|
|
46
|
-
Table.mkField("chain_id", "ChainId", ChainId.schema, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
47
|
-
Table.mkField("registration_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
48
|
-
Table.mkField("registration_log_index", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
49
|
-
Table.mkField("contract_name", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
55
|
+
Table.mkField("id", "String", S$RescriptSchema.string, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
56
|
+
Table.mkField("chain_id", "ChainId", ChainId.schema, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
57
|
+
Table.mkField("registration_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
58
|
+
Table.mkField("registration_log_index", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
59
|
+
Table.mkField("contract_name", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
50
60
|
], undefined);
|
|
51
61
|
|
|
52
62
|
let entityConfig_storage = {
|
|
@@ -59,7 +69,8 @@ let entityConfig = {
|
|
|
59
69
|
index: -1,
|
|
60
70
|
schema: schema,
|
|
61
71
|
table: table,
|
|
62
|
-
storage: entityConfig_storage
|
|
72
|
+
storage: entityConfig_storage,
|
|
73
|
+
crossChain: true
|
|
63
74
|
};
|
|
64
75
|
|
|
65
76
|
let EnvioAddresses = {
|
|
@@ -217,6 +228,7 @@ let entityStorageSchema = S$RescriptSchema.schema(s => ({
|
|
|
217
228
|
|
|
218
229
|
let entityJsonSchema = S$RescriptSchema.schema(s => ({
|
|
219
230
|
name: s.m(S$RescriptSchema.string),
|
|
231
|
+
crossChain: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
|
|
220
232
|
storage: s.m(S$RescriptSchema.option(entityStorageSchema)),
|
|
221
233
|
properties: s.m(S$RescriptSchema.array(propertySchema)),
|
|
222
234
|
derivedFields: s.m(S$RescriptSchema.option(S$RescriptSchema.array(derivedFieldSchema))),
|
|
@@ -324,19 +336,24 @@ function parseEnumsFromJson(enumsJson) {
|
|
|
324
336
|
return Object.entries(enumsJson).map(param => Table.makeEnumConfig(param[0], param[1]));
|
|
325
337
|
}
|
|
326
338
|
|
|
327
|
-
function
|
|
339
|
+
function makeChainIdField(globalStorage) {
|
|
340
|
+
return Table.mkField(chainIdFieldName, "ChainId", ChainId.schema, undefined, undefined, undefined, true, undefined, true, undefined, undefined, chainIdColumnName(globalStorage.postgresColumnNameFormat), chainIdColumnName(globalStorage.clickhouseColumnNameFormat));
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function parseEntitiesFromJson(entitiesJson, enumConfigsByName, globalStorage, defaultCrossChain) {
|
|
328
344
|
return entitiesJson.map((entityJson, index) => {
|
|
329
345
|
let entityName = entityJson.name;
|
|
346
|
+
let crossChain = Stdlib_Option.getOr(entityJson.crossChain, defaultCrossChain);
|
|
330
347
|
let fields = entityJson.properties.map(prop => {
|
|
331
348
|
let match = getFieldTypeAndSchema(prop, enumConfigsByName);
|
|
332
|
-
return Table.mkField(prop.name, match[0], match[1], undefined, match[3], match[2], prop.name === "id", match[4], prop.linkedEntity, prop.description, prop.postgresDbName, prop.clickhouseDbName);
|
|
349
|
+
return Table.mkField(prop.name, match[0], match[1], undefined, match[3], match[2], prop.name === "id", match[4], undefined, prop.linkedEntity, prop.description, prop.postgresDbName, prop.clickhouseDbName);
|
|
333
350
|
});
|
|
334
351
|
let derivedFields = Stdlib_Option.getOr(entityJson.derivedFields, []).map(df => Table.mkDerivedFromField(df.fieldName, df.derivedFromEntity, df.derivedFromField, df.description));
|
|
335
352
|
let compositeIndexes = Stdlib_Option.getOr(entityJson.compositeIndices, []).map(ci => ci.map(f => ({
|
|
336
353
|
fieldName: f.fieldName,
|
|
337
354
|
direction: f.direction === "Asc" ? "Asc" : "Desc"
|
|
338
355
|
})));
|
|
339
|
-
let table = Table.mkTable(entityName, compositeIndexes, fields.concat(derivedFields), entityJson.description);
|
|
356
|
+
let table = Table.mkTable(entityName, compositeIndexes, fields.concat(crossChain ? [] : [makeChainIdField(globalStorage)], derivedFields), entityJson.description);
|
|
340
357
|
let getApiFieldName = prop => {
|
|
341
358
|
let match = prop.linkedEntity;
|
|
342
359
|
if (match !== undefined) {
|
|
@@ -382,14 +399,22 @@ function parseEntitiesFromJson(entitiesJson, enumConfigsByName, globalStorage) {
|
|
|
382
399
|
index: index,
|
|
383
400
|
schema: schema,
|
|
384
401
|
table: table,
|
|
385
|
-
storage: storage
|
|
402
|
+
storage: storage,
|
|
403
|
+
crossChain: crossChain
|
|
386
404
|
};
|
|
387
405
|
});
|
|
388
406
|
}
|
|
389
407
|
|
|
408
|
+
let columnNameFormatSchema = S$RescriptSchema.$$enum([
|
|
409
|
+
"original",
|
|
410
|
+
"snake_case"
|
|
411
|
+
]);
|
|
412
|
+
|
|
390
413
|
let publicConfigStorageSchema = S$RescriptSchema.schema(s => ({
|
|
391
414
|
postgres: s.m(S$RescriptSchema.bool),
|
|
392
|
-
clickhouse: s.m(S$RescriptSchema.option(S$RescriptSchema.bool))
|
|
415
|
+
clickhouse: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
|
|
416
|
+
postgresColumnNameFormat: s.m(S$RescriptSchema.option(columnNameFormatSchema)),
|
|
417
|
+
clickhouseColumnNameFormat: s.m(S$RescriptSchema.option(columnNameFormatSchema))
|
|
393
418
|
}));
|
|
394
419
|
|
|
395
420
|
let publicConfigSchema = S$RescriptSchema.schema(s => ({
|
|
@@ -402,6 +427,7 @@ let publicConfigSchema = S$RescriptSchema.schema(s => ({
|
|
|
402
427
|
saveFullHistory: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
|
|
403
428
|
rawEvents: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
|
|
404
429
|
chainIdMode: s.m(S$RescriptSchema.option(ChainId.modeSchema)),
|
|
430
|
+
defaultCrossChain: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
|
|
405
431
|
storage: s.m(publicConfigStorageSchema),
|
|
406
432
|
evm: s.m(S$RescriptSchema.option(publicConfigEvmSchema)),
|
|
407
433
|
fuel: s.m(S$RescriptSchema.option(publicConfigEcosystemSchema)),
|
|
@@ -689,11 +715,16 @@ function fromPublic(publicConfigJson) {
|
|
|
689
715
|
]));
|
|
690
716
|
let globalStorage_postgres = publicConfig.storage.postgres;
|
|
691
717
|
let globalStorage_clickhouse = Stdlib_Option.getOr(publicConfig.storage.clickhouse, false);
|
|
718
|
+
let globalStorage_postgresColumnNameFormat = Stdlib_Option.getOr(publicConfig.storage.postgresColumnNameFormat, "original");
|
|
719
|
+
let globalStorage_clickhouseColumnNameFormat = Stdlib_Option.getOr(publicConfig.storage.clickhouseColumnNameFormat, "original");
|
|
692
720
|
let globalStorage = {
|
|
693
721
|
postgres: globalStorage_postgres,
|
|
694
|
-
clickhouse: globalStorage_clickhouse
|
|
722
|
+
clickhouse: globalStorage_clickhouse,
|
|
723
|
+
postgresColumnNameFormat: globalStorage_postgresColumnNameFormat,
|
|
724
|
+
clickhouseColumnNameFormat: globalStorage_clickhouseColumnNameFormat
|
|
695
725
|
};
|
|
696
|
-
let
|
|
726
|
+
let defaultCrossChain = Stdlib_Option.getOr(publicConfig.defaultCrossChain, true);
|
|
727
|
+
let userEntities = parseEntitiesFromJson(Stdlib_Option.getOr(publicConfig.entities, []), enumConfigsByName, globalStorage, defaultCrossChain);
|
|
697
728
|
let allEntities = userEntities.concat([entityConfig]);
|
|
698
729
|
let userEntitiesByName = Object.fromEntries(userEntities.map(entityConfig => [
|
|
699
730
|
Utils.$$String.capitalize(entityConfig.name),
|
|
@@ -710,6 +741,7 @@ function fromPublic(publicConfigJson) {
|
|
|
710
741
|
contractHandlers: contractHandlers,
|
|
711
742
|
shouldRollbackOnReorg: Stdlib_Option.getOr(publicConfig.rollbackOnReorg, true),
|
|
712
743
|
shouldSaveFullHistory: Stdlib_Option.getOr(publicConfig.saveFullHistory, false),
|
|
744
|
+
defaultCrossChain: defaultCrossChain,
|
|
713
745
|
storage: globalStorage,
|
|
714
746
|
chainIdMode: Stdlib_Option.getOr(publicConfig.chainIdMode, "int32"),
|
|
715
747
|
chainMap: chainMap,
|
|
@@ -1049,6 +1081,8 @@ function getPgUserEntities(config) {
|
|
|
1049
1081
|
}
|
|
1050
1082
|
|
|
1051
1083
|
export {
|
|
1084
|
+
chainIdFieldName,
|
|
1085
|
+
chainIdColumnName,
|
|
1052
1086
|
EnvioAddresses,
|
|
1053
1087
|
rpcSourceForSchema,
|
|
1054
1088
|
rpcConfigSchema,
|
|
@@ -1069,7 +1103,9 @@ export {
|
|
|
1069
1103
|
entityJsonSchema,
|
|
1070
1104
|
getFieldTypeAndSchema,
|
|
1071
1105
|
parseEnumsFromJson,
|
|
1106
|
+
makeChainIdField,
|
|
1072
1107
|
parseEntitiesFromJson,
|
|
1108
|
+
columnNameFormatSchema,
|
|
1073
1109
|
publicConfigStorageSchema,
|
|
1074
1110
|
publicConfigSchema,
|
|
1075
1111
|
fromPublic,
|
package/src/EffectState.res
CHANGED
|
@@ -131,7 +131,7 @@ let commitCacheCount = (inMemTable: effectCacheInMemTable, ~count) => {
|
|
|
131
131
|
|
|
132
132
|
let statsToMetrics = (stats: effectStats): Metrics.effectMetrics => {
|
|
133
133
|
Metrics.effect: stats.effectName,
|
|
134
|
-
scope: stats.scope->Internal.
|
|
134
|
+
scope: stats.scope->Internal.chainScopeToString,
|
|
135
135
|
callSeconds: stats.callSeconds,
|
|
136
136
|
callSecondsTotal: stats.callSecondsTotal,
|
|
137
137
|
callCount: stats.callCount,
|
|
@@ -152,7 +152,7 @@ let toMetrics = (self: t): array<Metrics.effectMetrics> => {
|
|
|
152
152
|
metrics
|
|
153
153
|
->Array.push({
|
|
154
154
|
Metrics.effect: effectName,
|
|
155
|
-
scope: scope->Internal.
|
|
155
|
+
scope: scope->Internal.chainScopeToString,
|
|
156
156
|
callSeconds: 0.,
|
|
157
157
|
callSecondsTotal: 0.,
|
|
158
158
|
callCount: 0.,
|
package/src/EffectState.res.mjs
CHANGED
|
@@ -68,7 +68,7 @@ function toMetrics(self) {
|
|
|
68
68
|
let stats = t.stats;
|
|
69
69
|
return {
|
|
70
70
|
effect: stats.effectName,
|
|
71
|
-
scope: Internal.
|
|
71
|
+
scope: Internal.chainScopeToString(stats.scope),
|
|
72
72
|
callSeconds: stats.callSeconds,
|
|
73
73
|
callSecondsTotal: stats.callSecondsTotal,
|
|
74
74
|
callCount: stats.callCount,
|
|
@@ -82,7 +82,7 @@ function toMetrics(self) {
|
|
|
82
82
|
Utils.Dict.forEach(self.unregisteredCacheCounts, param => {
|
|
83
83
|
metrics.push({
|
|
84
84
|
effect: param.effectName,
|
|
85
|
-
scope: Internal.
|
|
85
|
+
scope: Internal.chainScopeToString(param.scope),
|
|
86
86
|
callSeconds: 0,
|
|
87
87
|
callSecondsTotal: 0,
|
|
88
88
|
callCount: 0,
|