Skip to content

Commit 2c0984d

Browse files
authored
Merge pull request #158 from Giveth/add_boost_options
Add temporary legacy power boosting sync with rebalance and cache refresh
2 parents b88f179 + fa141ad commit 2c0984d

27 files changed

+2274
-80
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Temporary legacy power boosting sync (`boost_temp`)
2+
3+
TODO(boost_temp): remove after legacy power boosting migration is complete.
4+
5+
This code path allows the new backend to:
6+
7+
1. receive power boosting payloads from the new FE,
8+
2. write those payloads to legacy DB `public.power_boosting`,
9+
3. read back authoritative legacy state and ranking view data,
10+
4. persist only listing-related fields into the new DB.
11+
12+
Single-project updates follow legacy rebalancing behavior:
13+
- if it is the first boosted project, percentage must be `100`
14+
- otherwise, other boosted projects are recalculated proportionally so total stays `100`
15+
- a rounding residual fix is applied so the persisted total is exactly `100.00`
16+
17+
## Environment variables
18+
19+
- `LEGACY_DATABASE_URL` (reused; schema comes from `?schema=...` or defaults to `public`)
20+
21+
## Removal checklist
22+
23+
1. Delete files containing `boost_temp`.
24+
2. Remove temp providers from `power-boosting.module.ts`.
25+
3. Remove `syncPowerBoostingTemp` GraphQL mutation.
26+
4. Remove `syncPowerBoostingTemp` and any `boost_temp` references in env/docs.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@
8383
"reflect-metadata": "^0.2.2",
8484
"rxjs": "^7.8.2",
8585
"slugify": "^1.6.6",
86-
"styled-components": "^6.1.13"
86+
"styled-components": "^6.1.13",
87+
"typeorm": "^0.3.28"
8788
},
8889
"devDependencies": {
8990
"@eslint/eslintrc": "^3.3.1",

pnpm-lock.yaml

Lines changed: 106 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ALTER TABLE "projects"
2+
ADD COLUMN IF NOT EXISTS "total_power" DOUBLE PRECISION;
3+
4+
CREATE INDEX IF NOT EXISTS "projects_total_power_idx"
5+
ON "projects"("total_power");

prisma/schema.prisma

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ model Project {
8181
updatedAt DateTime @updatedAt @map("updated_at")
8282
projectType String @default("project") @map("project_type")
8383
powerRank Int? @map("power_rank")
84+
totalPower Float? @map("total_power")
8485
latestUpdateCreationDate DateTime? @map("latest_update_creation_date")
8586
status ProjectStatus? @map("status")
8687
donations Donation[]
@@ -100,6 +101,7 @@ model Project {
100101
@@index([isGivbacksEligible])
101102
@@index([adminUserId])
102103
@@index([slug])
104+
@@index([totalPower])
103105
@@index([title(ops: raw("gin_trgm_ops"))], type: Gin)
104106
@@index([description(ops: raw("gin_trgm_ops"))], type: Gin)
105107
@@map("projects")

src/common/enums/sorting.enum.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export enum ProjectSortField {
1414
CreatedAt = 'createdAt',
1515
UpdatedAt = 'updatedAt',
1616
TotalDonations = 'totalDonations',
17-
QualityScore = 'qualityScore',
17+
TotalPower = 'totalPower',
1818
Relevance = 'relevance',
1919
QfDonations = 'qfDonations',
2020
}

src/cronjobs/legacy-data-sync/legacy-data-sync.service.ts

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ interface LegacyProject {
124124
countUniqueDonorsForActiveQfRound: number | null
125125
countUniqueDonors: number | null
126126
qualityScore: number
127+
totalPower: number | null
127128
adminUserId: number
128129
creationDate: Date | null
129130
updatedAt: Date | null
@@ -1088,14 +1089,22 @@ export class LegacyDataSyncService implements OnModuleDestroy {
10881089
while (offset < totalCount) {
10891090
const projects = await this.queryLegacyDb<LegacyProject>(
10901091
`SELECT
1091-
id, title, slug, "slugHistory", description, "descriptionSummary",
1092-
image, "impactLocation", verified, "verificationStatus", "reviewStatus",
1093-
"totalDonations", "totalReactions", "totalProjectUpdates",
1094-
"sumDonationValueUsdForActiveQfRound", "countUniqueDonorsForActiveQfRound",
1095-
"countUniqueDonors", "qualityScore", "adminUserId", "creationDate", "updatedAt",
1096-
"statusId", "isGivbackEligible", "latestUpdateCreationDate"
1097-
FROM project
1098-
ORDER BY id
1092+
p.id, p.title, p.slug, p."slugHistory", p.description, p."descriptionSummary",
1093+
p.image, p."impactLocation", p.verified, p."verificationStatus", p."reviewStatus",
1094+
p."totalDonations", p."totalReactions", p."totalProjectUpdates",
1095+
p."sumDonationValueUsdForActiveQfRound", p."countUniqueDonorsForActiveQfRound",
1096+
p."countUniqueDonors", p."qualityScore", ppv."totalPower", p."adminUserId",
1097+
p."creationDate", p."updatedAt", p."statusId", p."isGivbackEligible",
1098+
p."latestUpdateCreationDate"
1099+
FROM project p
1100+
LEFT JOIN LATERAL (
1101+
SELECT "totalPower"
1102+
FROM project_power_view ppv
1103+
WHERE ppv."projectId" = p.id
1104+
ORDER BY ppv."round" DESC NULLS LAST
1105+
LIMIT 1
1106+
) ppv ON TRUE
1107+
ORDER BY p.id
10991108
LIMIT $1 OFFSET $2`,
11001109
[this.batchSize, offset],
11011110
)
@@ -1135,7 +1144,7 @@ export class LegacyDataSyncService implements OnModuleDestroy {
11351144
${p.totalDonations}, ${p.totalReactions}, ${p.totalProjectUpdates ?? 'NULL'},
11361145
${p.sumDonationValueUsdForActiveQfRound ?? 'NULL'},
11371146
${p.countUniqueDonorsForActiveQfRound ?? 'NULL'},
1138-
${p.countUniqueDonors ?? 'NULL'}, ${p.qualityScore ?? 0}, ${p.adminUserId},
1147+
${p.countUniqueDonors ?? 'NULL'}, ${p.qualityScore ?? 0}, ${p.totalPower ?? 'NULL'}, ${p.adminUserId},
11391148
'${p.createdAt}', NOW(),
11401149
${p.latestUpdateCreationDate ? `'${new Date(p.latestUpdateCreationDate).toISOString()}'` : 'NULL'})`,
11411150
)
@@ -1147,7 +1156,7 @@ export class LegacyDataSyncService implements OnModuleDestroy {
11471156
image, impact_location, vouched, is_givbacks_eligible, review_status, status,
11481157
total_donations, total_reactions, total_project_updates,
11491158
sum_donation_value_usd_for_active_qf_round, count_unique_donors_for_active_qf_round,
1150-
count_unique_donors, quality_score, admin_user_id, created_at, updated_at,
1159+
count_unique_donors, quality_score, total_power, admin_user_id, created_at, updated_at,
11511160
latest_update_creation_date)
11521161
VALUES ${values}
11531162
ON CONFLICT (id) DO UPDATE SET
@@ -1169,6 +1178,7 @@ export class LegacyDataSyncService implements OnModuleDestroy {
11691178
count_unique_donors_for_active_qf_round = EXCLUDED.count_unique_donors_for_active_qf_round,
11701179
count_unique_donors = EXCLUDED.count_unique_donors,
11711180
quality_score = EXCLUDED.quality_score,
1181+
total_power = EXCLUDED.total_power,
11721182
admin_user_id = EXCLUDED.admin_user_id,
11731183
latest_update_creation_date = EXCLUDED.latest_update_creation_date,
11741184
updated_at = NOW()
@@ -1954,6 +1964,26 @@ export class LegacyDataSyncService implements OnModuleDestroy {
19541964
`)
19551965
}
19561966

1967+
// Legacy sync inserts explicit IDs. Reset sequence so future inserts
1968+
// (e.g. boost_temp Prisma upserts that create rows) don't collide on PK(id).
1969+
// Keep setval monotonic so concurrent inserts cannot move it backwards.
1970+
try {
1971+
await this.prisma.$executeRawUnsafe(`
1972+
SELECT setval(
1973+
pg_get_serial_sequence('"power_boostings"', 'id'),
1974+
GREATEST(
1975+
COALESCE((SELECT MAX(id) FROM "power_boostings"), 0) + 1,
1976+
(SELECT last_value FROM "power_boostings_id_seq")
1977+
),
1978+
false
1979+
)
1980+
`)
1981+
} catch (error) {
1982+
this.logger.warn(
1983+
`Failed to reset power_boostings id sequence after legacy sync: ${error.message}`,
1984+
)
1985+
}
1986+
19571987
this.logger.log(`Synced ${validPowerBoostings.length} power boostings`)
19581988
return { synced: validPowerBoostings.length }
19591989
}

0 commit comments

Comments
 (0)