envio 3.5.0-alpha.3 → 3.5.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.
Files changed (127) hide show
  1. package/package.json +6 -6
  2. package/src/Batch.res +8 -8
  3. package/src/Batch.res.mjs +4 -3
  4. package/src/BatchProcessing.res +17 -7
  5. package/src/BatchProcessing.res.mjs +8 -4
  6. package/src/ChainFetching.res +20 -19
  7. package/src/ChainFetching.res.mjs +14 -14
  8. package/src/ChainId.res +58 -0
  9. package/src/ChainId.res.mjs +49 -0
  10. package/src/ChainId.resi +27 -0
  11. package/src/ChainMap.res +12 -26
  12. package/src/ChainMap.res.mjs +5 -41
  13. package/src/ChainMap.resi +5 -20
  14. package/src/ChainMetadata.res +1 -1
  15. package/src/ChainMetadata.res.mjs +3 -2
  16. package/src/ChainState.res +35 -20
  17. package/src/ChainState.res.mjs +34 -11
  18. package/src/ChainState.resi +2 -0
  19. package/src/Config.res +41 -24
  20. package/src/Config.res.mjs +17 -14
  21. package/src/ContractRegisterContext.res +1 -1
  22. package/src/ContractRegisterContext.res.mjs +1 -1
  23. package/src/Core.res +1 -0
  24. package/src/CrossChainState.res +61 -16
  25. package/src/CrossChainState.res.mjs +37 -13
  26. package/src/CrossChainState.resi +3 -2
  27. package/src/Env.res +0 -3
  28. package/src/Env.res.mjs +0 -3
  29. package/src/EventConfigBuilder.res +1 -1
  30. package/src/EventProcessing.res +4 -4
  31. package/src/EventProcessing.res.mjs +5 -5
  32. package/src/FetchState.res +261 -89
  33. package/src/FetchState.res.mjs +187 -63
  34. package/src/FinalizeBackfill.res +33 -6
  35. package/src/FinalizeBackfill.res.mjs +19 -1
  36. package/src/HandlerRegister.res +8 -8
  37. package/src/HandlerRegister.res.mjs +5 -4
  38. package/src/HandlerRegister.resi +1 -1
  39. package/src/InMemoryStore.res +4 -0
  40. package/src/InMemoryStore.res.mjs +1 -1
  41. package/src/IndexerLoop.res +9 -2
  42. package/src/IndexerLoop.res.mjs +8 -1
  43. package/src/IndexerState.res +41 -24
  44. package/src/IndexerState.res.mjs +36 -17
  45. package/src/IndexerState.resi +9 -7
  46. package/src/Internal.res +19 -17
  47. package/src/Internal.res.mjs +18 -9
  48. package/src/LoadLayer.res +1 -1
  49. package/src/LoadLayer.res.mjs +2 -1
  50. package/src/LogSelection.res +2 -2
  51. package/src/Main.res +7 -11
  52. package/src/Main.res.mjs +4 -6
  53. package/src/Metrics.res +6 -6
  54. package/src/Metrics.res.mjs +4 -3
  55. package/src/Persistence.res +15 -7
  56. package/src/PgStorage.res +284 -258
  57. package/src/PgStorage.res.mjs +181 -208
  58. package/src/RawEvent.res +1 -2
  59. package/src/RawEvent.res.mjs +1 -1
  60. package/src/Rollback.res +18 -20
  61. package/src/Rollback.res.mjs +9 -9
  62. package/src/RollbackCommit.res +2 -2
  63. package/src/RollbackCommit.res.mjs +3 -3
  64. package/src/SafeCheckpointTracking.res +2 -2
  65. package/src/SimulateDeadInputTracker.res +17 -21
  66. package/src/SimulateDeadInputTracker.res.mjs +9 -8
  67. package/src/SimulateItems.res +8 -10
  68. package/src/SimulateItems.res.mjs +9 -10
  69. package/src/Sink.res +2 -2
  70. package/src/Sink.res.mjs +3 -2
  71. package/src/TestIndexer.res +11 -14
  72. package/src/TestIndexer.res.mjs +14 -10
  73. package/src/UserContext.res +2 -2
  74. package/src/UserContext.res.mjs +2 -1
  75. package/src/Utils.res +0 -4
  76. package/src/Utils.res.mjs +1 -6
  77. package/src/bindings/ClickHouse.res +20 -2
  78. package/src/bindings/ClickHouse.res.mjs +25 -14
  79. package/src/db/EntityHistory.res +1 -1
  80. package/src/db/IndexCatalog.res +248 -0
  81. package/src/db/IndexCatalog.res.mjs +222 -0
  82. package/src/db/IndexDefinition.res +131 -0
  83. package/src/db/IndexDefinition.res.mjs +138 -0
  84. package/src/db/IndexManager.res +145 -0
  85. package/src/db/IndexManager.res.mjs +130 -0
  86. package/src/db/InternalTable.res +50 -26
  87. package/src/db/InternalTable.res.mjs +32 -24
  88. package/src/db/Table.res +11 -1
  89. package/src/db/Table.res.mjs +9 -4
  90. package/src/sources/AddressSet.res +5 -4
  91. package/src/sources/AddressStore.res +25 -14
  92. package/src/sources/AddressStore.res.mjs +10 -12
  93. package/src/sources/Evm.res +2 -2
  94. package/src/sources/Evm.res.mjs +1 -1
  95. package/src/sources/EvmChain.res +3 -3
  96. package/src/sources/EvmChain.res.mjs +3 -3
  97. package/src/sources/EvmHyperSyncSource.res +7 -7
  98. package/src/sources/EvmHyperSyncSource.res.mjs +6 -6
  99. package/src/sources/Fuel.res +2 -2
  100. package/src/sources/Fuel.res.mjs +1 -1
  101. package/src/sources/FuelHyperSyncClient.res +3 -0
  102. package/src/sources/FuelHyperSyncClient.res.mjs +1 -0
  103. package/src/sources/FuelHyperSyncSource.res +5 -7
  104. package/src/sources/FuelHyperSyncSource.res.mjs +5 -5
  105. package/src/sources/HyperSync.resi +2 -2
  106. package/src/sources/HyperSyncClient.res +5 -0
  107. package/src/sources/HyperSyncClient.res.mjs +1 -0
  108. package/src/sources/RpcSource.res +13 -14
  109. package/src/sources/RpcSource.res.mjs +13 -12
  110. package/src/sources/SimulateSource.res +42 -15
  111. package/src/sources/SimulateSource.res.mjs +27 -9
  112. package/src/sources/Source.res +1 -5
  113. package/src/sources/SourceManager.res +12 -12
  114. package/src/sources/SourceManager.res.mjs +11 -10
  115. package/src/sources/SourceManager.resi +2 -2
  116. package/src/sources/Svm.res +4 -5
  117. package/src/sources/Svm.res.mjs +5 -4
  118. package/src/sources/SvmHyperSyncClient.res +3 -0
  119. package/src/sources/SvmHyperSyncClient.res.mjs +1 -0
  120. package/src/sources/SvmHyperSyncSource.res +4 -4
  121. package/src/sources/SvmHyperSyncSource.res.mjs +3 -3
  122. package/src/tui/Tui.res +1 -1
  123. package/src/tui/Tui.res.mjs +2 -1
  124. package/src/tui/components/CustomHooks.res +5 -4
  125. package/src/tui/components/CustomHooks.res.mjs +4 -2
  126. package/src/db/IndexRegistry.res +0 -219
  127. package/src/db/IndexRegistry.res.mjs +0 -195
@@ -9,6 +9,7 @@ import * as Utils from "./Utils.res.mjs";
9
9
  import * as Config from "./Config.res.mjs";
10
10
  import * as Hasura from "./Hasura.res.mjs";
11
11
  import * as Schema from "./db/Schema.res.mjs";
12
+ import * as ChainId from "./ChainId.res.mjs";
12
13
  import * as Logging from "./Logging.res.mjs";
13
14
  import * as EntityId from "./EntityId.res.mjs";
14
15
  import * as Internal from "./Internal.res.mjs";
@@ -16,14 +17,16 @@ import Postgres from "postgres";
16
17
  import * as ChainState from "./ChainState.res.mjs";
17
18
  import * as Performance from "./bindings/Performance.res.mjs";
18
19
  import * as Persistence from "./Persistence.res.mjs";
20
+ import * as IndexCatalog from "./db/IndexCatalog.res.mjs";
21
+ import * as IndexManager from "./db/IndexManager.res.mjs";
19
22
  import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
20
23
  import * as EntityHistory from "./db/EntityHistory.res.mjs";
21
- import * as IndexRegistry from "./db/IndexRegistry.res.mjs";
22
24
  import * as InternalTable from "./db/InternalTable.res.mjs";
23
25
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
24
26
  import * as Child_process from "child_process";
25
27
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
26
28
  import * as Stdlib_Promise from "@rescript/runtime/lib/es6/Stdlib_Promise.js";
29
+ import * as IndexDefinition from "./db/IndexDefinition.res.mjs";
27
30
  import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
28
31
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
29
32
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
@@ -45,108 +48,33 @@ function makeClient() {
45
48
  });
46
49
  }
47
50
 
48
- function makeCreateIndexQuery(tableName, indexFields, pgSchema) {
49
- let indexName = tableName + "_" + indexFields.join("_");
50
- let index = indexFields.map(idx => `"` + idx + `"`).join(", ");
51
- return `CREATE INDEX IF NOT EXISTS "` + indexName + `" ON "` + pgSchema + `"."` + tableName + `"(` + index + `);`;
52
- }
53
-
54
- function directionToSql(direction) {
55
- if (direction === "Asc") {
56
- return "";
57
- } else {
58
- return " DESC";
59
- }
60
- }
61
-
62
- function directionToIndexName(direction) {
63
- if (direction === "Asc") {
64
- return "";
65
- } else {
66
- return "_desc";
67
- }
68
- }
69
-
70
- function makeCreateCompositeIndexQuery(tableName, indexFields, pgSchema) {
71
- let indexName = tableName + "_" + indexFields.map(f => f.fieldName + directionToIndexName(f.direction)).join("_");
72
- let index = indexFields.map(f => `"` + f.fieldName + `"` + directionToSql(f.direction)).join(", ");
73
- return `CREATE INDEX IF NOT EXISTS "` + indexName + `" ON "` + pgSchema + `"."` + tableName + `"(` + index + `);`;
74
- }
75
-
76
- function makeCreateTableIndexesQuery(table, pgSchema) {
77
- let tableName = table.tableName;
78
- let createIndex = indexField => makeCreateIndexQuery(tableName, [indexField], pgSchema);
79
- let createCompositeIndex = indexFields => makeCreateCompositeIndexQuery(tableName, indexFields, pgSchema);
80
- let singleIndexes = Table.getSingleIndexes(table);
81
- let compositeIndexes = Table.getCompositeIndexes(table);
82
- return singleIndexes.map(createIndex).join("\n") + compositeIndexes.map(createCompositeIndex).join("\n");
83
- }
84
-
85
- function schemaIndexDescription(param) {
86
- return param.tableName + "_" + param.indexFields.map(f => f.fieldName + directionToIndexName(f.direction)).join("_");
87
- }
88
-
89
- function schemaIndexName(schemaIndex) {
90
- return IndexRegistry.truncateIndexName(schemaIndexDescription(schemaIndex));
91
- }
92
-
93
- function schemaIndexKey(param) {
94
- return IndexRegistry.makeKey(param.tableName, IndexRegistry.fromIndexFields(param.indexFields), IndexRegistry.btree);
95
- }
96
-
97
- function makeCreateSchemaIndexQuery(schemaIndex, pgSchema) {
98
- let columns = schemaIndex.indexFields.map(f => `"` + f.fieldName + `"` + directionToSql(f.direction)).join(", ");
99
- return `CREATE INDEX IF NOT EXISTS "` + IndexRegistry.truncateIndexName(schemaIndexDescription(schemaIndex)) + `" ON "` + pgSchema + `"."` + schemaIndex.tableName + `"(` + columns + `);`;
100
- }
101
-
102
51
  function formatSeconds(timeRef) {
103
52
  return (Math.round(Performance.secondsSince(timeRef) * 100) / 100).toString();
104
53
  }
105
54
 
106
55
  let slowOnLargeDatabaseNotice = "This can take a long time on a large database.";
107
56
 
108
- function makeReindexQuery(pgSchema, indexName) {
109
- return `REINDEX INDEX "` + pgSchema + `"."` + indexName + `";`;
110
- }
111
-
112
- function nameCollisionError(indexName, pgSchema) {
113
- return new Error(`Cannot create the index "` + indexName + `" in schema "` + pgSchema + `". An index of that name already exists and PostgreSQL reports it as invalid, but it isn't one the indexer created — it covers different columns, or it is a unique or partial index — so it is left untouched. Drop or repair it by hand, then restart the indexer.`);
114
- }
115
-
116
- function makeSingleColumnSchemaIndex(tableName, column) {
117
- return {
118
- tableName: tableName,
119
- indexFields: [{
120
- fieldName: column,
121
- direction: "Asc"
122
- }]
123
- };
124
- }
125
-
126
57
  function getSchemaIndexes(entities) {
127
58
  let derivedSchema = Schema.make(entities.map(e => e.table));
128
59
  let all = [];
129
60
  entities.forEach(param => {
130
61
  let table = param.table;
131
62
  Table.getSingleIndexes(table).forEach(column => {
132
- all.push(makeSingleColumnSchemaIndex(table.tableName, column));
63
+ all.push(IndexDefinition.single(table.tableName, column));
133
64
  });
134
65
  Table.getCompositeIndexes(table).forEach(indexFields => {
135
- all.push({
136
- tableName: table.tableName,
137
- indexFields: indexFields
138
- });
66
+ all.push(IndexDefinition.fromIndexFields(table.tableName, indexFields));
139
67
  });
140
68
  });
141
69
  entities.forEach(param => {
142
70
  Table.getDerivedFromFields(param.table).forEach(derivedFromField => {
143
71
  let column = Utils.unwrapResultExn(Schema.getDerivedFromPgFieldName(derivedSchema, derivedFromField));
144
- all.push(makeSingleColumnSchemaIndex(derivedFromField.derivedFromEntity, column));
72
+ all.push(IndexDefinition.single(derivedFromField.derivedFromEntity, column));
145
73
  });
146
74
  });
147
75
  let seen = new Set();
148
- return all.filter(schemaIndex => {
149
- let key = schemaIndexKey(schemaIndex);
76
+ return all.filter(definition => {
77
+ let key = IndexDefinition.key(definition);
150
78
  if (seen.has(key)) {
151
79
  return false;
152
80
  } else {
@@ -156,12 +84,13 @@ function getSchemaIndexes(entities) {
156
84
  });
157
85
  }
158
86
 
159
- function makeCreateTableQuery(table, pgSchema, isNumericArrayAsText) {
87
+ function makeCreateTableQuery(table, pgSchema, isNumericArrayAsText, chainIdModeOpt) {
88
+ let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
160
89
  let fieldsMapped = Table.getFields(table).map(field => {
161
90
  let defaultValue = field.defaultValue;
162
91
  let isNullable = field.isNullable;
163
92
  let fieldName = Table.getPgDbFieldName(field);
164
- return `"` + fieldName + `" ` + Table.getPgFieldType(field.fieldType, pgSchema, field.isArray, isNumericArrayAsText, isNullable) + (
93
+ return `"` + fieldName + `" ` + Table.getPgFieldType(field.fieldType, pgSchema, field.isArray, isNumericArrayAsText, isNullable, chainIdMode) + (
165
94
  defaultValue !== undefined ? ` DEFAULT ` + defaultValue : (
166
95
  isNullable ? `` : ` NOT NULL`
167
96
  )
@@ -244,12 +173,13 @@ function getEntityHistory(entityConfig) {
244
173
  return cache$1;
245
174
  }
246
175
 
247
- function makeInitializeTransaction(pgSchema, pgUser, isHasuraEnabled, chainConfigsOpt, entitiesOpt, enumsOpt, isEmptyPgSchemaOpt, deferSchemaIndexesOpt) {
176
+ function makeInitializeTransaction(pgSchema, pgUser, isHasuraEnabled, chainConfigsOpt, entitiesOpt, enumsOpt, isEmptyPgSchemaOpt, deferSchemaIndexesOpt, chainIdModeOpt) {
248
177
  let chainConfigs = chainConfigsOpt !== undefined ? chainConfigsOpt : [];
249
178
  let entities = entitiesOpt !== undefined ? entitiesOpt : [];
250
179
  let enums = enumsOpt !== undefined ? enumsOpt : [];
251
180
  let isEmptyPgSchema = isEmptyPgSchemaOpt !== undefined ? isEmptyPgSchemaOpt : false;
252
181
  let deferSchemaIndexes = deferSchemaIndexesOpt !== undefined ? deferSchemaIndexesOpt : false;
182
+ let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
253
183
  let generalTables = [
254
184
  InternalTable.Chains.table,
255
185
  InternalTable.EnvioInfo.table,
@@ -262,7 +192,6 @@ function makeInitializeTransaction(pgSchema, pgUser, isHasuraEnabled, chainConfi
262
192
  allTables.push(getEntityHistory(entityConfig).table);
263
193
  });
264
194
  let schemaIndexes = getSchemaIndexes(entities);
265
- IndexRegistry.validateIndexNamesOrThrow(schemaIndexes.map(schemaIndexDescription));
266
195
  let query = {
267
196
  contents: (
268
197
  isEmptyPgSchema && pgSchema === "public" ? `CREATE SCHEMA IF NOT EXISTS "` + pgSchema + `";\n` : `DROP SCHEMA IF EXISTS "` + pgSchema + `" CASCADE;
@@ -275,11 +204,11 @@ GRANT ALL ON SCHEMA "` + pgSchema + `" TO public;`)
275
204
  query.contents = query.contents + "\n" + enumCreateQuery;
276
205
  });
277
206
  allTables.forEach(table => {
278
- query.contents = query.contents + "\n" + makeCreateTableQuery(table, pgSchema, isHasuraEnabled);
207
+ query.contents = query.contents + "\n" + makeCreateTableQuery(table, pgSchema, isHasuraEnabled, chainIdMode);
279
208
  });
280
209
  if (!deferSchemaIndexes) {
281
- schemaIndexes.forEach(schemaIndex => {
282
- query.contents = query.contents + "\n" + makeCreateSchemaIndexQuery(schemaIndex, pgSchema);
210
+ schemaIndexes.forEach(definition => {
211
+ query.contents = query.contents + "\n" + IndexDefinition.makeCreateQuery(definition, pgSchema);
283
212
  });
284
213
  }
285
214
  query.contents = query.contents + "\n" + InternalTable.Views.makeMetaViewQuery(pgSchema);
@@ -368,8 +297,9 @@ function makeLoadAllQuery(pgSchema, tableName) {
368
297
  return `SELECT * FROM "` + pgSchema + `"."` + tableName + `";`;
369
298
  }
370
299
 
371
- function makeInsertUnnestSetQuery(pgSchema, table, itemSchema, isRawEvents) {
372
- let match = Table.toSqlParams(table, itemSchema, pgSchema);
300
+ function makeInsertUnnestSetQuery(pgSchema, table, itemSchema, isRawEvents, chainIdModeOpt) {
301
+ let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
302
+ let match = Table.toSqlParams(table, itemSchema, pgSchema, chainIdMode);
373
303
  let quotedNonPrimaryFieldNames = match.quotedNonPrimaryFieldNames;
374
304
  let primaryKeyFieldNames = Table.getPgPrimaryKeyFieldNames(table);
375
305
  return `INSERT INTO "` + pgSchema + `"."` + table.tableName + `" (` + match.quotedFieldNames.join(", ") + `)
@@ -380,8 +310,9 @@ SELECT * FROM unnest(` + match.arrayFieldTypes.map((arrayFieldType, idx) => `$`
380
310
  ) + ";";
381
311
  }
382
312
 
383
- function makeInsertValuesSetQuery(pgSchema, table, itemSchema, itemsCount) {
384
- let match = Table.toSqlParams(table, itemSchema, pgSchema);
313
+ function makeInsertValuesSetQuery(pgSchema, table, itemSchema, itemsCount, chainIdModeOpt) {
314
+ let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
315
+ let match = Table.toSqlParams(table, itemSchema, pgSchema, chainIdMode);
385
316
  let quotedNonPrimaryFieldNames = match.quotedNonPrimaryFieldNames;
386
317
  let quotedFieldNames = match.quotedFieldNames;
387
318
  let primaryKeyFieldNames = Table.getPgPrimaryKeyFieldNames(table);
@@ -408,19 +339,20 @@ VALUES` + placeholders + (
408
339
  ) + ";";
409
340
  }
410
341
 
411
- function makeTableBatchSetQuery(pgSchema, table, itemSchema) {
412
- let match = Table.toSqlParams(table, itemSchema, pgSchema);
342
+ function makeTableBatchSetQuery(pgSchema, table, itemSchema, chainIdModeOpt) {
343
+ let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
344
+ let match = Table.toSqlParams(table, itemSchema, pgSchema, chainIdMode);
413
345
  let isRawEvents = table.tableName === InternalTable.RawEvents.table.tableName;
414
346
  let isHistoryUpdate = table.tableName.startsWith(EntityHistory.historyTablePrefix);
415
347
  if ((isRawEvents || !match.hasArrayField) && !isHistoryUpdate) {
416
348
  return {
417
- query: makeInsertUnnestSetQuery(pgSchema, table, itemSchema, isRawEvents),
349
+ query: makeInsertUnnestSetQuery(pgSchema, table, itemSchema, isRawEvents, chainIdMode),
418
350
  convertOrThrow: S$RescriptSchema.compile(S$RescriptSchema.unnest(match.dbSchema), "Output", "Input", "Sync", false),
419
351
  isInsertValues: false
420
352
  };
421
353
  } else {
422
354
  return {
423
- query: makeInsertValuesSetQuery(pgSchema, table, itemSchema, 500),
355
+ query: makeInsertValuesSetQuery(pgSchema, table, itemSchema, 500, chainIdMode),
424
356
  convertOrThrow: S$RescriptSchema.compile(S$RescriptSchema.preprocess(S$RescriptSchema.unnest(itemSchema), param => ({
425
357
  s: prim => prim.flat(1)
426
358
  })), "Output", "Input", "Sync", false),
@@ -496,7 +428,8 @@ function classifyWriteError(specificError, table, exn) {
496
428
 
497
429
  let setQueryCache = new WeakMap();
498
430
 
499
- async function setOrThrow(sql, items, table, itemSchema, pgSchema) {
431
+ async function setOrThrow(sql, items, table, itemSchema, pgSchema, chainIdModeOpt) {
432
+ let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
500
433
  if (items.length === 0) {
501
434
  return;
502
435
  }
@@ -505,7 +438,7 @@ async function setOrThrow(sql, items, table, itemSchema, pgSchema) {
505
438
  if (cached !== undefined) {
506
439
  data = Primitive_option.valFromOption(cached);
507
440
  } else {
508
- let newQuery = makeTableBatchSetQuery(pgSchema, table, itemSchema);
441
+ let newQuery = makeTableBatchSetQuery(pgSchema, table, itemSchema, chainIdMode);
509
442
  setQueryCache.set(table, newQuery);
510
443
  data = newQuery;
511
444
  }
@@ -519,7 +452,7 @@ async function setOrThrow(sql, items, table, itemSchema, pgSchema) {
519
452
  let chunkSize = chunk.length;
520
453
  let isFullChunk = chunkSize === 500;
521
454
  let params = data.convertOrThrow(chunk);
522
- let response = isFullChunk ? sql.unsafe(data.query, params, {prepare: true}) : sql.unsafe(makeInsertValuesSetQuery(pgSchema, table, itemSchema, chunkSize), params);
455
+ let response = isFullChunk ? sql.unsafe(data.query, params, {prepare: true}) : sql.unsafe(makeInsertValuesSetQuery(pgSchema, table, itemSchema, chunkSize, chainIdMode), params);
523
456
  responses.push(response);
524
457
  });
525
458
  await Promise.all(responses);
@@ -654,7 +587,7 @@ function makeInsertDeleteUpdatesQuery(entityConfig, pgSchema) {
654
587
  }
655
588
  });
656
589
  let selectPartsStr = selectParts.join(", ");
657
- let checkpointIdPgType = Table.getPgFieldType(EntityHistory.checkpointIdFieldType, pgSchema, false, false, false);
590
+ let checkpointIdPgType = Table.getPgFieldType(EntityHistory.checkpointIdFieldType, pgSchema, false, false, false, undefined);
658
591
  let idPgType = Table.getIdPgFieldType(entityConfig.table, pgSchema);
659
592
  return `INSERT INTO "` + pgSchema + `"."` + historyTableName + `" (` + allHistoryFieldNamesStr + `)
660
593
  SELECT ` + selectPartsStr + `
@@ -671,6 +604,7 @@ function executeSet(sql, items, dbFunction) {
671
604
 
672
605
  async function writeBatch(sql, batch, pgSchema, rollback, isInReorgThreshold, config, allEntities, setEffectCacheOrThrow, updatedEffectsCache, updatedEntities, sinkPromise, chainMetaData, escapeTables) {
673
606
  try {
607
+ let chainIdMode = config.chainIdMode;
674
608
  let shouldSaveHistory = Config.shouldSaveHistory(config, isInReorgThreshold);
675
609
  let specificError = {
676
610
  contents: undefined
@@ -682,7 +616,7 @@ async function writeBatch(sql, batch, pgSchema, rollback, isInReorgThreshold, co
682
616
  if (item.kind !== 0) {
683
617
  return;
684
618
  }
685
- let coordinate = Internal.getItemChainId(item).toString() + `-` + item.blockNumber.toString() + `-` + item.logIndex.toString();
619
+ let coordinate = ChainId.toString(Internal.getItemChainId(item)) + `-` + item.blockNumber.toString() + `-` + item.logIndex.toString();
686
620
  if (seenLogCoordinates.has(coordinate)) {
687
621
  return;
688
622
  } else {
@@ -699,7 +633,7 @@ async function writeBatch(sql, batch, pgSchema, rollback, isInReorgThreshold, co
699
633
  }
700
634
  let setRawEvents = async sql => {
701
635
  try {
702
- return await executeSet(sql, rawEvents, (sql, items) => setOrThrow(sql, items, InternalTable.RawEvents.table, InternalTable.RawEvents.schema, pgSchema));
636
+ return await executeSet(sql, rawEvents, (sql, items) => setOrThrow(sql, items, InternalTable.RawEvents.table, InternalTable.RawEvents.schema, pgSchema, chainIdMode));
703
637
  } catch (raw_exn) {
704
638
  let exn = Primitive_exceptions.internalToException(raw_exn);
705
639
  return classifyWriteError(specificError, InternalTable.RawEvents.table, exn);
@@ -776,14 +710,14 @@ async function writeBatch(sql, batch, pgSchema, rollback, isInReorgThreshold, co
776
710
  }));
777
711
  }
778
712
  let entityHistory = getEntityHistory(entityConfig);
779
- promises.push(setOrThrow(sql, batchSetUpdates, entityHistory.table, entityHistory.setChangeSchema, pgSchema));
713
+ promises.push(setOrThrow(sql, batchSetUpdates, entityHistory.table, entityHistory.setChangeSchema, pgSchema, chainIdMode));
780
714
  }
781
715
  }
782
716
  if (Utils.$$Array.notEmpty(entitiesToSet)) {
783
717
  if (shouldRemoveInvalidUtf8) {
784
718
  removeInvalidUtf8InPlace(entitiesToSet);
785
719
  }
786
- promises.push(setOrThrow(sql, entitiesToSet, entityConfig.table, entityConfig.schema, pgSchema));
720
+ promises.push(setOrThrow(sql, entitiesToSet, entityConfig.table, entityConfig.schema, pgSchema, chainIdMode));
787
721
  }
788
722
  if (Utils.$$Array.notEmpty(idsToDelete)) {
789
723
  promises.push(deleteByIdsOrThrow(sql, pgSchema, idsToDelete, entityConfig.table));
@@ -800,7 +734,7 @@ async function writeBatch(sql, batch, pgSchema, rollback, isInReorgThreshold, co
800
734
  if (rollback !== undefined) {
801
735
  let rollbackTargetCheckpointId = rollback.targetCheckpointId;
802
736
  rollbackTables = sql => {
803
- let promises = allEntities.map(entityConfig => EntityHistory.rollback(sql, pgSchema, entityConfig.name, entityConfig.index, rollbackTargetCheckpointId));
737
+ let promises = allEntities.filter(entityConfig => entityConfig.storage.postgres).map(entityConfig => EntityHistory.rollback(sql, pgSchema, entityConfig.name, entityConfig.index, rollbackTargetCheckpointId));
804
738
  promises.push(InternalTable.Checkpoints.rollback(sql, pgSchema, rollbackTargetCheckpointId));
805
739
  return Promise.all(promises);
806
740
  };
@@ -826,7 +760,7 @@ async function writeBatch(sql, batch, pgSchema, rollback, isInReorgThreshold, co
826
760
  setOperations.push(sql => InternalTable.Chains.setMeta(sql, pgSchema, chainMetaData));
827
761
  }
828
762
  if (shouldSaveHistory) {
829
- setOperations.push(sql => InternalTable.Checkpoints.insert(sql, pgSchema, batch.checkpointIds, batch.checkpointChainIds, batch.checkpointBlockNumbers, batch.checkpointBlockHashes, batch.checkpointEventsProcessed));
763
+ setOperations.push(sql => InternalTable.Checkpoints.insert(sql, pgSchema, batch.checkpointIds, batch.checkpointChainIds, batch.checkpointBlockNumbers, batch.checkpointBlockHashes, batch.checkpointEventsProcessed, chainIdMode));
830
764
  }
831
765
  await Promise.all(setOperations.map(dbFunc => dbFunc(sql)));
832
766
  if (sinkPromise === undefined) {
@@ -901,7 +835,8 @@ let rollbackRowStateSchema = Utils.$$WeakMap.memoize(table => S$RescriptSchema.o
901
835
 
902
836
  let rollbackRemovedIdsSchema = Utils.$$WeakMap.memoize(table => S$RescriptSchema.array(S$RescriptSchema.object(s => s.f(Table.idFieldName, Table.getIdSchema(table)))));
903
837
 
904
- function make(sql, pgHost, pgSchema, pgPort, pgUser, pgDatabase, pgPassword, isHasuraEnabled, sink, onInitialize, onNewTables) {
838
+ function make(sql, pgHost, pgSchema, pgPort, pgUser, pgDatabase, pgPassword, isHasuraEnabled, chainIdModeOpt, sink, onInitialize, onNewTables) {
839
+ let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
905
840
  let containerName = "envio-postgres";
906
841
  let psqlExecOptions_env = Object.fromEntries([
907
842
  [
@@ -918,20 +853,25 @@ function make(sql, pgHost, pgSchema, pgPort, pgUser, pgDatabase, pgPassword, isH
918
853
  };
919
854
  let cacheDirPath = Path.resolve(".envio", "cache");
920
855
  let storageName = "postgres";
921
- let indexRegistry = IndexRegistry.make();
922
- let reloadIndexRegistry = async () => {
923
- let rows = S$RescriptSchema.parseOrThrow(await sql.unsafe(IndexRegistry.makeCatalogQuery(pgSchema)), IndexRegistry.catalogRowsSchema);
924
- let invalidIndexNames = IndexRegistry.reload(indexRegistry, rows);
856
+ let indexManager = IndexManager.make();
857
+ let loadCatalogRows = (sql, indexName) => sql.unsafe(IndexCatalog.makeQuery(pgSchema, indexName)).then(rows => S$RescriptSchema.parseOrThrow(rows, IndexCatalog.rowsSchema));
858
+ let refreshIndexCatalog = async () => {
859
+ let rows = await loadCatalogRows(sql, undefined);
860
+ return IndexManager.reload(indexManager, rows);
861
+ };
862
+ let reloadIndexCatalog = async () => {
863
+ let catalog = await refreshIndexCatalog();
864
+ let invalidIndexNames = IndexCatalog.invalidNames(catalog);
925
865
  if (invalidIndexNames.length !== 0) {
926
866
  Logging.warn({
927
867
  storage: storageName,
928
- msg: `Ignoring invalid PostgreSQL indexes in schema "` + pgSchema + `". They are left untouched drop and recreate them manually if you need them.`,
868
+ msg: `Ignoring invalid PostgreSQL indexes in schema "` + pgSchema + `". They can't serve queries, so the indexer builds its own alongside them.`,
929
869
  indexes: invalidIndexNames
930
870
  });
931
871
  }
932
872
  return Logging.info({
933
873
  storage: storageName,
934
- msg: `Found ` + IndexRegistry.size(indexRegistry).toString() + ` existing indexes in the indexer schema.`
874
+ msg: `Found ` + IndexCatalog.size(catalog).toString() + ` existing indexes in the indexer schema.`
935
875
  });
936
876
  };
937
877
  let isInitialized = async () => Utils.$$Array.notEmpty(await sql.unsafe(`SELECT table_schema FROM information_schema.tables WHERE table_schema = '` + pgSchema + `' AND (table_name = '` + "event_sync_state" + `' OR table_name = '` + InternalTable.Chains.table.tableName + `');`));
@@ -950,21 +890,23 @@ function make(sql, pgHost, pgSchema, pgPort, pgUser, pgDatabase, pgPassword, isH
950
890
  let subEntries = await Fs.promises.readdir(entryPath);
951
891
  let tsvs = subEntries.filter(sub => sub.endsWith(".tsv"));
952
892
  let chainId = Internal.EffectCache.parseChainId(entry);
953
- if (chainId !== undefined) {
954
- tsvs.forEach(sub => {
955
- let effectName = sub.slice(0, -4);
956
- let table = Internal.makeCacheTable(effectName, chainId);
957
- result.push([
958
- table,
959
- Path.join(entryPath, sub)
960
- ]);
961
- });
962
- return;
963
- } else if (Utils.$$Array.notEmpty(tsvs)) {
964
- return Stdlib_JsError.throwWithMessage(`Invalid effect cache directory ".envio/cache/` + entry + `". Chain cache directories must be named by a numeric chain id (e.g. "1"). Found cache files: ` + tsvs.join(", ") + `.`);
965
- } else {
966
- return;
893
+ if (chainId === undefined) {
894
+ if (Utils.$$Array.notEmpty(tsvs)) {
895
+ return Stdlib_JsError.throwWithMessage(`Invalid effect cache directory ".envio/cache/` + entry + `". Chain cache directories must be named by a numeric chain id (e.g. "1"). Found cache files: ` + tsvs.join(", ") + `.`);
896
+ } else {
897
+ return;
898
+ }
967
899
  }
900
+ let chainId$1 = Primitive_option.valFromOption(chainId);
901
+ tsvs.forEach(sub => {
902
+ let effectName = sub.slice(0, -4);
903
+ let table = Internal.makeCacheTable(effectName, chainId$1);
904
+ result.push([
905
+ table,
906
+ Path.join(entryPath, sub)
907
+ ]);
908
+ });
909
+ return;
968
910
  }
969
911
  if (!entry.endsWith(".tsv")) {
970
912
  return;
@@ -999,7 +941,7 @@ function make(sql, pgHost, pgSchema, pgPort, pgUser, pgDatabase, pgPassword, isH
999
941
  await Promise.all(entries.map(param => {
1000
942
  let inputFile = param[1];
1001
943
  let table = param[0];
1002
- return sql.unsafe(makeCreateTableQuery(table, pgSchema, false)).then(() => {
944
+ return sql.unsafe(makeCreateTableQuery(table, pgSchema, false, undefined)).then(() => {
1003
945
  let command = psqlExec$1 + ` -c 'COPY "` + pgSchema + `"."` + table.tableName + `" FROM STDIN WITH (FORMAT text, HEADER);' < ` + inputFile;
1004
946
  return new Promise((resolve, reject) => {
1005
947
  Child_process.exec(command, psqlExecOptions, (error, stdout, param) => {
@@ -1053,7 +995,7 @@ function make(sql, pgHost, pgSchema, pgPort, pgUser, pgDatabase, pgPassword, isH
1053
995
  if (sink !== undefined) {
1054
996
  await sink.initialize(chainConfigs, chEntities, enums);
1055
997
  }
1056
- let queries = makeInitializeTransaction(pgSchema, pgUser, isHasuraEnabled, chainConfigs, pgEntities, enums, Utils.$$Array.isEmpty(schemaTableNames), true);
998
+ let queries = makeInitializeTransaction(pgSchema, pgUser, isHasuraEnabled, chainConfigs, pgEntities, enums, Utils.$$Array.isEmpty(schemaTableNames), true, chainIdMode);
1057
999
  await sql.begin(async sql => {
1058
1000
  await Promise.all(queries.map(query => sql.unsafe(query)));
1059
1001
  return await InternalTable.EnvioInfo.write(sql, pgSchema, envioInfo);
@@ -1071,15 +1013,16 @@ function make(sql, pgHost, pgSchema, pgPort, pgUser, pgDatabase, pgPassword, isH
1071
1013
  });
1072
1014
  });
1073
1015
  if (ids.length !== 0) {
1016
+ let addrChainIdArrayType = Table.getPgFieldType("ChainId", pgSchema, true, false, false, chainIdMode);
1074
1017
  await sql.unsafe(`INSERT INTO "` + pgSchema + `"."` + Config.EnvioAddresses.table.tableName + `" ("id", "chain_id", "registration_block", "registration_log_index", "contract_name")
1075
- SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::text[]) AS t(id, chain_id, contract_name);`, [
1018
+ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::` + addrChainIdArrayType + `,$3::text[]) AS t(id, chain_id, contract_name);`, [
1076
1019
  ids,
1077
1020
  addrChainIds,
1078
1021
  addrContractNames
1079
1022
  ]);
1080
1023
  }
1081
1024
  let cache = await restoreEffectCache(true);
1082
- await reloadIndexRegistry();
1025
+ await reloadIndexCatalog();
1083
1026
  if (onInitialize !== undefined) {
1084
1027
  await onInitialize();
1085
1028
  }
@@ -1153,73 +1096,102 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
1153
1096
  filters.forEach(collect);
1154
1097
  return columns;
1155
1098
  };
1156
- let makeEnsureIndexQuery = schemaIndex => {
1157
- let indexName = IndexRegistry.truncateIndexName(schemaIndexDescription(schemaIndex));
1158
- let match = IndexRegistry.getInvalid(indexRegistry, indexName);
1159
- if (match === undefined) {
1160
- return makeCreateSchemaIndexQuery(schemaIndex, pgSchema);
1099
+ let runAndVerify = async (sql, prepared) => {
1100
+ for (let idx = 0, idx_finish = prepared.queries.length; idx < idx_finish; ++idx) {
1101
+ await sql.unsafe(prepared.queries[idx]);
1161
1102
  }
1162
- if (match.isRepairable) {
1163
- if (match.key === schemaIndexKey(schemaIndex)) {
1164
- return makeReindexQuery(pgSchema, indexName);
1165
- }
1166
- throw nameCollisionError(indexName, pgSchema);
1103
+ let rows = await loadCatalogRows(sql, prepared.name);
1104
+ return IndexManager.verifyOrThrow(prepared, rows, pgSchema);
1105
+ };
1106
+ let resyncIndex = async name => {
1107
+ let rows;
1108
+ try {
1109
+ rows = await loadCatalogRows(sql, name);
1110
+ } catch (raw_exn) {
1111
+ let exn = Primitive_exceptions.internalToException(raw_exn);
1112
+ return Logging.debug({
1113
+ storage: storageName,
1114
+ msg: `Could not re-read the index "` + name + `" after a failed build. The next attempt reads it again.`,
1115
+ err: Utils.prettifyExn(exn)
1116
+ });
1167
1117
  }
1168
- throw nameCollisionError(indexName, pgSchema);
1118
+ return IndexManager.resync(indexManager, name, rows);
1169
1119
  };
1170
- let isRepair = schemaIndex => Stdlib_Option.isSome(IndexRegistry.getInvalid(indexRegistry, IndexRegistry.truncateIndexName(schemaIndexDescription(schemaIndex))));
1171
1120
  let ensureQueryIndexes = async (table, filters) => {
1172
- let missing = Stdlib_Array.filterMap(filterColumns(table, filters), column => {
1173
- let schemaIndex = makeSingleColumnSchemaIndex(table.tableName, column);
1174
- if (IndexRegistry.has(indexRegistry, schemaIndexKey(schemaIndex))) {
1175
- return;
1176
- } else {
1177
- return schemaIndex;
1178
- }
1179
- });
1180
- if (Utils.$$Array.notEmpty(missing)) {
1181
- await Promise.all(missing.map(schemaIndex => {
1182
- let indexName = IndexRegistry.truncateIndexName(schemaIndexDescription(schemaIndex));
1183
- return IndexRegistry.ensure(indexRegistry, schemaIndexKey(schemaIndex), table.tableName, async () => {
1184
- let query = makeEnsureIndexQuery(schemaIndex);
1185
- let verb = isRepair(schemaIndex) ? "Repairing invalid index" : "Creating index";
1186
- Logging.info({
1187
- storage: storageName,
1188
- msg: verb + ` "` + indexName + `" to serve a getWhere query on "` + table.tableName + `". Writes to the table are paused until it completes. ` + slowOnLargeDatabaseNotice
1189
- });
1190
- let timeRef = Performance.now();
1191
- await sql.unsafe(query);
1192
- IndexRegistry.clearInvalidName(indexRegistry, indexName);
1193
- return Logging.info({
1194
- storage: storageName,
1195
- msg: `Index "` + indexName + `" is ready after ` + formatSeconds(timeRef) + `s. Resuming indexing.`
1196
- });
1197
- }).catch(exn => Logging.warn({
1121
+ let columns = filterColumns(table, filters);
1122
+ await Promise.all(columns.map(column => {
1123
+ let definition = IndexDefinition.single(table.tableName, column);
1124
+ return Stdlib_Promise.$$catch(IndexManager.ensure(indexManager, definition, "LeadingColumns", async () => {
1125
+ let prepared = IndexManager.prepare(indexManager, definition, "LeadingColumns", pgSchema);
1126
+ if (prepared === undefined) {
1127
+ return;
1128
+ }
1129
+ let verb = prepared.isRebuild ? "Rebuilding unusable index" : "Creating index";
1130
+ Logging.info({
1131
+ storage: storageName,
1132
+ msg: verb + ` "` + prepared.name + `" to serve a getWhere query on "` + table.tableName + `". Writes to the table are paused until it completes. ` + slowOnLargeDatabaseNotice
1133
+ });
1134
+ let timeRef = Performance.now();
1135
+ let entry = await runAndVerify(sql, prepared);
1136
+ IndexManager.record(indexManager, entry);
1137
+ return Logging.info({
1138
+ storage: storageName,
1139
+ msg: `Index "` + prepared.name + `" is ready after ` + formatSeconds(timeRef) + `s. Resuming indexing.`
1140
+ });
1141
+ }), async exn => {
1142
+ Logging.warn({
1198
1143
  storage: storageName,
1199
- msg: `Failed to create the index "` + indexName + `" for a getWhere query. The query runs without it.`,
1144
+ msg: `Failed to create an index on "` + table.tableName + `"("` + column + `") for a getWhere query. The query runs without it.`,
1200
1145
  err: Utils.prettifyExn(exn)
1201
- }));
1202
- }));
1203
- return;
1204
- }
1146
+ });
1147
+ return await resyncIndex(IndexDefinition.name(definition));
1148
+ });
1149
+ }));
1150
+ };
1151
+ let ensureSchemaIndexes = async entities => {
1152
+ let schemaIndexes = getSchemaIndexes(entities.filter(e => e.storage.postgres));
1153
+ await Promise.all(schemaIndexes.map(definition => Stdlib_Promise.$$catch(IndexManager.ensure(indexManager, definition, "Exact", async () => {
1154
+ let prepared = IndexManager.prepare(indexManager, definition, "Exact", pgSchema);
1155
+ if (prepared === undefined) {
1156
+ return;
1157
+ }
1158
+ let verb = prepared.isRebuild ? "Rebuilding unusable index" : "Creating missing index";
1159
+ Logging.info({
1160
+ storage: storageName,
1161
+ msg: verb + ` "` + prepared.name + `" the schema promises but the database no longer has. Writes to the table are paused until it completes. ` + slowOnLargeDatabaseNotice
1162
+ });
1163
+ let timeRef = Performance.now();
1164
+ let entry = await runAndVerify(sql, prepared);
1165
+ IndexManager.record(indexManager, entry);
1166
+ return Logging.info({
1167
+ storage: storageName,
1168
+ msg: `Index "` + prepared.name + `" is ready after ` + formatSeconds(timeRef) + `s.`
1169
+ });
1170
+ }), async exn => {
1171
+ Logging.warn({
1172
+ storage: storageName,
1173
+ msg: `Failed to restore the schema index "` + IndexDefinition.name(definition) + `". Queries relying on it run unindexed until the next restart.`,
1174
+ err: Utils.prettifyExn(exn)
1175
+ });
1176
+ return await resyncIndex(IndexDefinition.name(definition));
1177
+ })));
1205
1178
  };
1206
1179
  let finalizeBackfill = async (entities, chainIds, readyAt) => {
1207
1180
  let schemaIndexes = getSchemaIndexes(entities.filter(e => e.storage.postgres));
1208
- IndexRegistry.validateIndexNamesOrThrow(schemaIndexes.map(schemaIndexDescription));
1209
- let missing = schemaIndexes.filter(schemaIndex => !IndexRegistry.has(indexRegistry, schemaIndexKey(schemaIndex)));
1210
- let repaired = missing.filter(isRepair);
1211
- if (Utils.$$Array.notEmpty(repaired)) {
1181
+ let missing = Stdlib_Array.filterMap(schemaIndexes, definition => IndexManager.prepare(indexManager, definition, "Exact", pgSchema));
1182
+ let rebuilt = missing.filter(prepared => prepared.isRebuild);
1183
+ if (rebuilt.length !== 0) {
1212
1184
  Logging.warn({
1213
1185
  storage: storageName,
1214
- msg: `PostgreSQL reports ` + repaired.length.toString() + ` existing indexes as invalid, so they can't serve queries. Rebuilding them.`,
1215
- indexes: repaired.map(schemaIndexName)
1186
+ msg: `PostgreSQL reports ` + rebuilt.length.toString() + ` of the indexer's own indexes as invalid, so they can't serve queries. Rebuilding them.`,
1187
+ indexes: rebuilt.map(prepared => prepared.name)
1216
1188
  });
1217
1189
  }
1218
1190
  if (missing.length !== 0) {
1219
1191
  Logging.info({
1220
1192
  storage: storageName,
1221
1193
  msg: `Creating the ` + missing.length.toString() + ` remaining schema indexes before the indexer reports ready. Writes are paused until they are committed. ` + slowOnLargeDatabaseNotice,
1222
- indexes: missing.map(schemaIndexName)
1194
+ indexes: missing.map(prepared => prepared.name)
1223
1195
  });
1224
1196
  } else {
1225
1197
  Logging.info({
@@ -1227,28 +1199,40 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
1227
1199
  msg: `All ` + schemaIndexes.length.toString() + ` schema indexes are already in place. Marking the indexer ready.`
1228
1200
  });
1229
1201
  }
1230
- let indexQueries = missing.map(makeEnsureIndexQuery);
1231
1202
  let timeRef = Performance.now();
1203
+ for (let idx = 0, idx_finish = missing.length; idx < idx_finish; ++idx) {
1204
+ let prepared = missing[idx];
1205
+ let exit = 0;
1206
+ let entry;
1207
+ try {
1208
+ entry = await runAndVerify(sql, prepared);
1209
+ exit = 1;
1210
+ } catch (exn) {
1211
+ await resyncIndex(prepared.name);
1212
+ throw exn;
1213
+ }
1214
+ if (exit === 1) {
1215
+ IndexManager.record(indexManager, entry);
1216
+ }
1217
+ }
1218
+ let setReadyAtQuery = InternalTable.Chains.makeSetReadyAtQuery(pgSchema);
1232
1219
  await sql.begin(async sql => {
1233
- for (let idx = 0, idx_finish = indexQueries.length; idx < idx_finish; ++idx) {
1234
- await sql.unsafe(indexQueries[idx]);
1220
+ for (let idx = 0, idx_finish = chainIds.length; idx < idx_finish; ++idx) {
1221
+ await sql.unsafe(setReadyAtQuery, [
1222
+ readyAt,
1223
+ chainIds[idx]
1224
+ ], {prepare: true});
1235
1225
  }
1236
- return await sql.unsafe(InternalTable.Chains.makeSetReadyAtQuery(pgSchema), [
1237
- readyAt,
1238
- chainIds
1239
- ], {prepare: true});
1240
1226
  });
1241
- missing.forEach(schemaIndex => IndexRegistry.add(indexRegistry, schemaIndexKey(schemaIndex)));
1242
- repaired.forEach(schemaIndex => IndexRegistry.clearInvalidName(indexRegistry, IndexRegistry.truncateIndexName(schemaIndexDescription(schemaIndex))));
1243
1227
  return Logging.info({
1244
1228
  storage: storageName,
1245
1229
  msg: `Committed ` + missing.length.toString() + ` schema indexes and the ready timestamp in ` + formatSeconds(timeRef) + `s.`
1246
1230
  });
1247
1231
  };
1248
- let setOrThrow$1 = (items, table, itemSchema) => setOrThrow(sql, items, table, itemSchema, pgSchema);
1232
+ let setOrThrow$1 = (items, table, itemSchema) => setOrThrow(sql, items, table, itemSchema, pgSchema, undefined);
1249
1233
  let setEffectCacheOrThrow = async (table, itemSchema, items, initialize) => {
1250
1234
  if (initialize) {
1251
- await sql.unsafe(makeCreateTableQuery(table, pgSchema, false));
1235
+ await sql.unsafe(makeCreateTableQuery(table, pgSchema, false, undefined));
1252
1236
  if (onNewTables !== undefined) {
1253
1237
  await onNewTables([table.tableName]);
1254
1238
  }
@@ -1321,11 +1305,11 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
1321
1305
  sql.unsafe(InternalTable.Checkpoints.makeGetReorgCheckpointsQuery(pgSchema)),
1322
1306
  InternalTable.EnvioInfo.read(sql, pgSchema)
1323
1307
  ]);
1324
- await reloadIndexRegistry();
1308
+ await reloadIndexCatalog();
1325
1309
  let checkpointId = BigInt(match[2][0].id);
1326
1310
  let reorgCheckpoints = match[3].map(raw => ({
1327
1311
  id: BigInt(raw.id),
1328
- chain_id: raw.chain_id,
1312
+ chain_id: ChainId.normalizeOrThrow(raw.chain_id),
1329
1313
  block_number: raw.block_number,
1330
1314
  block_hash: raw.block_hash
1331
1315
  }));
@@ -1404,6 +1388,7 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
1404
1388
  resumeInitialState: resumeInitialState,
1405
1389
  loadOrThrow: loadOrThrow,
1406
1390
  ensureQueryIndexes: ensureQueryIndexes,
1391
+ ensureSchemaIndexes: ensureSchemaIndexes,
1407
1392
  finalizeBackfill: finalizeBackfill,
1408
1393
  dumpEffectCache: dumpEffectCache,
1409
1394
  reset: reset,
@@ -1444,11 +1429,11 @@ function makeStorageFromEnv(config, sqlOpt, pgSchemaOpt, isHasuraEnabledOpt) {
1444
1429
  if (missing.length !== 0) {
1445
1430
  Stdlib_JsError.throwWithMessage(`ClickHouse storage is enabled but required env vars are not set: ` + missing.join(", ") + `. Please set them, disable clickhouse in the \`storage\` config, or run \`envio dev\` for a pre-configured local ClickHouse.`);
1446
1431
  }
1447
- tmp = Sink.makeClickHouse(host, database, username, password);
1432
+ tmp = Sink.makeClickHouse(host, database, username, password, config.chainIdMode);
1448
1433
  } else {
1449
1434
  tmp = undefined;
1450
1435
  }
1451
- return make(sql, Env.Db.host, pgSchema, Env.Db.port, Env.Db.user, Env.Db.database, Env.Db.password, isHasuraEnabled, tmp, isHasuraEnabled ? () => Stdlib_Promise.$$catch(Hasura.trackDatabase(Env.Hasura.graphqlEndpoint, {
1436
+ return make(sql, Env.Db.host, pgSchema, Env.Db.port, Env.Db.user, Env.Db.database, Env.Db.password, isHasuraEnabled, config.chainIdMode, tmp, isHasuraEnabled ? () => Stdlib_Promise.$$catch(Hasura.trackDatabase(Env.Hasura.graphqlEndpoint, {
1452
1437
  role: Env.Hasura.role,
1453
1438
  secret: Env.Hasura.secret
1454
1439
  }, pgSchema, Config.getPgUserEntities(config), Env.Hasura.aggregateEntities, Env.Hasura.responseLimit, Schema.make(config.allEntities.map(e => e.table))), err => Promise.resolve(Logging.errorWithExn(Utils.prettifyExn(err), `Error tracking tables`))) : undefined, isHasuraEnabled ? tableNames => Stdlib_Promise.$$catch(Hasura.trackTables(Env.Hasura.graphqlEndpoint, {
@@ -1470,20 +1455,8 @@ let maxItemsPerQuery = 500;
1470
1455
 
1471
1456
  export {
1472
1457
  makeClient,
1473
- makeCreateIndexQuery,
1474
- directionToSql,
1475
- directionToIndexName,
1476
- makeCreateCompositeIndexQuery,
1477
- makeCreateTableIndexesQuery,
1478
- schemaIndexDescription,
1479
- schemaIndexName,
1480
- schemaIndexKey,
1481
- makeCreateSchemaIndexQuery,
1482
1458
  formatSeconds,
1483
1459
  slowOnLargeDatabaseNotice,
1484
- makeReindexQuery,
1485
- nameCollisionError,
1486
- makeSingleColumnSchemaIndex,
1487
1460
  getSchemaIndexes,
1488
1461
  makeCreateTableQuery,
1489
1462
  entityHistoryCache,