envio 2.27.6 → 2.28.0-alpha.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 +5 -5
- package/rescript.json +3 -0
- package/src/Hasura.res +135 -12
- package/src/Hasura.res.js +95 -13
- package/src/Internal.res +7 -4
- package/src/InternalConfig.res +20 -0
- package/src/InternalConfig.res.js +2 -0
- package/src/Js.shim.ts +11 -0
- package/src/LoadManager.res +12 -6
- package/src/LoadManager.res.js +13 -6
- package/src/Persistence.res +25 -33
- package/src/Persistence.res.js +18 -20
- package/src/PgStorage.res +155 -101
- package/src/PgStorage.res.js +141 -100
- package/src/Prometheus.res +2 -2
- package/src/Prometheus.res.js +2 -3
- package/src/bindings/Pino.res +1 -1
- package/src/bindings/Pino.res.js +2 -1
- package/src/db/EntityHistory.res +18 -17
- package/src/db/EntityHistory.res.js +28 -26
- package/src/db/InternalTable.gen.ts +43 -0
- package/src/db/InternalTable.res +392 -0
- package/src/db/InternalTable.res.js +295 -0
- package/src/vendored/Rest.res +11 -2
- package/src/vendored/Rest.res.js +44 -35
package/src/PgStorage.res.js
CHANGED
|
@@ -16,6 +16,7 @@ var Belt_Array = require("rescript/lib/js/belt_Array.js");
|
|
|
16
16
|
var Belt_Option = require("rescript/lib/js/belt_Option.js");
|
|
17
17
|
var Caml_option = require("rescript/lib/js/caml_option.js");
|
|
18
18
|
var Persistence = require("./Persistence.res.js");
|
|
19
|
+
var InternalTable = require("./db/InternalTable.res.js");
|
|
19
20
|
var Child_process = require("child_process");
|
|
20
21
|
var Caml_exceptions = require("rescript/lib/js/caml_exceptions.js");
|
|
21
22
|
var S$RescriptSchema = require("rescript-schema/src/S.res.js");
|
|
@@ -68,11 +69,18 @@ function makeCreateTableQuery(table, pgSchema) {
|
|
|
68
69
|
) + ");";
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
function makeInitializeTransaction(pgSchema, pgUser,
|
|
72
|
-
var
|
|
72
|
+
function makeInitializeTransaction(pgSchema, pgUser, chainConfigsOpt, entitiesOpt, enumsOpt, isEmptyPgSchemaOpt) {
|
|
73
|
+
var chainConfigs = chainConfigsOpt !== undefined ? chainConfigsOpt : [];
|
|
73
74
|
var entities = entitiesOpt !== undefined ? entitiesOpt : [];
|
|
74
75
|
var enums = enumsOpt !== undefined ? enumsOpt : [];
|
|
75
76
|
var isEmptyPgSchema = isEmptyPgSchemaOpt !== undefined ? isEmptyPgSchemaOpt : false;
|
|
77
|
+
var generalTables = [
|
|
78
|
+
InternalTable.EventSyncState.table,
|
|
79
|
+
InternalTable.Chains.table,
|
|
80
|
+
InternalTable.PersistedState.table,
|
|
81
|
+
InternalTable.EndOfBlockRangeScannedData.table,
|
|
82
|
+
InternalTable.RawEvents.table
|
|
83
|
+
];
|
|
76
84
|
var allTables = $$Array.copy(generalTables);
|
|
77
85
|
var allEntityTables = [];
|
|
78
86
|
entities.forEach(function (entity) {
|
|
@@ -107,12 +115,16 @@ function makeInitializeTransaction(pgSchema, pgUser, generalTablesOpt, entitiesO
|
|
|
107
115
|
contents: ""
|
|
108
116
|
};
|
|
109
117
|
entities.forEach(function (entity) {
|
|
110
|
-
functionsQuery.contents = functionsQuery.contents + "\n" + entity.entityHistory.
|
|
118
|
+
functionsQuery.contents = functionsQuery.contents + "\n" + entity.entityHistory.makeInsertFnQuery(pgSchema);
|
|
111
119
|
Table.getDerivedFromFields(entity.table).forEach(function (derivedFromField) {
|
|
112
120
|
var indexField = Utils.unwrapResultExn(Schema.getDerivedFromFieldName(derivedSchema, derivedFromField));
|
|
113
121
|
query.contents = query.contents + "\n" + makeCreateIndexQuery(derivedFromField.derivedFromEntity, [indexField], pgSchema);
|
|
114
122
|
});
|
|
115
123
|
});
|
|
124
|
+
var initialChainsValuesQuery = InternalTable.Chains.makeInitialValuesQuery(pgSchema, chainConfigs);
|
|
125
|
+
if (initialChainsValuesQuery !== undefined) {
|
|
126
|
+
query.contents = query.contents + "\n" + initialChainsValuesQuery;
|
|
127
|
+
}
|
|
116
128
|
functionsQuery.contents = functionsQuery.contents + "\n" + ("CREATE OR REPLACE FUNCTION " + getCacheRowCountFnName + "(table_name text) \nRETURNS integer AS $$\nDECLARE\n result integer;\nBEGIN\n EXECUTE format('SELECT COUNT(*) FROM \"" + pgSchema + "\".%I', table_name) INTO result;\n RETURN result;\nEND;\n$$ LANGUAGE plpgsql;");
|
|
117
129
|
return [query.contents].concat(functionsQuery.contents !== "" ? [functionsQuery.contents] : []);
|
|
118
130
|
}
|
|
@@ -129,6 +141,10 @@ function makeLoadByIdsQuery(pgSchema, tableName) {
|
|
|
129
141
|
return "SELECT * FROM \"" + pgSchema + "\".\"" + tableName + "\" WHERE id = ANY($1::text[]);";
|
|
130
142
|
}
|
|
131
143
|
|
|
144
|
+
function makeLoadAllQuery(pgSchema, tableName) {
|
|
145
|
+
return "SELECT * FROM \"" + pgSchema + "\".\"" + tableName + "\";";
|
|
146
|
+
}
|
|
147
|
+
|
|
132
148
|
function makeInsertUnnestSetQuery(pgSchema, table, itemSchema, isRawEvents) {
|
|
133
149
|
var match = Table.toSqlParams(table, itemSchema, pgSchema);
|
|
134
150
|
var quotedNonPrimaryFieldNames = match.quotedNonPrimaryFieldNames;
|
|
@@ -177,13 +193,9 @@ function makeInsertValuesSetQuery(pgSchema, table, itemSchema, itemsCount) {
|
|
|
177
193
|
) + ";";
|
|
178
194
|
}
|
|
179
195
|
|
|
180
|
-
var rawEventsTableName = "raw_events";
|
|
181
|
-
|
|
182
|
-
var eventSyncStateTableName = "event_sync_state";
|
|
183
|
-
|
|
184
196
|
function makeTableBatchSetQuery(pgSchema, table, itemSchema) {
|
|
185
197
|
var match = Table.toSqlParams(table, itemSchema, pgSchema);
|
|
186
|
-
var isRawEvents = table.tableName ===
|
|
198
|
+
var isRawEvents = table.tableName === InternalTable.RawEvents.table.tableName;
|
|
187
199
|
if (isRawEvents || !match.hasArrayField) {
|
|
188
200
|
return {
|
|
189
201
|
query: makeInsertUnnestSetQuery(pgSchema, table, itemSchema, isRawEvents),
|
|
@@ -285,13 +297,24 @@ async function setOrThrow(sql, items, table, itemSchema, pgSchema) {
|
|
|
285
297
|
|
|
286
298
|
function setEntityHistoryOrThrow(sql, entityHistory, rows, shouldCopyCurrentEntity, shouldRemoveInvalidUtf8Opt) {
|
|
287
299
|
var shouldRemoveInvalidUtf8 = shouldRemoveInvalidUtf8Opt !== undefined ? shouldRemoveInvalidUtf8Opt : false;
|
|
288
|
-
return
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
300
|
+
return Belt_Array.map(rows, (function (historyRow) {
|
|
301
|
+
var row = S$RescriptSchema.reverseConvertToJsonOrThrow(historyRow, entityHistory.schema);
|
|
302
|
+
if (shouldRemoveInvalidUtf8) {
|
|
303
|
+
removeInvalidUtf8InPlace([row]);
|
|
304
|
+
}
|
|
305
|
+
return $$Promise.$$catch(entityHistory.insertFn(sql, row, shouldCopyCurrentEntity !== undefined ? shouldCopyCurrentEntity : !Belt_Option.getWithDefault(historyRow.containsRollbackDiffChange, false)), (function (exn) {
|
|
306
|
+
var reason = Utils.prettifyExn(exn);
|
|
307
|
+
var detail = (reason?.detail || "");
|
|
308
|
+
throw {
|
|
309
|
+
RE_EXN_ID: Persistence.StorageError,
|
|
310
|
+
message: "Failed to insert history item into table \"" + entityHistory.table.tableName + "\"." + (
|
|
311
|
+
detail !== "" ? " Details: " + detail : ""
|
|
312
|
+
),
|
|
313
|
+
reason: reason,
|
|
314
|
+
Error: new Error()
|
|
315
|
+
};
|
|
316
|
+
}));
|
|
317
|
+
}));
|
|
295
318
|
}
|
|
296
319
|
|
|
297
320
|
function makeSchemaTableNamesQuery(pgSchema) {
|
|
@@ -370,29 +393,112 @@ function make(sql, pgHost, pgSchema, pgPort, pgUser, pgDatabase, pgPassword, onI
|
|
|
370
393
|
};
|
|
371
394
|
var cacheDirPath = Path.resolve("..", ".envio", "cache");
|
|
372
395
|
var isInitialized = async function () {
|
|
373
|
-
var envioTables = await sql.unsafe("SELECT table_schema FROM information_schema.tables WHERE table_schema = '" + pgSchema + "' AND table_name = '" +
|
|
396
|
+
var envioTables = await sql.unsafe("SELECT table_schema FROM information_schema.tables WHERE table_schema = '" + pgSchema + "' AND table_name = '" + InternalTable.EventSyncState.table.tableName + "' OR table_name = '" + InternalTable.Chains.table.tableName + "';");
|
|
374
397
|
return Utils.$$Array.notEmpty(envioTables);
|
|
375
398
|
};
|
|
376
|
-
var
|
|
399
|
+
var restoreEffectCache = async function (withUpload) {
|
|
400
|
+
if (withUpload) {
|
|
401
|
+
var nothingToUploadErrorMessage = "Nothing to upload.";
|
|
402
|
+
var match = await Promise.all([
|
|
403
|
+
$$Promise.$$catch(Fs.promises.readdir(cacheDirPath).then(function (e) {
|
|
404
|
+
return {
|
|
405
|
+
TAG: "Ok",
|
|
406
|
+
_0: e
|
|
407
|
+
};
|
|
408
|
+
}), (function (param) {
|
|
409
|
+
return Promise.resolve({
|
|
410
|
+
TAG: "Error",
|
|
411
|
+
_0: nothingToUploadErrorMessage
|
|
412
|
+
});
|
|
413
|
+
})),
|
|
414
|
+
getConnectedPsqlExec(pgUser, pgHost, pgDatabase, pgPort)
|
|
415
|
+
]);
|
|
416
|
+
var exit = 0;
|
|
417
|
+
var message;
|
|
418
|
+
var entries = match[0];
|
|
419
|
+
if (entries.TAG === "Ok") {
|
|
420
|
+
var psqlExec = match[1];
|
|
421
|
+
if (psqlExec.TAG === "Ok") {
|
|
422
|
+
var psqlExec$1 = psqlExec._0;
|
|
423
|
+
var cacheFiles = entries._0.filter(function (entry) {
|
|
424
|
+
return entry.endsWith(".tsv");
|
|
425
|
+
});
|
|
426
|
+
await Promise.all(cacheFiles.map(function (entry) {
|
|
427
|
+
var effectName = entry.slice(0, -4);
|
|
428
|
+
var table = Internal.makeCacheTable(effectName);
|
|
429
|
+
return sql.unsafe(makeCreateTableQuery(table, pgSchema)).then(function () {
|
|
430
|
+
var inputFile = Path.join(cacheDirPath, entry);
|
|
431
|
+
var command = psqlExec$1 + " -c 'COPY \"" + pgSchema + "\".\"" + table.tableName + "\" FROM STDIN WITH (FORMAT text, HEADER);' < " + inputFile;
|
|
432
|
+
return new Promise((function (resolve, reject) {
|
|
433
|
+
Child_process.exec(command, psqlExecOptions, (function (error, stdout, param) {
|
|
434
|
+
if (error === null) {
|
|
435
|
+
return resolve(stdout);
|
|
436
|
+
} else {
|
|
437
|
+
return reject(error);
|
|
438
|
+
}
|
|
439
|
+
}));
|
|
440
|
+
}));
|
|
441
|
+
});
|
|
442
|
+
}));
|
|
443
|
+
Logging.info("Successfully uploaded cache.");
|
|
444
|
+
} else {
|
|
445
|
+
message = match[1]._0;
|
|
446
|
+
exit = 1;
|
|
447
|
+
}
|
|
448
|
+
} else {
|
|
449
|
+
message = entries._0;
|
|
450
|
+
exit = 1;
|
|
451
|
+
}
|
|
452
|
+
if (exit === 1) {
|
|
453
|
+
if (message === nothingToUploadErrorMessage) {
|
|
454
|
+
Logging.info("No cache found to upload.");
|
|
455
|
+
} else {
|
|
456
|
+
Logging.error("Failed to upload cache, continuing without it. " + message);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
}
|
|
461
|
+
var cacheTableInfo = await sql.unsafe(makeSchemaCacheTableInfoQuery(pgSchema));
|
|
462
|
+
if (withUpload && Utils.$$Array.notEmpty(cacheTableInfo) && onNewTables !== undefined) {
|
|
463
|
+
await onNewTables(cacheTableInfo.map(function (info) {
|
|
464
|
+
return info.table_name;
|
|
465
|
+
}));
|
|
466
|
+
}
|
|
467
|
+
var cache = {};
|
|
468
|
+
cacheTableInfo.forEach(function (param) {
|
|
469
|
+
var effectName = param.table_name.slice(cacheTablePrefixLength);
|
|
470
|
+
cache[effectName] = {
|
|
471
|
+
effectName: effectName,
|
|
472
|
+
count: param.count
|
|
473
|
+
};
|
|
474
|
+
});
|
|
475
|
+
return cache;
|
|
476
|
+
};
|
|
477
|
+
var initialize = async function (chainConfigsOpt, entitiesOpt, enumsOpt) {
|
|
478
|
+
var chainConfigs = chainConfigsOpt !== undefined ? chainConfigsOpt : [];
|
|
377
479
|
var entities = entitiesOpt !== undefined ? entitiesOpt : [];
|
|
378
|
-
var generalTables = generalTablesOpt !== undefined ? generalTablesOpt : [];
|
|
379
480
|
var enums = enumsOpt !== undefined ? enumsOpt : [];
|
|
380
481
|
var schemaTableNames = await sql.unsafe(makeSchemaTableNamesQuery(pgSchema));
|
|
381
482
|
if (Utils.$$Array.notEmpty(schemaTableNames) && !schemaTableNames.some(function (table) {
|
|
382
|
-
return table.table_name ===
|
|
483
|
+
return table.table_name === InternalTable.EventSyncState.table.tableName;
|
|
383
484
|
})) {
|
|
384
485
|
Js_exn.raiseError("Cannot run Envio migrations on PostgreSQL schema \"" + pgSchema + "\" because it contains non-Envio tables. Running migrations would delete all data in this schema.\n\nTo resolve this:\n1. If you want to use this schema, first backup any important data, then drop it with: \"pnpm envio local db-migrate down\"\n2. Or specify a different schema name by setting the \"ENVIO_PG_PUBLIC_SCHEMA\" environment variable\n3. Or manually drop the schema in your database if you're certain the data is not needed.");
|
|
385
486
|
}
|
|
386
|
-
var queries = makeInitializeTransaction(pgSchema, pgUser,
|
|
487
|
+
var queries = makeInitializeTransaction(pgSchema, pgUser, chainConfigs, entities, enums, Utils.$$Array.isEmpty(schemaTableNames));
|
|
387
488
|
await sql.begin(function (sql) {
|
|
388
489
|
return queries.map(function (query) {
|
|
389
490
|
return sql.unsafe(query);
|
|
390
491
|
});
|
|
391
492
|
});
|
|
493
|
+
var cache = await restoreEffectCache(true);
|
|
392
494
|
if (onInitialize !== undefined) {
|
|
393
|
-
|
|
495
|
+
await onInitialize();
|
|
394
496
|
}
|
|
395
|
-
|
|
497
|
+
return {
|
|
498
|
+
cleanRun: true,
|
|
499
|
+
cache: cache,
|
|
500
|
+
chains: chainConfigs.map(InternalTable.Chains.initialFromConfig)
|
|
501
|
+
};
|
|
396
502
|
};
|
|
397
503
|
var loadByIdsOrThrow = async function (ids, table, rowsSchema) {
|
|
398
504
|
var rows;
|
|
@@ -526,90 +632,26 @@ function make(sql, pgHost, pgSchema, pgPort, pgUser, pgDatabase, pgPassword, onI
|
|
|
526
632
|
return Logging.errorWithExn(Utils.prettifyExn(exn$1), "Failed to dump cache.");
|
|
527
633
|
}
|
|
528
634
|
};
|
|
529
|
-
var
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
return Promise.resolve({
|
|
540
|
-
TAG: "Error",
|
|
541
|
-
_0: nothingToUploadErrorMessage
|
|
542
|
-
});
|
|
543
|
-
})),
|
|
544
|
-
getConnectedPsqlExec(pgUser, pgHost, pgDatabase, pgPort)
|
|
545
|
-
]);
|
|
546
|
-
var exit = 0;
|
|
547
|
-
var message;
|
|
548
|
-
var entries = match[0];
|
|
549
|
-
if (entries.TAG === "Ok") {
|
|
550
|
-
var psqlExec = match[1];
|
|
551
|
-
if (psqlExec.TAG === "Ok") {
|
|
552
|
-
var psqlExec$1 = psqlExec._0;
|
|
553
|
-
var cacheFiles = entries._0.filter(function (entry) {
|
|
554
|
-
return entry.endsWith(".tsv");
|
|
555
|
-
});
|
|
556
|
-
await Promise.all(cacheFiles.map(function (entry) {
|
|
557
|
-
var effectName = entry.slice(0, -4);
|
|
558
|
-
var table = Internal.makeCacheTable(effectName);
|
|
559
|
-
return sql.unsafe(makeCreateTableQuery(table, pgSchema)).then(function () {
|
|
560
|
-
var inputFile = Path.join(cacheDirPath, entry);
|
|
561
|
-
var command = psqlExec$1 + " -c 'COPY \"" + pgSchema + "\".\"" + table.tableName + "\" FROM STDIN WITH (FORMAT text, HEADER);' < " + inputFile;
|
|
562
|
-
return new Promise((function (resolve, reject) {
|
|
563
|
-
Child_process.exec(command, psqlExecOptions, (function (error, stdout, param) {
|
|
564
|
-
if (error === null) {
|
|
565
|
-
return resolve(stdout);
|
|
566
|
-
} else {
|
|
567
|
-
return reject(error);
|
|
568
|
-
}
|
|
569
|
-
}));
|
|
570
|
-
}));
|
|
571
|
-
});
|
|
572
|
-
}));
|
|
573
|
-
Logging.info("Successfully uploaded cache.");
|
|
574
|
-
} else {
|
|
575
|
-
message = match[1]._0;
|
|
576
|
-
exit = 1;
|
|
577
|
-
}
|
|
578
|
-
} else {
|
|
579
|
-
message = entries._0;
|
|
580
|
-
exit = 1;
|
|
581
|
-
}
|
|
582
|
-
if (exit === 1) {
|
|
583
|
-
if (message === nothingToUploadErrorMessage) {
|
|
584
|
-
Logging.info("No cache found to upload.");
|
|
585
|
-
} else {
|
|
586
|
-
Logging.error("Failed to upload cache, continuing without it. " + message);
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
}
|
|
591
|
-
var cacheTableInfo = await sql.unsafe(makeSchemaCacheTableInfoQuery(pgSchema));
|
|
592
|
-
if (withUpload && Utils.$$Array.notEmpty(cacheTableInfo) && onNewTables !== undefined) {
|
|
593
|
-
await onNewTables(cacheTableInfo.map(function (info) {
|
|
594
|
-
return info.table_name;
|
|
595
|
-
}));
|
|
596
|
-
}
|
|
597
|
-
return cacheTableInfo.map(function (info) {
|
|
598
|
-
return {
|
|
599
|
-
effectName: info.table_name.slice(cacheTablePrefixLength),
|
|
600
|
-
count: info.count
|
|
601
|
-
};
|
|
602
|
-
});
|
|
635
|
+
var loadInitialState = async function () {
|
|
636
|
+
var match = await Promise.all([
|
|
637
|
+
restoreEffectCache(false),
|
|
638
|
+
sql.unsafe(makeLoadAllQuery(pgSchema, InternalTable.Chains.table.tableName))
|
|
639
|
+
]);
|
|
640
|
+
return {
|
|
641
|
+
cleanRun: false,
|
|
642
|
+
cache: match[0],
|
|
643
|
+
chains: match[1]
|
|
644
|
+
};
|
|
603
645
|
};
|
|
604
646
|
return {
|
|
605
647
|
isInitialized: isInitialized,
|
|
606
648
|
initialize: initialize,
|
|
649
|
+
loadInitialState: loadInitialState,
|
|
607
650
|
loadByIdsOrThrow: loadByIdsOrThrow,
|
|
608
651
|
loadByFieldOrThrow: loadByFieldOrThrow,
|
|
609
652
|
setOrThrow: setOrThrow$1,
|
|
610
653
|
setEffectCacheOrThrow: setEffectCacheOrThrow,
|
|
611
|
-
dumpEffectCache: dumpEffectCache
|
|
612
|
-
restoreEffectCache: restoreEffectCache
|
|
654
|
+
dumpEffectCache: dumpEffectCache
|
|
613
655
|
};
|
|
614
656
|
}
|
|
615
657
|
|
|
@@ -623,10 +665,9 @@ exports.makeInitializeTransaction = makeInitializeTransaction;
|
|
|
623
665
|
exports.makeLoadByIdQuery = makeLoadByIdQuery;
|
|
624
666
|
exports.makeLoadByFieldQuery = makeLoadByFieldQuery;
|
|
625
667
|
exports.makeLoadByIdsQuery = makeLoadByIdsQuery;
|
|
668
|
+
exports.makeLoadAllQuery = makeLoadAllQuery;
|
|
626
669
|
exports.makeInsertUnnestSetQuery = makeInsertUnnestSetQuery;
|
|
627
670
|
exports.makeInsertValuesSetQuery = makeInsertValuesSetQuery;
|
|
628
|
-
exports.rawEventsTableName = rawEventsTableName;
|
|
629
|
-
exports.eventSyncStateTableName = eventSyncStateTableName;
|
|
630
671
|
exports.maxItemsPerQuery = maxItemsPerQuery;
|
|
631
672
|
exports.makeTableBatchSetQuery = makeTableBatchSetQuery;
|
|
632
673
|
exports.chunkArray = chunkArray;
|
package/src/Prometheus.res
CHANGED
|
@@ -213,9 +213,9 @@ let incrementExecuteBatchDurationCounter = (~duration) => {
|
|
|
213
213
|
executeBatchDurationCounter->PromClient.Counter.incMany(duration)
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
let setSourceChainHeight = (~blockNumber, ~
|
|
216
|
+
let setSourceChainHeight = (~blockNumber, ~chainId) => {
|
|
217
217
|
sourceChainHeight
|
|
218
|
-
->PromClient.Gauge.labels({"chainId":
|
|
218
|
+
->PromClient.Gauge.labels({"chainId": chainId})
|
|
219
219
|
->PromClient.Gauge.set(blockNumber)
|
|
220
220
|
}
|
|
221
221
|
|
package/src/Prometheus.res.js
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
var Utils = require("./Utils.res.js");
|
|
5
5
|
var Hrtime = require("./bindings/Hrtime.res.js");
|
|
6
6
|
var Js_exn = require("rescript/lib/js/js_exn.js");
|
|
7
|
-
var ChainMap = require("./ChainMap.res.js");
|
|
8
7
|
var Belt_Array = require("rescript/lib/js/belt_Array.js");
|
|
9
8
|
var Belt_Result = require("rescript/lib/js/belt_Result.js");
|
|
10
9
|
var PromClient = require("prom-client");
|
|
@@ -315,9 +314,9 @@ function incrementExecuteBatchDurationCounter(duration) {
|
|
|
315
314
|
executeBatchDurationCounter.inc(duration);
|
|
316
315
|
}
|
|
317
316
|
|
|
318
|
-
function setSourceChainHeight(blockNumber,
|
|
317
|
+
function setSourceChainHeight(blockNumber, chainId) {
|
|
319
318
|
sourceChainHeight.labels({
|
|
320
|
-
chainId:
|
|
319
|
+
chainId: chainId
|
|
321
320
|
}).set(blockNumber);
|
|
322
321
|
}
|
|
323
322
|
|
package/src/bindings/Pino.res
CHANGED
package/src/bindings/Pino.res.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var Pino = require("pino");
|
|
5
|
+
var Utils = require("../Utils.res.js");
|
|
5
6
|
var Caml_obj = require("rescript/lib/js/caml_obj.js");
|
|
6
7
|
var Belt_Array = require("rescript/lib/js/belt_Array.js");
|
|
7
8
|
var Belt_Option = require("rescript/lib/js/belt_Option.js");
|
|
@@ -14,7 +15,7 @@ function createPinoMessage(message) {
|
|
|
14
15
|
function createPinoMessageWithError(message, err) {
|
|
15
16
|
return {
|
|
16
17
|
msg: message,
|
|
17
|
-
err: err
|
|
18
|
+
err: Utils.prettifyExn(err)
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
21
|
|
package/src/db/EntityHistory.res
CHANGED
|
@@ -141,7 +141,7 @@ let makeHistoryRowSchema: S.t<'entity> => S.t<historyRow<'entity>> = entitySchem
|
|
|
141
141
|
|
|
142
142
|
type t<'entity> = {
|
|
143
143
|
table: table,
|
|
144
|
-
|
|
144
|
+
makeInsertFnQuery: (~pgSchema: string) => string,
|
|
145
145
|
schema: S.t<historyRow<'entity>>,
|
|
146
146
|
// Used for parsing
|
|
147
147
|
schemaRows: S.t<array<historyRow<'entity>>>,
|
|
@@ -153,7 +153,7 @@ type entityInternal
|
|
|
153
153
|
external castInternal: t<'entity> => t<entityInternal> = "%identity"
|
|
154
154
|
external eval: string => 'a = "eval"
|
|
155
155
|
|
|
156
|
-
let fromTable = (table: table, ~
|
|
156
|
+
let fromTable = (table: table, ~schema: S.t<'entity>): t<'entity> => {
|
|
157
157
|
let entity_history_block_timestamp = "entity_history_block_timestamp"
|
|
158
158
|
let entity_history_chain_id = "entity_history_chain_id"
|
|
159
159
|
let entity_history_block_number = "entity_history_block_number"
|
|
@@ -227,19 +227,6 @@ let fromTable = (table: table, ~pgSchema, ~schema: S.t<'entity>): t<'entity> =>
|
|
|
227
227
|
)
|
|
228
228
|
|
|
229
229
|
let insertFnName = `"insert_${table.tableName}"`
|
|
230
|
-
let historyRowArg = "history_row"
|
|
231
|
-
let historyTablePath = `"${pgSchema}"."${historyTableName}"`
|
|
232
|
-
let originTablePath = `"${pgSchema}"."${originTableName}"`
|
|
233
|
-
|
|
234
|
-
let previousHistoryFieldsAreNullStr =
|
|
235
|
-
previousChangeFieldNames
|
|
236
|
-
->Belt.Array.map(fieldName => `${historyRowArg}.${fieldName} IS NULL`)
|
|
237
|
-
->Js.Array2.joinWith(" OR ")
|
|
238
|
-
|
|
239
|
-
let currentChangeFieldNamesCommaSeparated = currentChangeFieldNames->Js.Array2.joinWith(", ")
|
|
240
|
-
|
|
241
|
-
let dataFieldNamesDoubleQuoted = dataFieldNames->Belt.Array.map(fieldName => `"${fieldName}"`)
|
|
242
|
-
let dataFieldNamesCommaSeparated = dataFieldNamesDoubleQuoted->Js.Array2.joinWith(", ")
|
|
243
230
|
|
|
244
231
|
let allFieldNamesDoubleQuoted =
|
|
245
232
|
Belt.Array.concatMany([
|
|
@@ -249,7 +236,21 @@ let fromTable = (table: table, ~pgSchema, ~schema: S.t<'entity>): t<'entity> =>
|
|
|
249
236
|
[actionFieldName],
|
|
250
237
|
])->Belt.Array.map(fieldName => `"${fieldName}"`)
|
|
251
238
|
|
|
252
|
-
let
|
|
239
|
+
let makeInsertFnQuery = (~pgSchema) => {
|
|
240
|
+
let historyRowArg = "history_row"
|
|
241
|
+
let historyTablePath = `"${pgSchema}"."${historyTableName}"`
|
|
242
|
+
let originTablePath = `"${pgSchema}"."${originTableName}"`
|
|
243
|
+
|
|
244
|
+
let previousHistoryFieldsAreNullStr =
|
|
245
|
+
previousChangeFieldNames
|
|
246
|
+
->Belt.Array.map(fieldName => `${historyRowArg}.${fieldName} IS NULL`)
|
|
247
|
+
->Js.Array2.joinWith(" OR ")
|
|
248
|
+
|
|
249
|
+
let currentChangeFieldNamesCommaSeparated = currentChangeFieldNames->Js.Array2.joinWith(", ")
|
|
250
|
+
|
|
251
|
+
let dataFieldNamesDoubleQuoted = dataFieldNames->Belt.Array.map(fieldName => `"${fieldName}"`)
|
|
252
|
+
let dataFieldNamesCommaSeparated = dataFieldNamesDoubleQuoted->Js.Array2.joinWith(", ")
|
|
253
|
+
|
|
253
254
|
`CREATE OR REPLACE FUNCTION ${insertFnName}(${historyRowArg} ${historyTablePath}, should_copy_current_entity BOOLEAN)
|
|
254
255
|
RETURNS void AS $$
|
|
255
256
|
DECLARE
|
|
@@ -315,7 +316,7 @@ $$ LANGUAGE plpgsql;`
|
|
|
315
316
|
|
|
316
317
|
let schema = makeHistoryRowSchema(schema)
|
|
317
318
|
|
|
318
|
-
{table,
|
|
319
|
+
{table, makeInsertFnQuery, schema, schemaRows: S.array(schema), insertFn}
|
|
319
320
|
}
|
|
320
321
|
|
|
321
322
|
type safeReorgBlocks = {
|
|
@@ -157,7 +157,7 @@ function makeHistoryRowSchema(entitySchema) {
|
|
|
157
157
|
}));
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
function fromTable(table,
|
|
160
|
+
function fromTable(table, schema) {
|
|
161
161
|
var currentChangeFieldNames = [
|
|
162
162
|
"entity_history_block_timestamp",
|
|
163
163
|
"entity_history_chain_id",
|
|
@@ -233,17 +233,6 @@ function fromTable(table, pgSchema, schema) {
|
|
|
233
233
|
]
|
|
234
234
|
]));
|
|
235
235
|
var insertFnName = "\"insert_" + table$1.tableName + "\"";
|
|
236
|
-
var historyRowArg = "history_row";
|
|
237
|
-
var historyTablePath = "\"" + pgSchema + "\".\"" + historyTableName + "\"";
|
|
238
|
-
var originTablePath = "\"" + pgSchema + "\".\"" + originTableName + "\"";
|
|
239
|
-
var previousHistoryFieldsAreNullStr = Belt_Array.map(previousChangeFieldNames, (function (fieldName) {
|
|
240
|
-
return historyRowArg + "." + fieldName + " IS NULL";
|
|
241
|
-
})).join(" OR ");
|
|
242
|
-
var currentChangeFieldNamesCommaSeparated = currentChangeFieldNames.join(", ");
|
|
243
|
-
var dataFieldNamesDoubleQuoted = Belt_Array.map(dataFieldNames, (function (fieldName) {
|
|
244
|
-
return "\"" + fieldName + "\"";
|
|
245
|
-
}));
|
|
246
|
-
var dataFieldNamesCommaSeparated = dataFieldNamesDoubleQuoted.join(", ");
|
|
247
236
|
var allFieldNamesDoubleQuoted = Belt_Array.map(Belt_Array.concatMany([
|
|
248
237
|
currentChangeFieldNames,
|
|
249
238
|
previousChangeFieldNames,
|
|
@@ -252,19 +241,32 @@ function fromTable(table, pgSchema, schema) {
|
|
|
252
241
|
]), (function (fieldName) {
|
|
253
242
|
return "\"" + fieldName + "\"";
|
|
254
243
|
}));
|
|
255
|
-
var
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return
|
|
265
|
-
}))
|
|
266
|
-
|
|
267
|
-
|
|
244
|
+
var makeInsertFnQuery = function (pgSchema) {
|
|
245
|
+
var historyRowArg = "history_row";
|
|
246
|
+
var historyTablePath = "\"" + pgSchema + "\".\"" + historyTableName + "\"";
|
|
247
|
+
var originTablePath = "\"" + pgSchema + "\".\"" + originTableName + "\"";
|
|
248
|
+
var previousHistoryFieldsAreNullStr = Belt_Array.map(previousChangeFieldNames, (function (fieldName) {
|
|
249
|
+
return historyRowArg + "." + fieldName + " IS NULL";
|
|
250
|
+
})).join(" OR ");
|
|
251
|
+
var currentChangeFieldNamesCommaSeparated = currentChangeFieldNames.join(", ");
|
|
252
|
+
var dataFieldNamesDoubleQuoted = Belt_Array.map(dataFieldNames, (function (fieldName) {
|
|
253
|
+
return "\"" + fieldName + "\"";
|
|
254
|
+
}));
|
|
255
|
+
var dataFieldNamesCommaSeparated = dataFieldNamesDoubleQuoted.join(", ");
|
|
256
|
+
return "CREATE OR REPLACE FUNCTION " + insertFnName + "(" + historyRowArg + " " + historyTablePath + ", should_copy_current_entity BOOLEAN)\nRETURNS void AS $$\nDECLARE\n v_previous_record RECORD;\n v_origin_record RECORD;\nBEGIN\n -- Check if previous values are not provided\n IF " + previousHistoryFieldsAreNullStr + " THEN\n -- Find the most recent record for the same id\n SELECT " + currentChangeFieldNamesCommaSeparated + " INTO v_previous_record\n FROM " + historyTablePath + "\n WHERE " + id + " = " + historyRowArg + "." + id + "\n ORDER BY " + Belt_Array.map(currentChangeFieldNames, (function (fieldName) {
|
|
257
|
+
return fieldName + " DESC";
|
|
258
|
+
})).join(", ") + "\n LIMIT 1;\n\n -- If a previous record exists, use its values\n IF FOUND THEN\n " + Belt_Array.map(Belt_Array.zip(currentChangeFieldNames, previousChangeFieldNames), (function (param) {
|
|
259
|
+
return historyRowArg + "." + param[1] + " := v_previous_record." + param[0] + ";";
|
|
260
|
+
})).join(" ") + "\n ElSIF should_copy_current_entity THEN\n -- Check if a value for the id exists in the origin table and if so, insert a history row for it.\n SELECT " + dataFieldNamesCommaSeparated + " FROM " + originTablePath + " WHERE id = " + historyRowArg + "." + id + " INTO v_origin_record;\n IF FOUND THEN\n INSERT INTO " + historyTablePath + " (" + currentChangeFieldNamesCommaSeparated + ", " + dataFieldNamesCommaSeparated + ", \"" + actionFieldName + "\")\n -- SET the current change data fields to 0 since we don't know what they were\n -- and it doesn't matter provided they are less than any new values\n VALUES (" + Belt_Array.map(currentChangeFieldNames, (function (param) {
|
|
261
|
+
return "0";
|
|
262
|
+
})).join(", ") + ", " + Belt_Array.map(dataFieldNames, (function (fieldName) {
|
|
263
|
+
return "v_origin_record.\"" + fieldName + "\"";
|
|
264
|
+
})).join(", ") + ", 'SET');\n\n " + Belt_Array.map(previousChangeFieldNames, (function (previousFieldName) {
|
|
265
|
+
return historyRowArg + "." + previousFieldName + " := 0;";
|
|
266
|
+
})).join(" ") + "\n END IF;\n END IF;\n END IF;\n\n INSERT INTO " + historyTablePath + " (" + allFieldNamesDoubleQuoted.join(", ") + ")\n VALUES (" + Belt_Array.map(allFieldNamesDoubleQuoted, (function (fieldName) {
|
|
267
|
+
return historyRowArg + "." + fieldName;
|
|
268
|
+
})).join(", ") + ");\nEND;\n$$ LANGUAGE plpgsql;";
|
|
269
|
+
};
|
|
268
270
|
var insertFnString = "(sql, rowArgs, shouldCopyCurrentEntity) =>\n sql\`select " + insertFnName + "(ROW(" + Belt_Array.map(allFieldNamesDoubleQuoted, (function (fieldNameDoubleQuoted) {
|
|
269
271
|
return "\${rowArgs[" + fieldNameDoubleQuoted + "]\}";
|
|
270
272
|
})).join(", ") + ", NULL), --NULL argument for SERIAL field\n \${shouldCopyCurrentEntity});\`";
|
|
@@ -272,7 +274,7 @@ function fromTable(table, pgSchema, schema) {
|
|
|
272
274
|
var schema$1 = makeHistoryRowSchema(schema);
|
|
273
275
|
return {
|
|
274
276
|
table: table$1,
|
|
275
|
-
|
|
277
|
+
makeInsertFnQuery: makeInsertFnQuery,
|
|
276
278
|
schema: schema$1,
|
|
277
279
|
schemaRows: S$RescriptSchema.array(schema$1),
|
|
278
280
|
insertFn: insertFn
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/* TypeScript file generated from InternalTable.res by genType. */
|
|
2
|
+
|
|
3
|
+
/* eslint-disable */
|
|
4
|
+
/* tslint:disable */
|
|
5
|
+
|
|
6
|
+
import type {Json_t as Js_Json_t} from '../../src/Js.shim';
|
|
7
|
+
|
|
8
|
+
import type {t as Address_t} from '../../src/Address.gen';
|
|
9
|
+
|
|
10
|
+
export type EventSyncState_t = {
|
|
11
|
+
readonly chain_id: number;
|
|
12
|
+
readonly block_number: number;
|
|
13
|
+
readonly log_index: number;
|
|
14
|
+
readonly block_timestamp: number
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type RawEvents_t = {
|
|
18
|
+
readonly chain_id: number;
|
|
19
|
+
readonly event_id: bigint;
|
|
20
|
+
readonly event_name: string;
|
|
21
|
+
readonly contract_name: string;
|
|
22
|
+
readonly block_number: number;
|
|
23
|
+
readonly log_index: number;
|
|
24
|
+
readonly src_address: Address_t;
|
|
25
|
+
readonly block_hash: string;
|
|
26
|
+
readonly block_timestamp: number;
|
|
27
|
+
readonly block_fields: Js_Json_t;
|
|
28
|
+
readonly transaction_fields: Js_Json_t;
|
|
29
|
+
readonly params: Js_Json_t
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type DynamicContractRegistry_t = {
|
|
33
|
+
readonly id: string;
|
|
34
|
+
readonly chain_id: number;
|
|
35
|
+
readonly registering_event_block_number: number;
|
|
36
|
+
readonly registering_event_log_index: number;
|
|
37
|
+
readonly registering_event_block_timestamp: number;
|
|
38
|
+
readonly registering_event_contract_name: string;
|
|
39
|
+
readonly registering_event_name: string;
|
|
40
|
+
readonly registering_event_src_address: Address_t;
|
|
41
|
+
readonly contract_address: Address_t;
|
|
42
|
+
readonly contract_name: string
|
|
43
|
+
};
|