@ercworldio/blockchain-shared 1.0.3-dev.3-PROJ-1296.26 → 1.0.3-dev.3-PROJ-1296.27
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.
|
@@ -4,18 +4,11 @@ import { Pool } from "pg";
|
|
|
4
4
|
import { OperationType } from "../../../contracts/types/escrow";
|
|
5
5
|
import { MarkCompleteScheduleJob, ScheduleTransactionJobWithDetails } from "../../types/db";
|
|
6
6
|
declare class ScheduleTransactionService {
|
|
7
|
-
static
|
|
7
|
+
static get_and_lock_available_jobs: (pool: Pool, limit?: number, job_ttl_s?: number, lock_metadata?: ClaimJobLockMetadata) => Promise<ScheduleTransactionJob[]>;
|
|
8
8
|
/** Same as get_available_jobs but joins withdrawal details from accounting for each job. */
|
|
9
|
-
static
|
|
9
|
+
static get_and_lock_available_jobs_with_details: (pool: Pool, limit?: number, job_ttl_s?: number, lock_metadata?: ClaimJobLockMetadata) => Promise<ScheduleTransactionJobWithDetails[]>;
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
* @param pool
|
|
13
|
-
* @param current_status
|
|
14
|
-
* @param limit
|
|
15
|
-
* @param lock_owner
|
|
16
|
-
* @param lock_reason
|
|
17
|
-
* @param max_retries
|
|
18
|
-
* @returns
|
|
11
|
+
* Requeues all jobs in the given status to "queued"
|
|
19
12
|
*/
|
|
20
13
|
static requeue_expired_jobs: (pool: Pool, current_status: ScheduleJobStatus, limit: number, lock_owner: string, lock_reason: string, max_retries: number) => Promise<ScheduleTransactionJob[]>;
|
|
21
14
|
static batch_update_status: (pool: Pool, operation_type: OperationType, request_ids: number[], new_status: ScheduleJobStatus) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScheduleTransactionService.d.ts","sourceRoot":"","sources":["../../../../src/services/db/timelock/ScheduleTransactionService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AACrG,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,iCAAiC,EAAE,MAAM,gBAAgB,CAAC;AAE5F,cAAM,0BAA0B;IAE5B,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"ScheduleTransactionService.d.ts","sourceRoot":"","sources":["../../../../src/services/db/timelock/ScheduleTransactionService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AACrG,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,iCAAiC,EAAE,MAAM,gBAAgB,CAAC;AAE5F,cAAM,0BAA0B;IAE5B,MAAM,CAAC,2BAA2B,GAAU,MAAM,IAAI,EAAE,QAAO,MAAW,EAAE,YAAW,MAAY,EAAE,gBAAe,oBAA0F,KAAG,OAAO,CAAC,sBAAsB,EAAE,CAAC,CA8CjP;IAGD,4FAA4F;IAC5F,MAAM,CAAC,wCAAwC,GAAU,MAAM,IAAI,EAAE,QAAO,MAAW,EAAE,YAAW,MAAY,EAAE,gBAAe,oBAA0F,KAAG,OAAO,CAAC,iCAAiC,EAAE,CAAC,CAmDzQ;IAGD;;OAEG;IACH,MAAM,CAAC,oBAAoB,GACvB,MAAM,IAAI,EACV,gBAAgB,iBAAiB,EACjC,OAAO,MAAM,EACb,YAAY,MAAM,EAClB,aAAa,MAAM,EACnB,aAAa,MAAM,KACpB,OAAO,CAAC,sBAAsB,EAAE,CAAC,CA8ClC;IAGF,MAAM,CAAC,mBAAmB,GAAU,MAAM,IAAI,EAAE,gBAAgB,aAAa,EAAE,aAAa,MAAM,EAAE,EAAE,YAAY,iBAAiB,KAAG,OAAO,CAAC,IAAI,CAAC,CASjJ;IAGF,MAAM,CAAC,wBAAwB,GAC3B,MAAM,IAAI,EACV,gBAAgB,aAAa,EAC7B,aAAa,MAAM,EAAE,EACrB,YAAY,iBAAiB,EAC7B,gBAAgB,MAAM,EACtB,YAAY,OAAO,KACpB,OAAO,CAAC,IAAI,CAAC,CAwBd;IAGF,MAAM,CAAC,qCAAqC,GACxC,MAAM,IAAI,EACV,gBAAgB,aAAa,EAC7B,MAAM;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,iBAAiB,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,EAAE,KACzG,OAAO,CAAC,IAAI,CAAC,CA8Bf;IAGD,MAAM,CAAC,0BAA0B,GAC7B,MAAM,IAAI,EACV,MAAM;QAAE,cAAc,EAAE,aAAa,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,IAAI,CAAA;KAAE,EAAE,KAC9F,OAAO,CAAC,IAAI,CAAC,CAwBd;IAGF,MAAM,CAAC,aAAa,GAAU,MAAM,IAAI,EAAE,UAAU,uBAAuB,EAAE,KAAG,OAAO,CAAC,IAAI,CAAC,CAmB5F;CAEJ;AAED,eAAe,0BAA0B,CAAC"}
|
|
@@ -14,25 +14,31 @@ const uuid_1 = require("uuid");
|
|
|
14
14
|
class ScheduleTransactionService {
|
|
15
15
|
}
|
|
16
16
|
_a = ScheduleTransactionService;
|
|
17
|
-
ScheduleTransactionService.
|
|
17
|
+
ScheduleTransactionService.get_and_lock_available_jobs = (pool_1, ...args_1) => __awaiter(void 0, [pool_1, ...args_1], void 0, function* (pool, limit = 10, job_ttl_s = 120, lock_metadata = { lock_owner: "schedule-tx-worker", lock_reason: "process_queued" }) {
|
|
18
18
|
const ttlSeconds = job_ttl_s;
|
|
19
19
|
const batchGroupId = (0, uuid_1.v4)();
|
|
20
20
|
const res = yield pool.query(`
|
|
21
|
-
WITH
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
WITH status_ids AS (
|
|
22
|
+
SELECT
|
|
23
|
+
MAX(CASE WHEN status = 'queued' THEN id END) AS queued_id,
|
|
24
|
+
MAX(CASE WHEN status = 'processing' THEN id END) AS processing_id
|
|
25
|
+
FROM multisig.schedule_job_statuses
|
|
26
|
+
),
|
|
27
|
+
candidates AS (
|
|
28
|
+
SELECT cj.id
|
|
29
|
+
FROM multisig.schedule_transaction_jobs cj, status_ids
|
|
30
|
+
WHERE cj.status_id = status_ids.queued_id
|
|
31
|
+
AND (cj.lock_expires_at IS NULL OR cj.lock_expires_at < now())
|
|
32
|
+
ORDER BY cj.blockchain, cj.chain_id ASC
|
|
27
33
|
LIMIT $1
|
|
28
34
|
FOR UPDATE SKIP LOCKED
|
|
29
35
|
)
|
|
30
36
|
UPDATE multisig.schedule_transaction_jobs cj
|
|
31
37
|
SET
|
|
32
|
-
|
|
33
|
-
locked_at
|
|
38
|
+
status_id = si.processing_id,
|
|
39
|
+
locked_at = now(),
|
|
34
40
|
lock_expires_at = now() + ($2 || ' seconds')::interval,
|
|
35
|
-
batch_group_id
|
|
41
|
+
batch_group_id = $3,
|
|
36
42
|
metadata = jsonb_set(
|
|
37
43
|
jsonb_set(
|
|
38
44
|
coalesce(cj.metadata, '{}'::jsonb),
|
|
@@ -43,33 +49,39 @@ ScheduleTransactionService.get_available_jobs = (pool_1, ...args_1) => __awaiter
|
|
|
43
49
|
to_jsonb($5::text)
|
|
44
50
|
),
|
|
45
51
|
updated_at = now()
|
|
46
|
-
FROM candidates c
|
|
52
|
+
FROM candidates c, status_ids si
|
|
47
53
|
WHERE cj.id = c.id
|
|
48
54
|
RETURNING cj.*;
|
|
49
55
|
`, [limit, ttlSeconds, batchGroupId, lock_metadata.lock_owner, lock_metadata.lock_reason]);
|
|
50
56
|
return res.rows;
|
|
51
57
|
});
|
|
52
58
|
/** Same as get_available_jobs but joins withdrawal details from accounting for each job. */
|
|
53
|
-
ScheduleTransactionService.
|
|
59
|
+
ScheduleTransactionService.get_and_lock_available_jobs_with_details = (pool_1, ...args_1) => __awaiter(void 0, [pool_1, ...args_1], void 0, function* (pool, limit = 10, job_ttl_s = 120, lock_metadata = { lock_owner: "schedule-tx-worker", lock_reason: "process_queued" }) {
|
|
54
60
|
const ttlSeconds = job_ttl_s;
|
|
55
61
|
const batchGroupId = (0, uuid_1.v4)();
|
|
56
62
|
const res = yield pool.query(`
|
|
57
|
-
WITH
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
WITH status_ids AS (
|
|
64
|
+
SELECT
|
|
65
|
+
MAX(CASE WHEN status = 'queued' THEN id END) AS queued_id,
|
|
66
|
+
MAX(CASE WHEN status = 'processing' THEN id END) AS processing_id
|
|
67
|
+
FROM multisig.schedule_job_statuses
|
|
68
|
+
),
|
|
69
|
+
candidates AS (
|
|
70
|
+
SELECT cj.id
|
|
71
|
+
FROM multisig.schedule_transaction_jobs cj, status_ids
|
|
72
|
+
WHERE cj.status_id = status_ids.queued_id
|
|
73
|
+
AND (cj.lock_expires_at IS NULL OR cj.lock_expires_at < now())
|
|
74
|
+
ORDER BY cj.blockchain, cj.chain_id ASC
|
|
63
75
|
LIMIT $1
|
|
64
76
|
FOR UPDATE SKIP LOCKED
|
|
65
77
|
),
|
|
66
78
|
updated AS (
|
|
67
79
|
UPDATE multisig.schedule_transaction_jobs cj
|
|
68
80
|
SET
|
|
69
|
-
|
|
70
|
-
locked_at
|
|
81
|
+
status_id = si.processing_id,
|
|
82
|
+
locked_at = now(),
|
|
71
83
|
lock_expires_at = now() + ($2 || ' seconds')::interval,
|
|
72
|
-
batch_group_id
|
|
84
|
+
batch_group_id = $3,
|
|
73
85
|
metadata = jsonb_set(
|
|
74
86
|
jsonb_set(
|
|
75
87
|
coalesce(cj.metadata, '{}'::jsonb),
|
|
@@ -80,44 +92,44 @@ ScheduleTransactionService.get_available_jobs_with_details = (pool_1, ...args_1)
|
|
|
80
92
|
to_jsonb($5::text)
|
|
81
93
|
),
|
|
82
94
|
updated_at = now()
|
|
83
|
-
FROM candidates c
|
|
95
|
+
FROM candidates c, status_ids si
|
|
84
96
|
WHERE cj.id = c.id
|
|
85
97
|
RETURNING cj.*
|
|
86
98
|
)
|
|
87
|
-
SELECT u.*, accounting.fn_get_crypto_withdrawal_details(u.request_id) AS withdrawal_details
|
|
88
|
-
FROM updated u
|
|
99
|
+
SELECT u.*, sjs.status, accounting.fn_get_crypto_withdrawal_details(u.request_id) AS withdrawal_details
|
|
100
|
+
FROM updated u
|
|
101
|
+
JOIN multisig.schedule_job_statuses sjs ON sjs.id = u.status_id
|
|
89
102
|
`, [limit, ttlSeconds, batchGroupId, lock_metadata.lock_owner, lock_metadata.lock_reason]);
|
|
90
103
|
return res.rows;
|
|
91
104
|
});
|
|
92
105
|
/**
|
|
93
|
-
*
|
|
94
|
-
* @param pool
|
|
95
|
-
* @param current_status
|
|
96
|
-
* @param limit
|
|
97
|
-
* @param lock_owner
|
|
98
|
-
* @param lock_reason
|
|
99
|
-
* @param max_retries
|
|
100
|
-
* @returns
|
|
106
|
+
* Requeues all jobs in the given status to "queued"
|
|
101
107
|
*/
|
|
102
108
|
ScheduleTransactionService.requeue_expired_jobs = (pool, current_status, limit, lock_owner, lock_reason, max_retries) => __awaiter(void 0, void 0, void 0, function* () {
|
|
103
109
|
const res = yield pool.query(`
|
|
104
|
-
WITH
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
WITH status_ids AS (
|
|
111
|
+
SELECT
|
|
112
|
+
MAX(CASE WHEN status = $4::text THEN id END) AS current_status_id,
|
|
113
|
+
MAX(CASE WHEN status = 'queued' THEN id END) AS queued_id
|
|
114
|
+
FROM multisig.schedule_job_statuses
|
|
115
|
+
),
|
|
116
|
+
expired AS (
|
|
117
|
+
SELECT sj.id
|
|
118
|
+
FROM multisig.schedule_transaction_jobs sj, status_ids
|
|
119
|
+
WHERE sj.status_id = status_ids.current_status_id
|
|
108
120
|
AND (
|
|
109
|
-
lock_expires_at IS NULL
|
|
110
|
-
OR lock_expires_at < now()
|
|
121
|
+
sj.lock_expires_at IS NULL
|
|
122
|
+
OR sj.lock_expires_at < now()
|
|
111
123
|
)
|
|
112
|
-
AND retry_count < $5
|
|
113
|
-
ORDER BY lock_expires_at ASC
|
|
124
|
+
AND sj.retry_count < $5
|
|
125
|
+
ORDER BY sj.lock_expires_at ASC
|
|
114
126
|
LIMIT $1
|
|
115
127
|
FOR UPDATE SKIP LOCKED
|
|
116
128
|
)
|
|
117
129
|
UPDATE multisig.schedule_transaction_jobs cj
|
|
118
130
|
SET
|
|
119
|
-
|
|
120
|
-
locked_at
|
|
131
|
+
status_id = si.queued_id,
|
|
132
|
+
locked_at = NULL,
|
|
121
133
|
lock_expires_at = NULL,
|
|
122
134
|
metadata = jsonb_set(
|
|
123
135
|
jsonb_set(
|
|
@@ -131,43 +143,45 @@ ScheduleTransactionService.requeue_expired_jobs = (pool, current_status, limit,
|
|
|
131
143
|
true
|
|
132
144
|
),
|
|
133
145
|
updated_at = now()
|
|
134
|
-
FROM expired e
|
|
146
|
+
FROM expired e, status_ids si
|
|
135
147
|
WHERE cj.id = e.id
|
|
136
148
|
RETURNING cj.*;
|
|
137
149
|
`, [limit, lock_owner, lock_reason, current_status, max_retries]);
|
|
138
150
|
return res.rows;
|
|
139
151
|
});
|
|
140
152
|
ScheduleTransactionService.batch_update_status = (pool, operation_type, request_ids, new_status) => __awaiter(void 0, void 0, void 0, function* () {
|
|
141
|
-
const status = new_status;
|
|
142
153
|
yield pool.query(`
|
|
143
154
|
UPDATE multisig.schedule_transaction_jobs
|
|
144
|
-
SET
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
155
|
+
SET
|
|
156
|
+
status_id = (SELECT id FROM multisig.schedule_job_statuses WHERE status = $1),
|
|
157
|
+
updated_at = CURRENT_TIMESTAMP
|
|
158
|
+
WHERE operation_type = $2::int
|
|
159
|
+
AND request_id = ANY($3)
|
|
160
|
+
`, [new_status, operation_type, request_ids]);
|
|
148
161
|
});
|
|
149
162
|
ScheduleTransactionService.batch_update_failed_jobs = (pool, operation_type, request_ids, new_status, error_message, retryable) => __awaiter(void 0, void 0, void 0, function* () {
|
|
150
163
|
yield pool.query(`
|
|
151
164
|
UPDATE multisig.schedule_transaction_jobs
|
|
152
|
-
SET
|
|
153
|
-
status = $1,
|
|
154
|
-
updated_at
|
|
165
|
+
SET
|
|
166
|
+
status_id = (SELECT id FROM multisig.schedule_job_statuses WHERE status = $1),
|
|
167
|
+
updated_at = CURRENT_TIMESTAMP,
|
|
155
168
|
error_message = COALESCE($2, error_message),
|
|
156
|
-
last_error_at = CASE
|
|
169
|
+
last_error_at = CASE
|
|
157
170
|
WHEN $2 IS NOT NULL THEN CURRENT_TIMESTAMP
|
|
158
171
|
ELSE last_error_at
|
|
159
172
|
END,
|
|
160
|
-
retry_count
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
WHERE operation_type = $5
|
|
173
|
+
retry_count = CASE
|
|
174
|
+
WHEN $3 = true THEN retry_count + 1
|
|
175
|
+
ELSE retry_count
|
|
176
|
+
END
|
|
177
|
+
WHERE operation_type = $5
|
|
178
|
+
AND request_id = ANY($4)
|
|
165
179
|
`, [
|
|
166
180
|
new_status,
|
|
167
181
|
error_message || null,
|
|
168
182
|
retryable === true,
|
|
169
183
|
request_ids,
|
|
170
|
-
operation_type
|
|
184
|
+
operation_type,
|
|
171
185
|
]);
|
|
172
186
|
});
|
|
173
187
|
ScheduleTransactionService.batch_update_failed_jobs_custom_error = (pool, operation_type, jobs) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -179,7 +193,7 @@ ScheduleTransactionService.batch_update_failed_jobs_custom_error = (pool, operat
|
|
|
179
193
|
yield pool.query(`
|
|
180
194
|
UPDATE multisig.schedule_transaction_jobs AS t
|
|
181
195
|
SET
|
|
182
|
-
|
|
196
|
+
status_id = sjs.id,
|
|
183
197
|
error_message = c.error_message,
|
|
184
198
|
last_error_at = CURRENT_TIMESTAMP,
|
|
185
199
|
retry_count = CASE WHEN c.retryable THEN t.retry_count + 1 ELSE t.retry_count END,
|
|
@@ -192,8 +206,9 @@ ScheduleTransactionService.batch_update_failed_jobs_custom_error = (pool, operat
|
|
|
192
206
|
UNNEST($4::text[]) AS error_message,
|
|
193
207
|
UNNEST($5::boolean[]) AS retryable
|
|
194
208
|
) AS c
|
|
209
|
+
JOIN multisig.schedule_job_statuses sjs ON sjs.status = c.status
|
|
195
210
|
WHERE t.operation_type = c.operation_type
|
|
196
|
-
|
|
211
|
+
AND t.request_id = c.request_id
|
|
197
212
|
`, [operationTypes, requestIds, newStatuses, errorMessages, retryables]);
|
|
198
213
|
});
|
|
199
214
|
ScheduleTransactionService.batch_update_executed_jobs = (pool, data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -203,21 +218,21 @@ ScheduleTransactionService.batch_update_executed_jobs = (pool, data) => __awaite
|
|
|
203
218
|
const sentAts = data.map(d => d.sent_at);
|
|
204
219
|
yield pool.query(`
|
|
205
220
|
UPDATE multisig.schedule_transaction_jobs AS t
|
|
206
|
-
SET
|
|
207
|
-
tx_hash
|
|
208
|
-
sent_at
|
|
209
|
-
status = 'confirming',
|
|
221
|
+
SET
|
|
222
|
+
tx_hash = c.tx_hash,
|
|
223
|
+
sent_at = c.sent_at,
|
|
224
|
+
status_id = (SELECT id FROM multisig.schedule_job_statuses WHERE status = 'confirming'),
|
|
210
225
|
updated_at = CURRENT_TIMESTAMP
|
|
211
226
|
FROM (
|
|
212
|
-
SELECT
|
|
213
|
-
UNNEST($1::int[])
|
|
214
|
-
UNNEST($2::int[])
|
|
215
|
-
UNNEST($3::text[])
|
|
227
|
+
SELECT
|
|
228
|
+
UNNEST($1::int[]) AS operation_type,
|
|
229
|
+
UNNEST($2::int[]) AS request_id,
|
|
230
|
+
UNNEST($3::text[]) AS tx_hash,
|
|
216
231
|
UNNEST($4::timestamptz[]) AS sent_at
|
|
217
232
|
) AS c
|
|
218
233
|
WHERE t.request_id = c.request_id
|
|
219
|
-
|
|
220
|
-
|
|
234
|
+
AND t.operation_type = c.operation_type
|
|
235
|
+
`, [operationTypes, requestIds, txHashes, sentAts]);
|
|
221
236
|
});
|
|
222
237
|
ScheduleTransactionService.mark_complete = (pool, payloads) => __awaiter(void 0, void 0, void 0, function* () {
|
|
223
238
|
if (payloads.length === 0)
|
|
@@ -227,15 +242,15 @@ ScheduleTransactionService.mark_complete = (pool, payloads) => __awaiter(void 0,
|
|
|
227
242
|
yield pool.query(`
|
|
228
243
|
UPDATE multisig.schedule_transaction_jobs AS t
|
|
229
244
|
SET
|
|
230
|
-
status = 'completed',
|
|
245
|
+
status_id = (SELECT id FROM multisig.schedule_job_statuses WHERE status = 'completed'),
|
|
231
246
|
updated_at = CURRENT_TIMESTAMP
|
|
232
247
|
FROM (
|
|
233
248
|
SELECT
|
|
234
249
|
UNNEST($1::int[]) AS request_id,
|
|
235
|
-
UNNEST($2::int[]) AS operation_type
|
|
250
|
+
UNNEST($2::int[]) AS operation_type
|
|
236
251
|
) AS c
|
|
237
252
|
WHERE t.request_id = c.request_id
|
|
238
|
-
|
|
239
|
-
|
|
253
|
+
AND t.operation_type = c.operation_type
|
|
254
|
+
`, [requestIds, operationTypes]);
|
|
240
255
|
});
|
|
241
256
|
exports.default = ScheduleTransactionService;
|
package/package.json
CHANGED