Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pi: Cache proposal statuses. #1586

Merged
merged 45 commits into from Dec 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
45084c4
[wip] pi: cache proposal statuses.
amass01 Nov 24, 2021
e9a7af7
cleanup & lint
amass01 Nov 26, 2021
56ce553
finalize proposal status caching
amass01 Nov 27, 2021
20b3e53
fix list of cacheable proposal statuses
amass01 Nov 27, 2021
9fa9827
cache vote status to avoid extra tlog tree read
amass01 Nov 28, 2021
7339925
typo
amass01 Nov 28, 2021
b8375ef
apply @lukebp suggestions
amass01 Nov 29, 2021
481ee3b
doc
amass01 Nov 29, 2021
b59bf09
doc
amass01 Nov 29, 2021
e8cf4c0
cleanup
amass01 Nov 29, 2021
4220db0
doc limit
amass01 Nov 29, 2021
3b10bde
cleanup
amass01 Nov 29, 2021
911ea00
more code review nits
amass01 Nov 29, 2021
c7e0bdb
improve logic paths
amass01 Nov 29, 2021
59bd598
one logic path to determine & cache status
amass01 Nov 29, 2021
24cf649
fix filenames
amass01 Nov 29, 2021
424f054
whoops
amass01 Nov 29, 2021
1b67f1d
cleanup
amass01 Nov 29, 2021
a3ab88c
simplify & cleanup for good
amass01 Nov 29, 2021
bdca766
tests cmdSummary command for final statuses
amass01 Nov 30, 2021
7582bc3
test cache get func
amass01 Nov 30, 2021
fb885ed
whooops
amass01 Nov 30, 2021
b39ef6c
add proposalStatuses.set unit tests
amass01 Dec 2, 2021
f5ee062
typos
amass01 Dec 2, 2021
350a711
cache capacity limit as a global var
amass01 Dec 2, 2021
7c20f2a
doc
amass01 Dec 2, 2021
b36738f
cleanup
amass01 Dec 2, 2021
6b4bd49
doc
amass01 Dec 2, 2021
d630c1a
more doc
amass01 Dec 2, 2021
fcf4b6f
code review nits
amass01 Dec 3, 2021
549973b
use slice of tests instead of array
amass01 Dec 3, 2021
5bb46c5
table driven tests for cache getter
amass01 Dec 3, 2021
74d74b5
Tweak logic. (#4)
lukebp Dec 3, 2021
0bf0ae3
typo
amass01 Dec 3, 2021
dc88536
don't fetch vote summary if cached vote status is final
amass01 Dec 3, 2021
75f497f
typo
amass01 Dec 3, 2021
172337c
cleanup setter tests & add overwrite test case
amass01 Dec 3, 2021
a53cdb4
the
amass01 Dec 3, 2021
ad6d77e
unique tokens in getter test
amass01 Dec 3, 2021
a1f12d4
cleanup
amass01 Dec 3, 2021
dcf06de
Move TestProposalStatus
amass01 Dec 3, 2021
d00d8f3
last couple of touches
amass01 Dec 3, 2021
6588101
.
amass01 Dec 3, 2021
f1a48fc
add debug statements to proposalStatuses.set
amass01 Dec 3, 2021
f4dc4ae
init pi plugin log
amass01 Dec 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
137 changes: 5 additions & 132 deletions politeiad/backendv2/tstorebe/plugins/pi/cmds.go
Expand Up @@ -244,63 +244,19 @@ func (p *piPlugin) cmdBillingStatusChanges(token []byte) (string, error) {

// cmdSummary returns the pi summary of a proposal.
amass01 marked this conversation as resolved.
Show resolved Hide resolved
func (p *piPlugin) cmdSummary(token []byte) (string, error) {
lukebp marked this conversation as resolved.
Show resolved Hide resolved
amass01 marked this conversation as resolved.
Show resolved Hide resolved
// Get an abridged version of the record. We only
// need the record metadata and the vote metadata.
r, err := p.record(backend.RecordRequest{
Token: token,
Filenames: []string{ticketvote.FileNameVoteMetadata},
})
if err != nil {
return "", err
}
var (
mdState = r.RecordMetadata.State
mdStatus = r.RecordMetadata.Status
voteStatus = ticketvote.VoteStatusInvalid

voteMD *ticketvote.VoteMetadata
bscs []pi.BillingStatusChange
)

// Pull the vote metadata out of the record files.
voteMD, err = voteMetadataDecode(r.Files)
if err != nil {
return "", err
}

// Fetch vote status & billing status change if they are needed in order
// to determine the proposal status.
if mdState == backend.StateVetted {
// If proposal status is public fetch vote status.
if mdStatus == backend.StatusPublic {
vs, err := p.voteSummary(token)
if err != nil {
return "", err
}
voteStatus = vs.Status
// If vote status is approved fetch billing status change.
if voteStatus == ticketvote.VoteStatusApproved {
bscs, err = p.billingStatusChanges(token)
if err != nil {
return "", err
}
}
}
}

// Determine the proposal status
proposalStatus, err := proposalStatus(mdState, mdStatus,
voteStatus, voteMD, bscs)
// Get the proposal status
propStatus, err := p.getProposalStatus(token)
if err != nil {
return "", err
}

// Prepare reply
// Prepare the reply
sr := pi.SummaryReply{
Summary: pi.ProposalSummary{
Status: proposalStatus,
Status: propStatus,
},
}

reply, err := json.Marshal(sr)
if err != nil {
return "", err
Expand All @@ -309,19 +265,6 @@ func (p *piPlugin) cmdSummary(token []byte) (string, error) {
return string(reply), nil
}

// statusChangeReason returns the last status change reason of a proposal.
// This function assumes the proposal has at least one status change.
func (p *piPlugin) lastStatusChangeReason(metadata []backend.MetadataStream) (string, error) {
// Decode status changes
statusChanges, err := statusChangesDecode(metadata)
if err != nil {
return "", err
}

// Return latest status change reason
return statusChanges[len(statusChanges)-1].Reason, nil
}

// statusChangesDecode decodes and returns the StatusChangeMetadata from the
// metadata streams if one is present.
func statusChangesDecode(metadata []backend.MetadataStream) ([]usermd.StatusChangeMetadata, error) {
Expand All @@ -348,34 +291,6 @@ func statusChangesDecode(metadata []backend.MetadataStream) ([]usermd.StatusChan
return statuses, nil
}

// proposalStatusApproved returns the proposal status of an approved proposal.
func proposalStatusApproved(voteMD *ticketvote.VoteMetadata, bscs []pi.BillingStatusChange) (pi.PropStatusT, error) {
// If the proposal in an RFP then we don't need to
// check the billing status changes. RFP proposals
// do not bill against the treasury. This does not
// apply to RFP submission proposals.
if isRFP(voteMD) {
return pi.PropStatusApproved, nil
}

// Use the billing status to determine the proposal status.
bs := proposalBillingStatus(ticketvote.VoteStatusApproved, bscs)
switch bs {
case pi.BillingStatusClosed:
return pi.PropStatusClosed, nil
case pi.BillingStatusCompleted:
return pi.PropStatusCompleted, nil
case pi.BillingStatusActive:
return pi.PropStatusActive, nil
}

// Shouldn't happen return an error
return pi.PropStatusInvalid,
errors.Errorf(
"couldn't determine proposal status of an approved propsoal: "+
"billingStatus: %v", bs)
}

// proposalBillingStatus accepts proposal's vote status with the billing status
// changes and returns the proposal's billing status.
func proposalBillingStatus(vs ticketvote.VoteStatusT, bscs []pi.BillingStatusChange) pi.BillingStatusT {
Expand All @@ -400,48 +315,6 @@ func proposalBillingStatus(vs ticketvote.VoteStatusT, bscs []pi.BillingStatusCha
return bs
}

// proposalStatus combines record metadata and plugin metadata in order to
// create a unified map of the various paths a proposal can take throughout
// the proposal process.
func proposalStatus(state backend.StateT, status backend.StatusT, voteStatus ticketvote.VoteStatusT, voteMD *ticketvote.VoteMetadata, bscs []pi.BillingStatusChange) (pi.PropStatusT, error) {
switch state {
case backend.StateUnvetted:
switch status {
case backend.StatusUnreviewed:
return pi.PropStatusUnvetted, nil
case backend.StatusArchived:
return pi.PropStatusUnvettedAbandoned, nil
case backend.StatusCensored:
return pi.PropStatusUnvettedCensored, nil
}
case backend.StateVetted:
switch status {
case backend.StatusArchived:
return pi.PropStatusAbandoned, nil
case backend.StatusCensored:
return pi.PropStatusCensored, nil
case backend.StatusPublic:
switch voteStatus {
case ticketvote.VoteStatusUnauthorized:
return pi.PropStatusUnderReview, nil
case ticketvote.VoteStatusAuthorized:
return pi.PropStatusVoteAuthorized, nil
case ticketvote.VoteStatusStarted:
return pi.PropStatusVoteStarted, nil
case ticketvote.VoteStatusRejected:
return pi.PropStatusRejected, nil
case ticketvote.VoteStatusApproved:
return proposalStatusApproved(voteMD, bscs)
}
}
}
// Shouldn't happen return an error
return pi.PropStatusInvalid,
errors.Errorf(
"couldn't determine proposal status: proposal state: %v, "+
"proposal status %v, vote status: %v", state, status, voteStatus)
}

// record returns a record from the backend with it's contents filtered
// according to the provided record request.
//
Expand Down