envio 3.0.0-alpha.19 → 3.0.0-alpha.19-main-node-pg-client
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 +1 -0
- package/src/Config.res.mjs +2 -2
- package/src/Env.res +1 -1
- package/src/Env.res.mjs +2 -2
- package/src/Internal.res.mjs +1 -1
- package/src/PgStorage.res +192 -124
- package/src/PgStorage.res.mjs +219 -112
- package/src/bindings/ClickHouse.res +1 -1
- package/src/bindings/ClickHouse.res.mjs +1 -1
- package/src/bindings/Pg.res +146 -0
- package/src/bindings/{Postgres.res.d.mts → Pg.res.d.mts} +1 -1
- package/src/bindings/Pg.res.mjs +110 -0
- package/src/db/EntityHistory.res +21 -21
- package/src/db/EntityHistory.res.mjs +16 -3
- package/src/db/InternalTable.res +47 -49
- package/src/db/InternalTable.res.mjs +57 -23
- package/src/db/Table.res +45 -33
- package/src/db/Table.res.mjs +43 -41
- package/src/PgStorage.gen.ts +0 -10
- package/src/bindings/Postgres.gen.ts +0 -8
- package/src/bindings/Postgres.res +0 -120
- package/src/bindings/Postgres.res.mjs +0 -17
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
@unboxed
|
|
2
|
+
type sslOptions =
|
|
3
|
+
| Bool(bool)
|
|
4
|
+
| @as("require") Require
|
|
5
|
+
| @as("allow") Allow
|
|
6
|
+
| @as("prefer") Prefer
|
|
7
|
+
| @as("verify-full") VerifyFull
|
|
8
|
+
|
|
9
|
+
let sslOptionsSchema: S.schema<sslOptions> = S.enum([
|
|
10
|
+
Bool(true),
|
|
11
|
+
Bool(false),
|
|
12
|
+
Require,
|
|
13
|
+
Allow,
|
|
14
|
+
Prefer,
|
|
15
|
+
VerifyFull,
|
|
16
|
+
])
|
|
17
|
+
|
|
18
|
+
type poolConfig = {
|
|
19
|
+
host?: string,
|
|
20
|
+
port?: int,
|
|
21
|
+
database?: string,
|
|
22
|
+
username?: string,
|
|
23
|
+
password?: string,
|
|
24
|
+
ssl?: sslOptions,
|
|
25
|
+
max?: int,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@unboxed type ssl = Bool(bool) | Options({rejectUnauthorized: bool})
|
|
29
|
+
type pgConfig = {
|
|
30
|
+
host?: string,
|
|
31
|
+
port?: int,
|
|
32
|
+
user?: string,
|
|
33
|
+
password?: string,
|
|
34
|
+
database?: string,
|
|
35
|
+
ssl?: ssl,
|
|
36
|
+
max?: int,
|
|
37
|
+
allowExitOnIdle?: bool,
|
|
38
|
+
}
|
|
39
|
+
type queryConfig = {
|
|
40
|
+
text: string,
|
|
41
|
+
values?: array<unknown>,
|
|
42
|
+
name?: string,
|
|
43
|
+
}
|
|
44
|
+
type queryResult = {
|
|
45
|
+
rows: array<unknown>,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
type sql = {query: queryConfig => promise<queryResult>}
|
|
49
|
+
type client = {
|
|
50
|
+
...sql,
|
|
51
|
+
release: (~destroy: bool=?) => unit,
|
|
52
|
+
}
|
|
53
|
+
type pool = {
|
|
54
|
+
...sql,
|
|
55
|
+
connect: unit => promise<client>,
|
|
56
|
+
on: (string, Js.Exn.t => unit) => unit,
|
|
57
|
+
}
|
|
58
|
+
external poolToSql: pool => sql = "%identity"
|
|
59
|
+
external clientToSql: client => sql = "%identity"
|
|
60
|
+
@module("pg") @new external makeRawPool: pgConfig => pool = "Pool"
|
|
61
|
+
|
|
62
|
+
let makePool = (~config: poolConfig): pool => {
|
|
63
|
+
let pgConfig: pgConfig = {
|
|
64
|
+
host: ?config.host,
|
|
65
|
+
port: ?config.port,
|
|
66
|
+
user: ?config.username,
|
|
67
|
+
password: ?config.password,
|
|
68
|
+
database: ?config.database,
|
|
69
|
+
max: ?config.max,
|
|
70
|
+
allowExitOnIdle: true,
|
|
71
|
+
ssl: ?switch config.ssl {
|
|
72
|
+
| Some(Require) => Some(Options({rejectUnauthorized: false}))
|
|
73
|
+
| Some(VerifyFull) => Some(Options({rejectUnauthorized: true}))
|
|
74
|
+
| Some(Prefer | Allow | Bool(true)) => Some(Bool(true))
|
|
75
|
+
| Some(Bool(false)) => Some(Bool(false))
|
|
76
|
+
| None => None
|
|
77
|
+
},
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let pool = makeRawPool(pgConfig)
|
|
81
|
+
|
|
82
|
+
// Prevent unhandled error events from crashing the process.
|
|
83
|
+
// Individual query errors are still propagated through promises.
|
|
84
|
+
pool.on("error", (err: Js.Exn.t) => {
|
|
85
|
+
Js.Console.error2("Pool error:", err->Js.Exn.message->Belt.Option.getWithDefault("Unknown error"))
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
pool
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let beginSql = async (pool: pool, fn: sql => promise<'a>) => {
|
|
92
|
+
let client = await pool.connect()
|
|
93
|
+
try {
|
|
94
|
+
let _ = await client.query({text: "BEGIN"})
|
|
95
|
+
let result = await fn(client->clientToSql)
|
|
96
|
+
let _ = await client.query({text: "COMMIT"})
|
|
97
|
+
client.release()
|
|
98
|
+
result
|
|
99
|
+
} catch {
|
|
100
|
+
| exn =>
|
|
101
|
+
try {
|
|
102
|
+
let _ = await client.query({text: "ROLLBACK"})
|
|
103
|
+
} catch {
|
|
104
|
+
| _ => ()
|
|
105
|
+
}
|
|
106
|
+
// Destroy the client instead of returning it to the pool
|
|
107
|
+
// to avoid reusing a client in a potentially bad state after a failed transaction.
|
|
108
|
+
client.release(~destroy=true)
|
|
109
|
+
raise(exn)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// pg-types default parser for NUMERIC[] (OID 1231) converts elements to numbers,
|
|
114
|
+
// but BigInt.schema and BigDecimal.schema expect string inputs.
|
|
115
|
+
// Override to keep elements as strings.
|
|
116
|
+
module PgTypes = {
|
|
117
|
+
type arrayParserResult<'a> = {parse: unit => 'a}
|
|
118
|
+
type arrayParserModule = {create: (string, unknown) => arrayParserResult<unknown>}
|
|
119
|
+
|
|
120
|
+
@module("pg") @scope("types")
|
|
121
|
+
external setTypeParser: (int, string => unknown) => unit = "setTypeParser"
|
|
122
|
+
|
|
123
|
+
@module("pg") @scope("types")
|
|
124
|
+
external arrayParser: arrayParserModule = "arrayParser"
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// OID 1231 = NUMERIC[]. Parse elements as strings, not numbers.
|
|
128
|
+
let stringIdentity: unknown = %raw(`String`)
|
|
129
|
+
PgTypes.setTypeParser(1231, val =>
|
|
130
|
+
PgTypes.arrayParser.create(val, stringIdentity).parse()
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
@unboxed
|
|
134
|
+
type columnType =
|
|
135
|
+
| @as("INTEGER") Integer
|
|
136
|
+
| @as("BIGINT") BigInt
|
|
137
|
+
| @as("BOOLEAN") Boolean
|
|
138
|
+
| @as("NUMERIC") Numeric
|
|
139
|
+
| @as("DOUBLE PRECISION") DoublePrecision
|
|
140
|
+
| @as("TEXT") Text
|
|
141
|
+
| @as("SERIAL") Serial
|
|
142
|
+
| @as("BIGSERIAL") BigSerial
|
|
143
|
+
| @as("JSONB") JsonB
|
|
144
|
+
| @as("TIMESTAMP WITH TIME ZONE") TimestampWithTimezone
|
|
145
|
+
| @as("TIMESTAMP") TimestampWithoutTimezone
|
|
146
|
+
| Custom(string)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Pg from "pg";
|
|
4
|
+
import * as Belt_Option from "rescript/lib/es6/belt_Option.js";
|
|
5
|
+
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
6
|
+
|
|
7
|
+
var sslOptionsSchema = S$RescriptSchema.$$enum([
|
|
8
|
+
true,
|
|
9
|
+
false,
|
|
10
|
+
"require",
|
|
11
|
+
"allow",
|
|
12
|
+
"prefer",
|
|
13
|
+
"verify-full"
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
function makePool(config) {
|
|
17
|
+
var match = config.ssl;
|
|
18
|
+
var tmp;
|
|
19
|
+
if (match !== undefined) {
|
|
20
|
+
if (typeof match !== "boolean") {
|
|
21
|
+
switch (match) {
|
|
22
|
+
case "require" :
|
|
23
|
+
tmp = {
|
|
24
|
+
rejectUnauthorized: false
|
|
25
|
+
};
|
|
26
|
+
break;
|
|
27
|
+
case "allow" :
|
|
28
|
+
case "prefer" :
|
|
29
|
+
tmp = true;
|
|
30
|
+
break;
|
|
31
|
+
case "verify-full" :
|
|
32
|
+
tmp = {
|
|
33
|
+
rejectUnauthorized: true
|
|
34
|
+
};
|
|
35
|
+
break;
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
tmp = match ? true : false;
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
tmp = undefined;
|
|
43
|
+
}
|
|
44
|
+
var pgConfig_host = config.host;
|
|
45
|
+
var pgConfig_port = config.port;
|
|
46
|
+
var pgConfig_user = config.username;
|
|
47
|
+
var pgConfig_password = config.password;
|
|
48
|
+
var pgConfig_database = config.database;
|
|
49
|
+
var pgConfig_max = config.max;
|
|
50
|
+
var pgConfig_allowExitOnIdle = true;
|
|
51
|
+
var pgConfig = {
|
|
52
|
+
host: pgConfig_host,
|
|
53
|
+
port: pgConfig_port,
|
|
54
|
+
user: pgConfig_user,
|
|
55
|
+
password: pgConfig_password,
|
|
56
|
+
database: pgConfig_database,
|
|
57
|
+
ssl: tmp,
|
|
58
|
+
max: pgConfig_max,
|
|
59
|
+
allowExitOnIdle: pgConfig_allowExitOnIdle
|
|
60
|
+
};
|
|
61
|
+
var pool = new Pg.Pool(pgConfig);
|
|
62
|
+
pool.on("error", (function (err) {
|
|
63
|
+
console.error("Pool error:", Belt_Option.getWithDefault(err.message, "Unknown error"));
|
|
64
|
+
}));
|
|
65
|
+
return pool;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function beginSql(pool, fn) {
|
|
69
|
+
var client = await pool.connect();
|
|
70
|
+
try {
|
|
71
|
+
await client.query({
|
|
72
|
+
text: "BEGIN"
|
|
73
|
+
});
|
|
74
|
+
var result = await fn(client);
|
|
75
|
+
await client.query({
|
|
76
|
+
text: "COMMIT"
|
|
77
|
+
});
|
|
78
|
+
client.release(undefined);
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
catch (exn){
|
|
82
|
+
try {
|
|
83
|
+
await client.query({
|
|
84
|
+
text: "ROLLBACK"
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
catch (exn$1){
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
client.release(true);
|
|
91
|
+
throw exn;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
var PgTypes = {};
|
|
96
|
+
|
|
97
|
+
var stringIdentity = String;
|
|
98
|
+
|
|
99
|
+
Pg.types.setTypeParser(1231, (function (val) {
|
|
100
|
+
return Pg.types.arrayParser.create(val, stringIdentity).parse();
|
|
101
|
+
}));
|
|
102
|
+
|
|
103
|
+
export {
|
|
104
|
+
sslOptionsSchema ,
|
|
105
|
+
makePool ,
|
|
106
|
+
beginSql ,
|
|
107
|
+
PgTypes ,
|
|
108
|
+
stringIdentity ,
|
|
109
|
+
}
|
|
110
|
+
/* sslOptionsSchema Not a pure module */
|
package/src/db/EntityHistory.res
CHANGED
|
@@ -104,16 +104,18 @@ WHERE d.id = a.id
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
let pruneStaleEntityHistory = (
|
|
107
|
-
sql,
|
|
107
|
+
sql: Pg.sql,
|
|
108
108
|
~entityName,
|
|
109
109
|
~entityIndex,
|
|
110
110
|
~pgSchema,
|
|
111
111
|
~safeCheckpointId,
|
|
112
112
|
): promise<unit> => {
|
|
113
|
-
sql
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
sql.query({
|
|
114
|
+
name: `eh_prune_${entityIndex->Belt.Int.toString}`,
|
|
115
|
+
text: makePruneStaleEntityHistoryQuery(~entityName, ~entityIndex, ~pgSchema),
|
|
116
|
+
values: [safeCheckpointId->BigInt.toString]->(Utils.magic: array<string> => array<unknown>),
|
|
117
|
+
})
|
|
118
|
+
->Promise.ignoreValue
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
// If an entity doesn't have a history before the update
|
|
@@ -121,7 +123,7 @@ let pruneStaleEntityHistory = (
|
|
|
121
123
|
let makeBackfillHistoryQuery = (~pgSchema, ~entityName, ~entityIndex) => {
|
|
122
124
|
let historyTableRef = `"${pgSchema}"."${historyTableName(~entityName, ~entityIndex)}"`
|
|
123
125
|
`WITH target_ids AS (
|
|
124
|
-
SELECT UNNEST($1::${(Text:
|
|
126
|
+
SELECT UNNEST($1::${(Text: Pg.columnType :> string)}[]) AS id
|
|
125
127
|
),
|
|
126
128
|
missing_history AS (
|
|
127
129
|
SELECT e.*
|
|
@@ -135,23 +137,21 @@ SELECT *, 0 AS ${checkpointIdFieldName}, '${(RowAction.SET :> string)}' as ${cha
|
|
|
135
137
|
FROM missing_history;`
|
|
136
138
|
}
|
|
137
139
|
|
|
138
|
-
let backfillHistory = (sql, ~pgSchema, ~entityName, ~entityIndex, ~ids: array<string>) => {
|
|
139
|
-
sql
|
|
140
|
-
|
|
141
|
-
makeBackfillHistoryQuery(~entityName, ~entityIndex, ~pgSchema),
|
|
142
|
-
[ids]->Obj.magic,
|
|
143
|
-
)
|
|
140
|
+
let backfillHistory = (sql: Pg.sql, ~pgSchema, ~entityName, ~entityIndex, ~ids: array<string>) => {
|
|
141
|
+
sql.query({
|
|
142
|
+
name: `eh_backfill_${entityIndex->Belt.Int.toString}`,
|
|
143
|
+
text: makeBackfillHistoryQuery(~entityName, ~entityIndex, ~pgSchema),
|
|
144
|
+
values: [ids]->Obj.magic,
|
|
145
|
+
})
|
|
144
146
|
->Promise.ignoreValue
|
|
145
147
|
}
|
|
146
148
|
|
|
147
|
-
let rollback = (sql, ~pgSchema, ~entityName, ~entityIndex, ~rollbackTargetCheckpointId: Internal.checkpointId) => {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
`
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
[rollbackTargetCheckpointId->BigInt.toString]->(Utils.magic: array<string> => unknown),
|
|
155
|
-
)
|
|
149
|
+
let rollback = (sql: Pg.sql, ~pgSchema, ~entityName, ~entityIndex, ~rollbackTargetCheckpointId: Internal.checkpointId) => {
|
|
150
|
+
let tableName = historyTableName(~entityName, ~entityIndex)
|
|
151
|
+
sql.query({
|
|
152
|
+
name: `eh_rollback_${entityIndex->Belt.Int.toString}`,
|
|
153
|
+
text: `DELETE FROM "${pgSchema}"."${tableName}" WHERE "${checkpointIdFieldName}" > $1;`,
|
|
154
|
+
values: [rollbackTargetCheckpointId->BigInt.toString]->(Utils.magic: array<string> => array<unknown>),
|
|
155
|
+
})
|
|
156
156
|
->Promise.ignoreValue
|
|
157
157
|
}
|
|
@@ -81,7 +81,11 @@ function makePruneStaleEntityHistoryQuery(entityName, entityIndex, pgSchema) {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
function pruneStaleEntityHistory(sql, entityName, entityIndex, pgSchema, safeCheckpointId) {
|
|
84
|
-
return sql.
|
|
84
|
+
return sql.query({
|
|
85
|
+
text: makePruneStaleEntityHistoryQuery(entityName, entityIndex, pgSchema),
|
|
86
|
+
values: [safeCheckpointId.toString()],
|
|
87
|
+
name: "eh_prune_" + String(entityIndex)
|
|
88
|
+
});
|
|
85
89
|
}
|
|
86
90
|
|
|
87
91
|
function makeBackfillHistoryQuery(pgSchema, entityName, entityIndex) {
|
|
@@ -90,11 +94,20 @@ function makeBackfillHistoryQuery(pgSchema, entityName, entityIndex) {
|
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
function backfillHistory(sql, pgSchema, entityName, entityIndex, ids) {
|
|
93
|
-
return sql.
|
|
97
|
+
return sql.query({
|
|
98
|
+
text: makeBackfillHistoryQuery(pgSchema, entityName, entityIndex),
|
|
99
|
+
values: [ids],
|
|
100
|
+
name: "eh_backfill_" + String(entityIndex)
|
|
101
|
+
});
|
|
94
102
|
}
|
|
95
103
|
|
|
96
104
|
function rollback(sql, pgSchema, entityName, entityIndex, rollbackTargetCheckpointId) {
|
|
97
|
-
|
|
105
|
+
var tableName = historyTableName(entityName, entityIndex);
|
|
106
|
+
return sql.query({
|
|
107
|
+
text: "DELETE FROM \"" + pgSchema + "\".\"" + tableName + "\" WHERE \"" + checkpointIdFieldName + "\" > $1;",
|
|
108
|
+
values: [rollbackTargetCheckpointId.toString()],
|
|
109
|
+
name: "eh_rollback_" + String(entityIndex)
|
|
110
|
+
});
|
|
98
111
|
}
|
|
99
112
|
|
|
100
113
|
var checkpointIdFieldType = "UInt64";
|
package/src/db/InternalTable.res
CHANGED
|
@@ -199,10 +199,9 @@ WHERE "${(#id: field :> string)}" = $1;`
|
|
|
199
199
|
FROM "${pgSchema}"."${table.tableName}" as chains;`
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
let getInitialState = (sql, ~pgSchema) => {
|
|
203
|
-
sql
|
|
204
|
-
->
|
|
205
|
-
->(Utils.magic: promise<array<unknown>> => promise<array<rawInitialState>>)
|
|
202
|
+
let getInitialState = (sql: Pg.sql, ~pgSchema) => {
|
|
203
|
+
sql.query({text: makeGetInitialStateQuery(~pgSchema)})
|
|
204
|
+
->Promise.thenResolve(r => r.rows->(Utils.magic: array<unknown> => array<rawInitialState>))
|
|
206
205
|
}
|
|
207
206
|
|
|
208
207
|
let progressFields: array<progressFields> = [#progress_block, #events_processed, #source_block]
|
|
@@ -219,7 +218,7 @@ SET ${setClauses->Js.Array2.joinWith(",\n ")}
|
|
|
219
218
|
WHERE "id" = $1;`
|
|
220
219
|
}
|
|
221
220
|
|
|
222
|
-
let setMeta = (sql, ~pgSchema, ~chainsData: dict<metaFields>) => {
|
|
221
|
+
let setMeta = (sql: Pg.sql, ~pgSchema, ~chainsData: dict<metaFields>) => {
|
|
223
222
|
let query = makeMetaFieldsUpdateQuery(~pgSchema)
|
|
224
223
|
|
|
225
224
|
let promises = []
|
|
@@ -237,7 +236,7 @@ WHERE "id" = $1;`
|
|
|
237
236
|
params->Js.Array2.push(value)->ignore
|
|
238
237
|
})
|
|
239
238
|
|
|
240
|
-
promises->Js.Array2.push(sql
|
|
239
|
+
promises->Js.Array2.push(sql.query({name: "chains_set_meta", text: query, values: params->Obj.magic}))->ignore
|
|
241
240
|
})
|
|
242
241
|
|
|
243
242
|
Promise.all(promises)
|
|
@@ -250,7 +249,7 @@ WHERE "id" = $1;`
|
|
|
250
249
|
totalEventsProcessed: float,
|
|
251
250
|
}
|
|
252
251
|
|
|
253
|
-
let setProgressedChains = (sql, ~pgSchema, ~progressedChains: array<progressedChain>) => {
|
|
252
|
+
let setProgressedChains = (sql: Pg.sql, ~pgSchema, ~progressedChains: array<progressedChain>) => {
|
|
254
253
|
let query = makeProgressFieldsUpdateQuery(~pgSchema)
|
|
255
254
|
|
|
256
255
|
let promises = []
|
|
@@ -274,7 +273,7 @@ WHERE "id" = $1;`
|
|
|
274
273
|
->ignore
|
|
275
274
|
})
|
|
276
275
|
|
|
277
|
-
promises->Js.Array2.push(sql
|
|
276
|
+
promises->Js.Array2.push(sql.query({name: "chains_set_progress", text: query, values: params->Obj.magic}))->ignore
|
|
278
277
|
})
|
|
279
278
|
|
|
280
279
|
Promise.all(promises)->Promise.ignoreValue
|
|
@@ -380,11 +379,11 @@ WHERE cp."${(#block_hash: field :> string)}" IS NOT NULL
|
|
|
380
379
|
|
|
381
380
|
let makeInsertCheckpointQuery = (~pgSchema) => {
|
|
382
381
|
`INSERT INTO "${pgSchema}"."${table.tableName}" ("${(#id: field :> string)}", "${(#chain_id: field :> string)}", "${(#block_number: field :> string)}", "${(#block_hash: field :> string)}", "${(#events_processed: field :> string)}")
|
|
383
|
-
SELECT * FROM unnest($1::${(BigInt:
|
|
382
|
+
SELECT * FROM unnest($1::${(BigInt: Pg.columnType :> string)}[],$2::${(Integer: Pg.columnType :> string)}[],$3::${(Integer: Pg.columnType :> string)}[],$4::${(Text: Pg.columnType :> string)}[],$5::${(Integer: Pg.columnType :> string)}[]);`
|
|
384
383
|
}
|
|
385
384
|
|
|
386
385
|
let insert = (
|
|
387
|
-
sql,
|
|
386
|
+
sql: Pg.sql,
|
|
388
387
|
~pgSchema,
|
|
389
388
|
~checkpointIds,
|
|
390
389
|
~checkpointChainIds,
|
|
@@ -396,10 +395,10 @@ SELECT * FROM unnest($1::${(BigInt: Postgres.columnType :> string)}[],$2::${(Int
|
|
|
396
395
|
|
|
397
396
|
// Convert bigint arrays to string arrays for postgres driver compatibility
|
|
398
397
|
let checkpointIdStrings = checkpointIds->BigInt.arrayToStringArray
|
|
399
|
-
sql
|
|
400
|
-
|
|
401
|
-
query,
|
|
402
|
-
(
|
|
398
|
+
sql.query({
|
|
399
|
+
name: "checkpoints_insert",
|
|
400
|
+
text: query,
|
|
401
|
+
values: (
|
|
403
402
|
checkpointIdStrings,
|
|
404
403
|
checkpointChainIds,
|
|
405
404
|
checkpointBlockNumbers,
|
|
@@ -408,18 +407,18 @@ SELECT * FROM unnest($1::${(BigInt: Postgres.columnType :> string)}[],$2::${(Int
|
|
|
408
407
|
)->(
|
|
409
408
|
Utils.magic: (
|
|
410
409
|
(array<string>, array<int>, array<int>, array<Js.Null.t<string>>, array<int>)
|
|
411
|
-
) => unknown
|
|
410
|
+
) => array<unknown>
|
|
412
411
|
),
|
|
413
|
-
)
|
|
412
|
+
})
|
|
414
413
|
->Promise.ignoreValue
|
|
415
414
|
}
|
|
416
415
|
|
|
417
|
-
let rollback = (sql, ~pgSchema, ~rollbackTargetCheckpointId: Internal.checkpointId) => {
|
|
418
|
-
sql
|
|
419
|
-
|
|
420
|
-
`DELETE FROM "${pgSchema}"."${table.tableName}" WHERE "${(#id: field :> string)}" > $1;`,
|
|
421
|
-
[rollbackTargetCheckpointId->BigInt.toString]->(Utils.magic: array<string> => unknown),
|
|
422
|
-
)
|
|
416
|
+
let rollback = (sql: Pg.sql, ~pgSchema, ~rollbackTargetCheckpointId: Internal.checkpointId) => {
|
|
417
|
+
sql.query({
|
|
418
|
+
name: "checkpoints_rollback",
|
|
419
|
+
text: `DELETE FROM "${pgSchema}"."${table.tableName}" WHERE "${(#id: field :> string)}" > $1;`,
|
|
420
|
+
values: [rollbackTargetCheckpointId->BigInt.toString]->(Utils.magic: array<string> => array<unknown>),
|
|
421
|
+
})
|
|
423
422
|
->Promise.ignoreValue
|
|
424
423
|
}
|
|
425
424
|
|
|
@@ -427,12 +426,12 @@ SELECT * FROM unnest($1::${(BigInt: Postgres.columnType :> string)}[],$2::${(Int
|
|
|
427
426
|
`DELETE FROM "${pgSchema}"."${table.tableName}" WHERE "${(#id: field :> string)}" < $1;`
|
|
428
427
|
}
|
|
429
428
|
|
|
430
|
-
let pruneStaleCheckpoints = (sql, ~pgSchema, ~safeCheckpointId: bigint) => {
|
|
431
|
-
sql
|
|
432
|
-
|
|
433
|
-
makePruneStaleCheckpointsQuery(~pgSchema),
|
|
434
|
-
[safeCheckpointId->BigInt.toString]->Obj.magic,
|
|
435
|
-
)
|
|
429
|
+
let pruneStaleCheckpoints = (sql: Pg.sql, ~pgSchema, ~safeCheckpointId: bigint) => {
|
|
430
|
+
sql.query({
|
|
431
|
+
name: "checkpoints_prune",
|
|
432
|
+
text: makePruneStaleCheckpointsQuery(~pgSchema),
|
|
433
|
+
values: [safeCheckpointId->BigInt.toString]->Obj.magic,
|
|
434
|
+
})
|
|
436
435
|
->Promise.ignoreValue
|
|
437
436
|
}
|
|
438
437
|
|
|
@@ -446,25 +445,24 @@ LIMIT 1;`
|
|
|
446
445
|
}
|
|
447
446
|
|
|
448
447
|
let getRollbackTargetCheckpoint = (
|
|
449
|
-
sql,
|
|
448
|
+
sql: Pg.sql,
|
|
450
449
|
~pgSchema,
|
|
451
450
|
~reorgChainId: int,
|
|
452
451
|
~lastKnownValidBlockNumber: int,
|
|
453
452
|
) => {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
->(Utils.magic:
|
|
461
|
-
rawResult->Promise.thenResolve(rows => {
|
|
453
|
+
sql.query({
|
|
454
|
+
name: "checkpoints_rollback_target",
|
|
455
|
+
text: makeGetRollbackTargetCheckpointQuery(~pgSchema),
|
|
456
|
+
values: (reorgChainId, lastKnownValidBlockNumber)->Obj.magic,
|
|
457
|
+
})
|
|
458
|
+
->Promise.thenResolve(r => {
|
|
459
|
+
let rows = r.rows->(Utils.magic: array<unknown> => array<{"id": string}>)
|
|
462
460
|
rows->Belt.Array.get(0)->Belt.Option.map(row => row["id"]->BigInt.fromStringUnsafe)
|
|
463
461
|
})
|
|
464
462
|
}
|
|
465
463
|
|
|
466
464
|
let makeGetRollbackProgressDiffQuery = (~pgSchema) => {
|
|
467
|
-
`SELECT
|
|
465
|
+
`SELECT
|
|
468
466
|
"${(#chain_id: field :> string)}",
|
|
469
467
|
SUM("${(#events_processed: field :> string)}") as events_processed_diff,
|
|
470
468
|
MIN("${(#block_number: field :> string)}") - 1 as new_progress_block_number
|
|
@@ -474,23 +472,23 @@ GROUP BY "${(#chain_id: field :> string)}";`
|
|
|
474
472
|
}
|
|
475
473
|
|
|
476
474
|
let getRollbackProgressDiff = (
|
|
477
|
-
sql,
|
|
475
|
+
sql: Pg.sql,
|
|
478
476
|
~pgSchema,
|
|
479
477
|
~rollbackTargetCheckpointId: Internal.checkpointId,
|
|
480
478
|
) => {
|
|
481
|
-
sql
|
|
482
|
-
|
|
483
|
-
makeGetRollbackProgressDiffQuery(~pgSchema),
|
|
484
|
-
[rollbackTargetCheckpointId->BigInt.toString]->Obj.magic,
|
|
485
|
-
)
|
|
486
|
-
->(
|
|
487
|
-
|
|
488
|
-
array<{
|
|
479
|
+
sql.query({
|
|
480
|
+
name: "checkpoints_rollback_diff",
|
|
481
|
+
text: makeGetRollbackProgressDiffQuery(~pgSchema),
|
|
482
|
+
values: [rollbackTargetCheckpointId->BigInt.toString]->Obj.magic,
|
|
483
|
+
})
|
|
484
|
+
->Promise.thenResolve(r =>
|
|
485
|
+
r.rows->(
|
|
486
|
+
Utils.magic: array<unknown> => array<{
|
|
489
487
|
"chain_id": int,
|
|
490
488
|
"events_processed_diff": string,
|
|
491
489
|
"new_progress_block_number": int,
|
|
492
|
-
}
|
|
493
|
-
|
|
490
|
+
}>
|
|
491
|
+
)
|
|
494
492
|
)
|
|
495
493
|
}
|
|
496
494
|
}
|