Skip to content

Commit

Permalink
chore: fetch all updated proposals in one tx for commenting in discourse
Browse files Browse the repository at this point in the history
  • Loading branch information
1emu committed Oct 20, 2023
1 parent 392a6d7 commit 1728469
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 22 deletions.
5 changes: 4 additions & 1 deletion src/back/routes/proposal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,10 @@ export async function updateProposalStatus(req: WithAuth<Request<{ proposal: str
NotificationService.grantProposalEnacted(proposal)
}

DiscourseService.commentProposalUpdateInDiscourse(proposal.id)
const updatedProposal: ProposalAttributes | undefined = await ProposalModel.findOne<ProposalAttributes>({
id,
})
updatedProposal && DiscourseService.commentUpdatedProposal(updatedProposal)

return {
...proposal,
Expand Down
2 changes: 1 addition & 1 deletion src/entities/Proposal/jobs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('finishProposals', () => {
beforeAll(() => {
jest.spyOn(ProposalModel, 'getFinishProposalQuery')
jest.spyOn(CoauthorModel, 'findAllByProposals').mockResolvedValue([])
jest.spyOn(DiscourseService, 'commentProposalUpdateInDiscourse').mockImplementation(() => {})
jest.spyOn(DiscourseService, 'commentUpdatedProposal').mockImplementation(() => {})
jest.spyOn(DiscordService, 'init').mockImplementation(() => {})
jest.spyOn(DiscordService, 'finishProposal').mockImplementation(() => {})
jest.spyOn(DiscordService, 'newProposal').mockImplementation(() => {})
Expand Down
6 changes: 3 additions & 3 deletions src/entities/Proposal/jobs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ function updateCategoryBudget(proposal: ProposalAttributes, budgetForProposal: B
}

async function getProposalsVotingResult(proposals: ProposalAttributes[]) {
const pendingProposalsVotingResult: ProposalVotingResult[] = []
const proposalsWithVotingResult: ProposalVotingResult[] = []
for (const proposal of proposals) {
const outcome = await calculateVotingResult(proposal)
if (!outcome) {
continue
}
pendingProposalsVotingResult.push({ ...proposal, ...outcome })
proposalsWithVotingResult.push({ ...proposal, ...outcome })
}
return pendingProposalsVotingResult
return proposalsWithVotingResult
}

export async function getFinishableLinkedProposals(
Expand Down
13 changes: 13 additions & 0 deletions src/entities/Proposal/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,19 @@ export default class ProposalModel extends Model<ProposalAttributes> {
return results.map((item) => ProposalModel.parse(item))
}

static async findByIds(ids: string[]): Promise<ProposalAttributes[]> {
const query = SQL`
SELECT *
FROM ${table(ProposalModel)}
WHERE "id" IN (${join(
ids.map((id) => SQL`${id}`),
SQL`, `
)})`

const results = await this.namedQuery('find_by_ids', query)
return results.map((item) => ProposalModel.parse(item))
}

static async getSitemapProposals(page: number): Promise<{ id: string }[]> {
const query = SQL`
SELECT id
Expand Down
27 changes: 10 additions & 17 deletions src/services/DiscourseService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import ProposalModel from '../entities/Proposal/model'
import { ProposalWithOutcome } from '../entities/Proposal/outcome'
import * as proposalTemplates from '../entities/Proposal/templates'
import { getUpdateMessage } from '../entities/Proposal/templates/messages'
import { ProposalAttributes, ProposalStatus } from '../entities/Proposal/types'
import { ProposalAttributes } from '../entities/Proposal/types'
import { forumUrl, proposalUrl } from '../entities/Proposal/utils'
import * as updateTemplates from '../entities/Updates/templates'
import { UpdateAttributes } from '../entities/Updates/types'
Expand Down Expand Up @@ -154,18 +154,10 @@ export class DiscourseService {
}
}

// TODO: change getUpdateMessage to receive update values instead of having to fetch updated proposal
// TODO: votes are not necessary in all cases, they could be fetched only when needed
static commentProposalUpdateInDiscourse(id: string) {
static commentUpdatedProposal(updatedProposal: ProposalAttributes) {
inBackground(async () => {
const updatedProposal: ProposalAttributes | undefined = await ProposalModel.findOne<ProposalAttributes>({
id,
})
if (!updatedProposal) {
logger.error('Invalid proposal id for discourse update', { id })
return
}
const votes = await VoteService.getVotes(id)
// TODO: votes are not necessary in all cases, they could be fetched only when needed
const votes = await VoteService.getVotes(updatedProposal.id)
const updateMessage = getUpdateMessage(updatedProposal, votes)
const discourseComment: DiscourseComment = {
topic_id: updatedProposal.discourse_topic_id,
Expand All @@ -177,11 +169,12 @@ export class DiscourseService {
}

static commentFinishedProposals(proposalsWithOutcome: ProposalWithOutcome[]) {
proposalsWithOutcome.forEach((proposal) => {
//TODO: is it ok that we only notify finished proposals? (what about passed/rejected/OOB?)
if (proposal.newStatus === ProposalStatus.Finished) {
this.commentProposalUpdateInDiscourse(proposal.id)
}
inBackground(async () => {
const ids = proposalsWithOutcome.map(({ id }) => id)
const updatedProposals = await ProposalModel.findByIds(ids)
updatedProposals.forEach((proposal) => {
this.commentUpdatedProposal(proposal)
})
})
}
}

0 comments on commit 1728469

Please sign in to comment.