envio 3.0.0-rc.1 → 3.0.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/package.json +6 -6
- package/src/Config.res +84 -11
- package/src/Config.res.mjs +81 -4
- package/src/InMemoryTable.res +20 -24
- package/src/InMemoryTable.res.mjs +3 -19
- package/src/Main.res +2 -0
- package/src/Main.res.mjs +2 -2
- package/src/Persistence.res +17 -2
- package/src/Persistence.res.mjs +14 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envio",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
|
|
6
6
|
"bin": "./bin.mjs",
|
|
@@ -71,10 +71,10 @@
|
|
|
71
71
|
"tsx": "4.21.0"
|
|
72
72
|
},
|
|
73
73
|
"optionalDependencies": {
|
|
74
|
-
"envio-linux-x64": "3.0.
|
|
75
|
-
"envio-linux-x64-musl": "3.0.
|
|
76
|
-
"envio-linux-arm64": "3.0.
|
|
77
|
-
"envio-darwin-x64": "3.0.
|
|
78
|
-
"envio-darwin-arm64": "3.0.
|
|
74
|
+
"envio-linux-x64": "3.0.1",
|
|
75
|
+
"envio-linux-x64-musl": "3.0.1",
|
|
76
|
+
"envio-linux-arm64": "3.0.1",
|
|
77
|
+
"envio-darwin-x64": "3.0.1",
|
|
78
|
+
"envio-darwin-arm64": "3.0.1"
|
|
79
79
|
}
|
|
80
80
|
}
|
package/src/Config.res
CHANGED
|
@@ -957,11 +957,18 @@ let rec canonicalJson = (json: JSON.t): JSON.t =>
|
|
|
957
957
|
}
|
|
958
958
|
|
|
959
959
|
// Returns dotted leaf paths (`a.b[i].c`) where `stored` differs from
|
|
960
|
-
// `current
|
|
960
|
+
// `current`, restricted to the highest-priority top-level tier with any
|
|
961
|
+
// diff. Tiers in order: version → name → storage → ecosystem
|
|
962
|
+
// (evm/fuel/svm) → entities → other top-level keys. The first tier
|
|
963
|
+
// containing a diff is the only one rendered; lower tiers are silenced
|
|
964
|
+
// so a single noisy section doesn't bury the actionable change.
|
|
961
965
|
let diffPaths = (~stored: JSON.t, ~current: JSON.t): array<string> => {
|
|
966
|
+
let canonEq = (a: JSON.t, b: JSON.t) =>
|
|
967
|
+
JSON.stringify(canonicalJson(a)) === JSON.stringify(canonicalJson(b))
|
|
968
|
+
|
|
962
969
|
let acc = []
|
|
963
970
|
let rec go = (s: JSON.t, c: JSON.t, prefix: string) => {
|
|
964
|
-
if
|
|
971
|
+
if canonEq(s, c) {
|
|
965
972
|
()
|
|
966
973
|
} else {
|
|
967
974
|
switch (s, c) {
|
|
@@ -987,25 +994,91 @@ let diffPaths = (~stored: JSON.t, ~current: JSON.t): array<string> => {
|
|
|
987
994
|
| (Some(sv), Some(cv)) => go(sv, cv, p)
|
|
988
995
|
}
|
|
989
996
|
}
|
|
990
|
-
| _ =>
|
|
991
|
-
|
|
992
|
-
|
|
997
|
+
| _ => acc->Array.push(prefix === "" ? "<root>" : prefix)->ignore
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
let getTopKey = (j: JSON.t, k: string) =>
|
|
1003
|
+
switch j {
|
|
1004
|
+
| Object(d) => d->Dict.get(k)
|
|
1005
|
+
| _ => None
|
|
1006
|
+
}
|
|
1007
|
+
let topKeyDiffers = (k: string) =>
|
|
1008
|
+
switch (getTopKey(stored, k), getTopKey(current, k)) {
|
|
1009
|
+
| (None, None) => false
|
|
1010
|
+
| (None, _) | (_, None) => true
|
|
1011
|
+
| (Some(s), Some(c)) => !canonEq(s, c)
|
|
1012
|
+
}
|
|
1013
|
+
let runTier = (keys: array<string>) =>
|
|
1014
|
+
keys->Array.forEach(k =>
|
|
1015
|
+
switch (getTopKey(stored, k), getTopKey(current, k)) {
|
|
1016
|
+
| (None, None) => ()
|
|
1017
|
+
| (None, _) | (_, None) => acc->Array.push(k)->ignore
|
|
1018
|
+
| (Some(s), Some(c)) => go(s, c, k)
|
|
1019
|
+
}
|
|
1020
|
+
)
|
|
1021
|
+
|
|
1022
|
+
switch (stored, current) {
|
|
1023
|
+
| (Object(sObj), Object(cObj)) =>
|
|
1024
|
+
let tiers = [["version"], ["name"], ["storage"], ["evm", "fuel", "svm"], ["entities"]]
|
|
1025
|
+
let firstHit = tiers->Array.reduce(None, (acc, tier) =>
|
|
1026
|
+
switch acc {
|
|
1027
|
+
| Some(_) => acc
|
|
1028
|
+
| None =>
|
|
1029
|
+
switch tier->Array.filter(topKeyDiffers) {
|
|
1030
|
+
| [] => None
|
|
1031
|
+
| hits => Some(hits)
|
|
1032
|
+
}
|
|
993
1033
|
}
|
|
1034
|
+
)
|
|
1035
|
+
switch firstHit {
|
|
1036
|
+
| Some(hits) => runTier(hits)
|
|
1037
|
+
| None =>
|
|
1038
|
+
let knownSet = Utils.Set.fromArray(tiers->Belt.Array.concatMany)
|
|
1039
|
+
let extras =
|
|
1040
|
+
Utils.Set.fromArray(Array.concat(sObj->Dict.keysToArray, cObj->Dict.keysToArray))
|
|
1041
|
+
->Utils.Set.toArray
|
|
1042
|
+
->Array.filter(k => !(knownSet->Utils.Set.has(k)))
|
|
1043
|
+
->Array.toSorted(String.compare)
|
|
1044
|
+
->Array.filter(topKeyDiffers)
|
|
1045
|
+
runTier(extras)
|
|
994
1046
|
}
|
|
1047
|
+
| _ => go(stored, current, "")
|
|
995
1048
|
}
|
|
996
|
-
go(stored, current, "")
|
|
997
1049
|
acc
|
|
998
1050
|
}
|
|
999
1051
|
|
|
1000
1052
|
// Throws an `incompatible config` error listing each path in `changedPaths`,
|
|
1001
|
-
// plus the
|
|
1002
|
-
// (
|
|
1003
|
-
//
|
|
1004
|
-
|
|
1053
|
+
// plus the remediation options. `~resetCommand` is rendered as-is for
|
|
1054
|
+
// option 2 (the wipe-and-redo). `~runCommand` controls option 3 (parallel
|
|
1055
|
+
// indexer recipe): when `None`, option 3 is omitted — the migrate flow
|
|
1056
|
+
// uses this because running a second indexer doesn't apply.
|
|
1057
|
+
// `~hasClickhouse` adds the extra env line so users running both
|
|
1058
|
+
// Postgres and Clickhouse get a complete override.
|
|
1059
|
+
let throwIfIncompatible = (
|
|
1060
|
+
changedPaths: array<string>,
|
|
1061
|
+
~resetCommand: string,
|
|
1062
|
+
~runCommand: option<string>,
|
|
1063
|
+
~hasClickhouse: bool,
|
|
1064
|
+
) => {
|
|
1005
1065
|
if changedPaths->Array.length > 0 {
|
|
1006
1066
|
let bullets = changedPaths->Array.map(p => ` - ${p}`)->Array.joinUnsafe("\n")
|
|
1067
|
+
let option1 = "Revert the changes above"
|
|
1068
|
+
let padTo = (s, col) => s ++ " "->String.repeat(Math.Int.max(col - String.length(s), 1))
|
|
1069
|
+
let col = Math.Int.max(String.length(option1), String.length(resetCommand)) + 2
|
|
1070
|
+
let option3 = switch runCommand {
|
|
1071
|
+
| None => ""
|
|
1072
|
+
| Some(cmd) =>
|
|
1073
|
+
let clickhouseLine = hasClickhouse ? " ENVIO_CLICKHOUSE_DATABASE=<new_db> \\\n" : ""
|
|
1074
|
+
`\n 3. Run a second indexer alongside this one — keep both datasets:\n ENVIO_PG_SCHEMA=<new_schema> \\\n${clickhouseLine} ENVIO_INDEXER_PORT=<new_port> \\\n ${cmd}`
|
|
1075
|
+
}
|
|
1007
1076
|
JsError.throwWithMessage(
|
|
1008
|
-
`The following config changes are incompatible with the existing indexer data:\n\n${bullets}\n\nPick one:\n
|
|
1077
|
+
`The following config changes are incompatible with the existing indexer data:\n\n${bullets}\n\nPick one:\n 1. ${option1->padTo(
|
|
1078
|
+
col,
|
|
1079
|
+
)}# resume indexing where it left off\n 2. ${resetCommand->padTo(
|
|
1080
|
+
col,
|
|
1081
|
+
)}# delete all indexed data and start over${option3}`,
|
|
1009
1082
|
)
|
|
1010
1083
|
}
|
|
1011
1084
|
}
|
package/src/Config.res.mjs
CHANGED
|
@@ -780,9 +780,10 @@ function canonicalJson(json) {
|
|
|
780
780
|
}
|
|
781
781
|
|
|
782
782
|
function diffPaths(stored, current) {
|
|
783
|
+
let canonEq = (a, b) => JSON.stringify(canonicalJson(a)) === JSON.stringify(canonicalJson(b));
|
|
783
784
|
let acc = [];
|
|
784
785
|
let go = (s, c, prefix) => {
|
|
785
|
-
if (
|
|
786
|
+
if (canonEq(s, c)) {
|
|
786
787
|
return;
|
|
787
788
|
}
|
|
788
789
|
if (Array.isArray(s)) {
|
|
@@ -830,16 +831,92 @@ function diffPaths(stored, current) {
|
|
|
830
831
|
}
|
|
831
832
|
acc.push(prefix === "" ? "<root>" : prefix);
|
|
832
833
|
};
|
|
833
|
-
|
|
834
|
+
let getTopKey = (j, k) => {
|
|
835
|
+
if (typeof j === "object" && j !== null && !Array.isArray(j)) {
|
|
836
|
+
return j[k];
|
|
837
|
+
}
|
|
838
|
+
};
|
|
839
|
+
let topKeyDiffers = k => {
|
|
840
|
+
let match = getTopKey(stored, k);
|
|
841
|
+
let match$1 = getTopKey(current, k);
|
|
842
|
+
if (match !== undefined) {
|
|
843
|
+
if (match$1 !== undefined) {
|
|
844
|
+
return !canonEq(match, match$1);
|
|
845
|
+
} else {
|
|
846
|
+
return true;
|
|
847
|
+
}
|
|
848
|
+
} else {
|
|
849
|
+
return match$1 !== undefined;
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
let runTier = keys => {
|
|
853
|
+
keys.forEach(k => {
|
|
854
|
+
let match = getTopKey(stored, k);
|
|
855
|
+
let match$1 = getTopKey(current, k);
|
|
856
|
+
if (match !== undefined) {
|
|
857
|
+
if (match$1 !== undefined) {
|
|
858
|
+
return go(match, match$1, k);
|
|
859
|
+
} else {
|
|
860
|
+
acc.push(k);
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
863
|
+
} else if (match$1 !== undefined) {
|
|
864
|
+
acc.push(k);
|
|
865
|
+
return;
|
|
866
|
+
} else {
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
};
|
|
871
|
+
if (typeof stored === "object" && stored !== null && !Array.isArray(stored) && typeof current === "object" && current !== null && !Array.isArray(current)) {
|
|
872
|
+
let tiers = [
|
|
873
|
+
["version"],
|
|
874
|
+
["name"],
|
|
875
|
+
["storage"],
|
|
876
|
+
[
|
|
877
|
+
"evm",
|
|
878
|
+
"fuel",
|
|
879
|
+
"svm"
|
|
880
|
+
],
|
|
881
|
+
["entities"]
|
|
882
|
+
];
|
|
883
|
+
let firstHit = Stdlib_Array.reduce(tiers, undefined, (acc, tier) => {
|
|
884
|
+
if (acc !== undefined) {
|
|
885
|
+
return acc;
|
|
886
|
+
}
|
|
887
|
+
let hits = tier.filter(topKeyDiffers);
|
|
888
|
+
if (hits.length !== 0) {
|
|
889
|
+
return hits;
|
|
890
|
+
}
|
|
891
|
+
});
|
|
892
|
+
if (firstHit !== undefined) {
|
|
893
|
+
runTier(firstHit);
|
|
894
|
+
} else {
|
|
895
|
+
let knownSet = new Set(Belt_Array.concatMany(tiers));
|
|
896
|
+
runTier(Array.from(new Set(Object.keys(stored).concat(Object.keys(current)))).filter(k => !knownSet.has(k)).toSorted(Primitive_string.compare).filter(topKeyDiffers));
|
|
897
|
+
}
|
|
898
|
+
} else {
|
|
899
|
+
go(stored, current, "");
|
|
900
|
+
}
|
|
834
901
|
return acc;
|
|
835
902
|
}
|
|
836
903
|
|
|
837
|
-
function throwIfIncompatible(changedPaths, resetCommand) {
|
|
904
|
+
function throwIfIncompatible(changedPaths, resetCommand, runCommand, hasClickhouse) {
|
|
838
905
|
if (changedPaths.length === 0) {
|
|
839
906
|
return;
|
|
840
907
|
}
|
|
841
908
|
let bullets = changedPaths.map(p => ` - ` + p).join("\n");
|
|
842
|
-
|
|
909
|
+
let option1 = "Revert the changes above";
|
|
910
|
+
let padTo = (s, col) => s + " ".repeat(Math.max(col - s.length | 0, 1));
|
|
911
|
+
let col = Math.max(option1.length, resetCommand.length) + 2 | 0;
|
|
912
|
+
let option3;
|
|
913
|
+
if (runCommand !== undefined) {
|
|
914
|
+
let clickhouseLine = hasClickhouse ? " ENVIO_CLICKHOUSE_DATABASE=<new_db> \\\n" : "";
|
|
915
|
+
option3 = `\n 3. Run a second indexer alongside this one — keep both datasets:\n ENVIO_PG_SCHEMA=<new_schema> \\\n` + clickhouseLine + ` ENVIO_INDEXER_PORT=<new_port> \\\n ` + runCommand;
|
|
916
|
+
} else {
|
|
917
|
+
option3 = "";
|
|
918
|
+
}
|
|
919
|
+
Stdlib_JsError.throwWithMessage(`The following config changes are incompatible with the existing indexer data:\n\n` + bullets + `\n\nPick one:\n 1. ` + padTo(option1, col) + `# resume indexing where it left off\n 2. ` + padTo(resetCommand, col) + `# delete all indexed data and start over` + option3);
|
|
843
920
|
}
|
|
844
921
|
|
|
845
922
|
function loadWithoutRegistrations() {
|
package/src/InMemoryTable.res
CHANGED
|
@@ -71,7 +71,6 @@ module Entity = {
|
|
|
71
71
|
fieldNameIndices: make(~hash=TableIndices.Index.getFieldName),
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
exception UndefinedKey(string)
|
|
75
74
|
let updateIndices = (
|
|
76
75
|
self: t<'entity>,
|
|
77
76
|
~entity: 'entity,
|
|
@@ -83,8 +82,7 @@ module Entity = {
|
|
|
83
82
|
let fieldValue =
|
|
84
83
|
entity
|
|
85
84
|
->(Utils.magic: 'entity => dict<TableIndices.FieldValue.t>)
|
|
86
|
-
->Dict.
|
|
87
|
-
->Option.getUnsafe
|
|
85
|
+
->Dict.getUnsafe(fieldName)
|
|
88
86
|
if !(index->TableIndices.Index.evaluate(~fieldName, ~fieldValue)) {
|
|
89
87
|
entityIndices->Utils.Set.delete(index)->ignore
|
|
90
88
|
}
|
|
@@ -93,27 +91,25 @@ module Entity = {
|
|
|
93
91
|
self.fieldNameIndices.dict
|
|
94
92
|
->Dict.keysToArray
|
|
95
93
|
->Array.forEach(fieldName => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
->
|
|
103
|
-
->
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
)
|
|
116
|
-
}
|
|
94
|
+
let indices = self.fieldNameIndices.dict->Dict.getUnsafe(fieldName)
|
|
95
|
+
// A missing key reads as `undefined`, which matches the `None` arm of
|
|
96
|
+
// `FieldValue.t` (`option<...>`). Mirror `addEmptyIndex` so nullable
|
|
97
|
+
// FK columns that were omitted on the set entity don't crash.
|
|
98
|
+
let fieldValue =
|
|
99
|
+
entity
|
|
100
|
+
->(Utils.magic: 'entity => dict<TableIndices.FieldValue.t>)
|
|
101
|
+
->Dict.getUnsafe(fieldName)
|
|
102
|
+
indices
|
|
103
|
+
->values
|
|
104
|
+
->Array.forEach(((index, relatedEntityIds)) => {
|
|
105
|
+
if index->TableIndices.Index.evaluate(~fieldName, ~fieldValue) {
|
|
106
|
+
//Add entity id to indices and add index to entity indicies
|
|
107
|
+
relatedEntityIds->Utils.Set.add(getEntityIdUnsafe(entity))->ignore
|
|
108
|
+
entityIndices->Utils.Set.add(index)->ignore
|
|
109
|
+
} else {
|
|
110
|
+
relatedEntityIds->Utils.Set.delete(getEntityIdUnsafe(entity))->ignore
|
|
111
|
+
}
|
|
112
|
+
})
|
|
117
113
|
})
|
|
118
114
|
}
|
|
119
115
|
|
|
@@ -90,8 +90,6 @@ function make$1() {
|
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
let UndefinedKey = /* @__PURE__ */Primitive_exceptions.create("InMemoryTable.Entity.UndefinedKey");
|
|
94
|
-
|
|
95
93
|
function updateIndices(self, entity, entityIndices) {
|
|
96
94
|
entityIndices.forEach(index => {
|
|
97
95
|
let fieldName = TableIndices.Index.getFieldName(index);
|
|
@@ -102,22 +100,9 @@ function updateIndices(self, entity, entityIndices) {
|
|
|
102
100
|
}
|
|
103
101
|
});
|
|
104
102
|
Object.keys(self.fieldNameIndices.dict).forEach(fieldName => {
|
|
105
|
-
let
|
|
106
|
-
let
|
|
107
|
-
|
|
108
|
-
return ErrorHandling.mkLogAndRaise(undefined, "Expected field name to exist on the referenced index and the provided entity", {
|
|
109
|
-
RE_EXN_ID: UndefinedKey,
|
|
110
|
-
_1: fieldName
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
if (match$1 === undefined) {
|
|
114
|
-
return ErrorHandling.mkLogAndRaise(undefined, "Expected field name to exist on the referenced index and the provided entity", {
|
|
115
|
-
RE_EXN_ID: UndefinedKey,
|
|
116
|
-
_1: fieldName
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
let fieldValue = Primitive_option.valFromOption(match);
|
|
120
|
-
Object.values(match$1.dict).forEach(param => {
|
|
103
|
+
let indices = self.fieldNameIndices.dict[fieldName];
|
|
104
|
+
let fieldValue = entity[fieldName];
|
|
105
|
+
Object.values(indices.dict).forEach(param => {
|
|
121
106
|
let relatedEntityIds = param[1];
|
|
122
107
|
let index = param[0];
|
|
123
108
|
if (TableIndices.Index.evaluate(index, fieldName, fieldValue)) {
|
|
@@ -333,7 +318,6 @@ let Entity = {
|
|
|
333
318
|
getEntityIdUnsafe: getEntityIdUnsafe,
|
|
334
319
|
makeIndicesSerializedToValue: makeIndicesSerializedToValue,
|
|
335
320
|
make: make$1,
|
|
336
|
-
UndefinedKey: UndefinedKey,
|
|
337
321
|
updateIndices: updateIndices,
|
|
338
322
|
deleteEntityFromIndices: deleteEntityFromIndices,
|
|
339
323
|
initValue: initValue,
|
package/src/Main.res
CHANGED
|
@@ -622,6 +622,7 @@ let migrate = async (~reset) => {
|
|
|
622
622
|
~chainConfigs=config.chainMap->ChainMap.values,
|
|
623
623
|
~envioInfo=getEnvioInfo(),
|
|
624
624
|
~resetCommand="envio local db-migrate setup",
|
|
625
|
+
~runCommand=None,
|
|
625
626
|
)
|
|
626
627
|
await persistence.storage.close()
|
|
627
628
|
}
|
|
@@ -668,6 +669,7 @@ let start = async (
|
|
|
668
669
|
~chainConfigs=configWithoutRegistrations.chainMap->ChainMap.values,
|
|
669
670
|
~envioInfo=getEnvioInfo(),
|
|
670
671
|
~resetCommand=isDevelopmentMode ? "envio dev -r" : "envio start -r",
|
|
672
|
+
~runCommand=Some(isDevelopmentMode ? "envio dev" : "envio start"),
|
|
671
673
|
)
|
|
672
674
|
|
|
673
675
|
// `Config.loadWithoutRegistrations` never sees registration state; handler,
|
package/src/Main.res.mjs
CHANGED
|
@@ -472,7 +472,7 @@ function getEnvioInfo() {
|
|
|
472
472
|
async function migrate(reset) {
|
|
473
473
|
let config = Config.loadWithoutRegistrations();
|
|
474
474
|
let persistence = PgStorage.makePersistenceFromConfig(config, undefined);
|
|
475
|
-
await Persistence.init(persistence, ChainMap.values(config.chainMap), Config.stripSensitiveData(Config.getPublicConfigJson()), "envio local db-migrate setup", reset);
|
|
475
|
+
await Persistence.init(persistence, ChainMap.values(config.chainMap), Config.stripSensitiveData(Config.getPublicConfigJson()), "envio local db-migrate setup", undefined, reset);
|
|
476
476
|
return await persistence.storage.close();
|
|
477
477
|
}
|
|
478
478
|
|
|
@@ -497,7 +497,7 @@ async function start(persistence, resetOpt, isTestOpt, exitAfterFirstEventBlockO
|
|
|
497
497
|
let isDevelopmentMode = !isTest && configWithoutRegistrations.isDev;
|
|
498
498
|
let persistence$1 = persistence !== undefined ? persistence : PgStorage.makePersistenceFromConfig(configWithoutRegistrations, undefined);
|
|
499
499
|
globalPersistenceRef.contents = persistence$1;
|
|
500
|
-
await Persistence.init(persistence$1, ChainMap.values(configWithoutRegistrations.chainMap), Config.stripSensitiveData(Config.getPublicConfigJson()), isDevelopmentMode ? "envio dev -r" : "envio start -r", reset);
|
|
500
|
+
await Persistence.init(persistence$1, ChainMap.values(configWithoutRegistrations.chainMap), Config.stripSensitiveData(Config.getPublicConfigJson()), isDevelopmentMode ? "envio dev -r" : "envio start -r", isDevelopmentMode ? "envio dev" : "envio start", reset);
|
|
501
501
|
let match = await HandlerLoader.registerAllHandlers(configWithoutRegistrations);
|
|
502
502
|
let registrations = match[1];
|
|
503
503
|
let config = match[0];
|
package/src/Persistence.res
CHANGED
|
@@ -168,7 +168,7 @@ let make = (
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
let init = {
|
|
171
|
-
async (persistence, ~chainConfigs, ~envioInfo, ~resetCommand, ~reset=false) => {
|
|
171
|
+
async (persistence, ~chainConfigs, ~envioInfo, ~resetCommand, ~runCommand, ~reset=false) => {
|
|
172
172
|
try {
|
|
173
173
|
let shouldRun = switch persistence.storageStatus {
|
|
174
174
|
| Unknown => true
|
|
@@ -212,7 +212,22 @@ let init = {
|
|
|
212
212
|
| None => ["envio info is missing — storage initialized by an older envio"]
|
|
213
213
|
| Some(stored) => Config.diffPaths(~stored, ~current=envioInfo)
|
|
214
214
|
}
|
|
215
|
-
|
|
215
|
+
// `storage.clickhouse` is serialized as a plain bool by the
|
|
216
|
+
// public config (see Rust `StorageConfig`), so probe for
|
|
217
|
+
// `Boolean(true)`, not an object.
|
|
218
|
+
let hasClickhouse = switch envioInfo {
|
|
219
|
+
| Object(d) =>
|
|
220
|
+
switch d->Dict.get("storage") {
|
|
221
|
+
| Some(Object(s)) =>
|
|
222
|
+
switch s->Dict.get("clickhouse") {
|
|
223
|
+
| Some(Boolean(true)) => true
|
|
224
|
+
| _ => false
|
|
225
|
+
}
|
|
226
|
+
| _ => false
|
|
227
|
+
}
|
|
228
|
+
| _ => false
|
|
229
|
+
}
|
|
230
|
+
Config.throwIfIncompatible(changedPaths, ~resetCommand, ~runCommand, ~hasClickhouse)
|
|
216
231
|
persistence.storageStatus = Ready(initialState)
|
|
217
232
|
let progress = Dict.make()
|
|
218
233
|
initialState.chains->Array.forEach(c => {
|
package/src/Persistence.res.mjs
CHANGED
|
@@ -27,7 +27,7 @@ function make(userEntities, allEnums, storage) {
|
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
async function init(persistence, chainConfigs, envioInfo, resetCommand, resetOpt) {
|
|
30
|
+
async function init(persistence, chainConfigs, envioInfo, resetCommand, runCommand, resetOpt) {
|
|
31
31
|
let reset = resetOpt !== undefined ? resetOpt : false;
|
|
32
32
|
try {
|
|
33
33
|
let promise = persistence.storageStatus;
|
|
@@ -70,7 +70,19 @@ async function init(persistence, chainConfigs, envioInfo, resetCommand, resetOpt
|
|
|
70
70
|
let initialState$1 = await persistence.storage.resumeInitialState();
|
|
71
71
|
let stored = initialState$1.envioInfo;
|
|
72
72
|
let changedPaths = stored !== undefined ? Config.diffPaths(stored, envioInfo) : ["envio info is missing — storage initialized by an older envio"];
|
|
73
|
-
|
|
73
|
+
let hasClickhouse;
|
|
74
|
+
if (typeof envioInfo === "object" && envioInfo !== null && !Array.isArray(envioInfo)) {
|
|
75
|
+
let match$1 = envioInfo["storage"];
|
|
76
|
+
if (typeof match$1 === "object" && match$1 !== null && !Array.isArray(match$1)) {
|
|
77
|
+
let match$2 = match$1["clickhouse"];
|
|
78
|
+
hasClickhouse = match$2 === true;
|
|
79
|
+
} else {
|
|
80
|
+
hasClickhouse = false;
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
hasClickhouse = false;
|
|
84
|
+
}
|
|
85
|
+
Config.throwIfIncompatible(changedPaths, resetCommand, runCommand, hasClickhouse);
|
|
74
86
|
persistence.storageStatus = {
|
|
75
87
|
TAG: "Ready",
|
|
76
88
|
_0: initialState$1
|