Skip to content

Commit 9160da6

Browse files
authored
fix: backfill cycle signer stats for previous cycles (#89)
* fix: backfill cycle signer stats for previous cycles * chore: log before migrations run * fix: duplicate ranks * ci: test before publish * fix: down migration
1 parent 0a12e4d commit 9160da6

File tree

4 files changed

+102
-5
lines changed

4 files changed

+102
-5
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,15 @@ jobs:
8686
uses: codecov/codecov-action@v4
8787
with:
8888
token: ${{ secrets.CODECOV_TOKEN }}
89-
89+
9090
build-publish:
9191
permissions:
9292
contents: write
9393
issues: write
9494
pull-requests: write
9595
runs-on: ubuntu-latest
96-
# needs:
97-
# - lint
98-
# - test
96+
needs:
97+
- test
9998
steps:
10099
- name: Generate release bot app token
101100
id: generate_token
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/* eslint-disable @typescript-eslint/naming-convention */
2+
import { MigrationBuilder, ColumnDefinitions } from 'node-pg-migrate';
3+
4+
export const shorthands: ColumnDefinitions | undefined = undefined;
5+
6+
export function up(pgm: MigrationBuilder): void {
7+
pgm.sql(`
8+
UPDATE reward_set_signers rss
9+
SET
10+
signer_stacked_amount_percentage = (rss.signer_stacked_amount::numeric / total.total_stacked),
11+
signer_weight_percentage = (rss.signer_weight::float / total.total_weight),
12+
signer_stacked_amount_rank = ranked.rank
13+
FROM
14+
(SELECT cycle_number, SUM(signer_stacked_amount::numeric) as total_stacked, SUM(signer_weight) as total_weight FROM reward_set_signers GROUP BY cycle_number) total,
15+
(SELECT signer_key, cycle_number, RANK() OVER (PARTITION BY cycle_number ORDER BY signer_stacked_amount::numeric DESC, signer_key ASC) as rank FROM reward_set_signers) ranked
16+
WHERE rss.cycle_number = total.cycle_number AND rss.cycle_number = ranked.cycle_number AND rss.signer_key = ranked.signer_key
17+
`);
18+
pgm.sql(`
19+
UPDATE reward_set_signers rss
20+
SET
21+
proposals_accepted_count = COALESCE(agg.accepted_count, 0),
22+
proposals_rejected_count = COALESCE(agg.rejected_count, 0),
23+
proposals_missed_count = COALESCE(agg.missed_count, 0),
24+
average_response_time_ms = COALESCE(agg.avg_ms, 0),
25+
last_response_time = agg.last_time,
26+
last_response_metadata_server_version = agg.last_version
27+
FROM
28+
(
29+
WITH signer_proposal_data AS (
30+
SELECT
31+
rss.signer_key,
32+
rss.cycle_number,
33+
bp.block_hash,
34+
bp.received_at AS proposal_received_at,
35+
br.accepted,
36+
br.received_at AS response_received_at,
37+
br.metadata_server_version,
38+
EXTRACT(EPOCH FROM (br.received_at - bp.received_at)) * 1000 AS response_time_ms
39+
FROM reward_set_signers rss
40+
JOIN block_proposals bp ON bp.reward_cycle = rss.cycle_number
41+
LEFT JOIN block_responses br ON br.signer_sighash = bp.block_hash AND br.signer_key = rss.signer_key
42+
),
43+
aggregated_data AS (
44+
SELECT
45+
signer_key,
46+
cycle_number,
47+
COUNT(CASE WHEN accepted = true THEN 1 END)::integer AS accepted_count,
48+
COUNT(CASE WHEN accepted = false THEN 1 END)::integer AS rejected_count,
49+
COUNT(CASE WHEN accepted IS NULL THEN 1 END)::integer AS missed_count,
50+
ROUND(AVG(response_time_ms), 3)::float8 AS avg_ms
51+
FROM signer_proposal_data
52+
GROUP BY signer_key, cycle_number
53+
),
54+
latest_response AS (
55+
SELECT
56+
signer_key,
57+
cycle_number,
58+
MAX(response_received_at) AS last_time,
59+
(array_agg(metadata_server_version ORDER BY response_received_at DESC))[1] AS last_version
60+
FROM signer_proposal_data
61+
WHERE response_received_at IS NOT NULL
62+
GROUP BY signer_key, cycle_number
63+
)
64+
SELECT
65+
agg.signer_key,
66+
agg.cycle_number,
67+
agg.accepted_count,
68+
agg.rejected_count,
69+
agg.missed_count,
70+
agg.avg_ms,
71+
lr.last_time,
72+
lr.last_version
73+
FROM aggregated_data agg
74+
LEFT JOIN latest_response lr ON lr.signer_key = agg.signer_key AND lr.cycle_number = agg.cycle_number
75+
) agg
76+
WHERE rss.signer_key = agg.signer_key AND rss.cycle_number = agg.cycle_number
77+
`);
78+
79+
// Drop old unused table that was not dropped in a previous migration.
80+
pgm.dropTable('reward_set_signers_old-no-slot-index');
81+
}
82+
83+
export function down(pgm: MigrationBuilder): void {
84+
pgm.sql(`
85+
UPDATE reward_set_signers
86+
SET
87+
last_response_time = NULL,
88+
last_response_metadata_server_version = NULL,
89+
proposals_accepted_count = 0,
90+
proposals_rejected_count = 0,
91+
proposals_missed_count = 0,
92+
average_response_time_ms = 0,
93+
signer_stacked_amount_percentage = 0,
94+
signer_stacked_amount_rank = 0,
95+
signer_weight_percentage = 0
96+
`);
97+
}

src/pg/ingestion/pg-write-store.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ export class PgWriteStore extends BasePgStoreModule {
467467
WHERE cycle_number = ${cycleNumber}
468468
),
469469
signer_ranks AS (
470-
SELECT signer_key, RANK() OVER (ORDER BY signer_stacked_amount DESC) AS rank
470+
SELECT signer_key, RANK() OVER (ORDER BY signer_stacked_amount DESC, signer_key ASC) AS rank
471471
FROM reward_set_signers
472472
WHERE cycle_number = ${cycleNumber}
473473
)

src/pg/pg-store.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export class PgStore extends BasePgStore {
5353
if (opts?.skipMigrations !== true) {
5454
while (true) {
5555
try {
56+
logger.info('Running migrations, this may take a while...');
5657
await runMigrations(MIGRATIONS_DIR, 'up', pgConfig);
5758
break;
5859
} catch (error) {

0 commit comments

Comments
 (0)