Skip to content

Commit

Permalink
ticketvote: Move inventory cache to db.
Browse files Browse the repository at this point in the history
This commit rewrites the ticketvote inventory cache.

The initial plugin implementations were part of an extremely large
commit that added the tstore backend. The caches were saved to the file
system as a quick and dirty way to get things into production, with the
intention of revisting them at a later date. API was later added that
allowed the plugins to cache data in the tstore database.

The new inventory cache that was added in this commit has an improved
API, better documentation, and was moved off of the file system and
into the tstore database.
  • Loading branch information
lukebp authored Jul 5, 2022
1 parent 9366695 commit 6f6bcc0
Show file tree
Hide file tree
Showing 5 changed files with 731 additions and 765 deletions.
63 changes: 39 additions & 24 deletions politeiad/backendv2/tstorebe/plugins/ticketvote/cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"sort"
"strconv"
Expand All @@ -23,6 +22,7 @@ import (
"github.com/decred/politeia/politeiad/plugins/dcrdata"
"github.com/decred/politeia/politeiad/plugins/ticketvote"
"github.com/decred/politeia/util"
"github.com/pkg/errors"
)

const (
Expand Down Expand Up @@ -153,7 +153,7 @@ func (p *ticketVotePlugin) cmdAuthorize(token []byte, payload string) (string, e
return "", err
}

// Update inventory
// Update the cached inventory
var status ticketvote.VoteStatusT
switch a.Action {
case ticketvote.AuthActionAuthorize:
Expand All @@ -162,9 +162,9 @@ func (p *ticketVotePlugin) cmdAuthorize(token []byte, payload string) (string, e
status = ticketvote.VoteStatusUnauthorized
default:
// Action has already been validated. This should not happen.
return "", fmt.Errorf("invalid action %v", a.Action)
return "", errors.Errorf("invalid action %v", a.Action)
}
p.inventoryUpdate(a.Token, status)
p.inv.UpdateEntryPreVote(auth.Token, status, auth.Timestamp)

// Prepare reply
ar := ticketvote.AuthorizeReply{
Expand Down Expand Up @@ -545,9 +545,9 @@ func (p *ticketVotePlugin) startStandard(token []byte, s ticketvote.Start) (*tic
return nil, err
}

// Update inventory
p.inventoryUpdateToStarted(vd.Params.Token, ticketvote.VoteStatusStarted,
vd.EndBlockHeight)
// Update the cached inventory
p.inv.UpdateEntryPostVote(vd.Params.Token,
ticketvote.VoteStatusStarted, vd.EndBlockHeight)

// Update active votes cache
p.activeVotesAdd(vd)
Expand Down Expand Up @@ -689,11 +689,11 @@ func (p *ticketVotePlugin) startRunoffForSub(token []byte, srs startRunoffSubmis
// Save vote details
err = p.voteDetailsSave(token, vd)
if err != nil {
return fmt.Errorf("voteDetailsSave %x: %v", token, err)
return err
}

// Update inventory
p.inventoryUpdateToStarted(vd.Params.Token,
// Update the cached inventory
p.inv.UpdateEntryPostVote(vd.Params.Token,
ticketvote.VoteStatusStarted, vd.EndBlockHeight)

// Update active votes cache
Expand Down Expand Up @@ -1814,28 +1814,43 @@ func (p *ticketVotePlugin) cmdInventory(payload string) (string, error) {
return "", err
}

// Get best block. This command does not write any data so we can
// use the unsafe best block.
bb, err := p.bestBlockUnsafe()
// Get the best block. This command does not write
// any data so we can use the unsafe best block.
bestBlock, err := p.bestBlockUnsafe()
if err != nil {
return "", fmt.Errorf("bestBlockUnsafe: %v", err)
return "", err
}

// Get the inventory
ibs, err := p.inventoryByStatus(bb, i.Status, i.Page)
if err != nil {
return "", fmt.Errorf("invByStatus: %v", err)
}
tokens := make(map[string][]string, 256)
switch i.Status {
case ticketvote.VoteStatusInvalid:
// No vote status was provided. Return a
// page of results for all vote statuses.
inv, err := p.inv.GetPage(bestBlock)
if err != nil {
return "", err
}
for status, entries := range inv.Entries {
statusStr := ticketvote.VoteStatuses[status]
tokens[statusStr] = entryTokens(entries)
}

// Prepare reply
tokens := make(map[string][]string, len(ibs.Tokens))
for k, v := range ibs.Tokens {
vs := ticketvote.VoteStatuses[k]
tokens[vs] = v
default:
// A vote status was provided. Return a page of results for the
// provided status.
entries, err := p.inv.GetPageForStatus(bestBlock, i.Status, i.Page)
if err != nil {
return "", err
}
statusStr := ticketvote.VoteStatuses[i.Status]
tokens[statusStr] = entryTokens(entries)
}

// Prepare the reply
ir := ticketvote.InventoryReply{
Tokens: tokens,
BestBlock: ibs.BestBlock,
BestBlock: bestBlock,
}
reply, err := json.Marshal(ir)
if err != nil {
Expand Down
31 changes: 18 additions & 13 deletions politeiad/backendv2/tstorebe/plugins/ticketvote/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,26 +64,31 @@ func (p *ticketVotePlugin) hookSetRecordStatusPost(payload string) error {
return err
}

// Ticketvote caches only need to be updated for vetted records
if srs.RecordMetadata.State == backend.StateUnvetted {
// ticketvote plugin commands can only be run on
// vetted records. We can skip all hooks when the
// record is not vetted.
recordMD := srs.RecordMetadata
if recordMD.State == backend.StateUnvetted {
return nil
}

// Update the inventory cache
switch srs.RecordMetadata.Status {
// Update the cached inventory
switch recordMD.Status {
case backend.StatusPublic:
// Add to inventory
p.inventoryAdd(srs.RecordMetadata.Token,
ticketvote.VoteStatusUnauthorized)
// Add a new entry to the inventory for this record
p.inv.AddEntry(recordMD.Token, ticketvote.VoteStatusUnauthorized,
recordMD.Timestamp)

case backend.StatusCensored, backend.StatusArchived:
// These statuses do not allow for a vote. Mark as ineligible.
p.inventoryUpdate(srs.RecordMetadata.Token,
ticketvote.VoteStatusIneligible)
// These statuses are not allowed to be voted on. Update the inventory
// to reflect that this record is ineligible for a vote.
p.inv.UpdateEntryPreVote(recordMD.Token, ticketvote.VoteStatusIneligible,
recordMD.Timestamp)
}

// Update cached vote metadata
return p.voteMetadataCacheOnStatusChange(srs.RecordMetadata.Token,
srs.RecordMetadata.State, srs.RecordMetadata.Status, srs.Record.Files)
// Update the cached vote metadata
return p.voteMetadataCacheOnStatusChange(recordMD.Token,
recordMD.State, recordMD.Status, srs.Record.Files)
}

// linkByVerify verifies that the provided link by timestamp meets all
Expand Down
Loading

0 comments on commit 6f6bcc0

Please sign in to comment.