Skip to content

Commit

Permalink
feat: use GetMissingHeights() in enqueueMissingBlocks() & in `par…
Browse files Browse the repository at this point in the history
…se blocks` cmd (#89)

## Description


following the request from @maiquanghiep : https://forbole.atlassian.net/browse/BDU-489?focusedCommentId=17477

## Checklist
- [x] Targeted PR against correct branch.
- [x] Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
- [ ] Wrote unit tests.  
- [x] Re-reviewed `Files changed` in the Github PR explorer.
  • Loading branch information
huichiaotsou authored Dec 28, 2022
1 parent b73251c commit 86c1cc5
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## Unreleased
### Changes
- ([\#74](https://github.com/forbole/juno/pull/74)) Applied `GetMissingHeights()` in `enqueueMissingBlocks()` & in `parse blocks missing` cmd

## v4.0.0
### Changes
- Updated cosmos/cosmos-sdk to `v0.45.8`
Expand Down
2 changes: 1 addition & 1 deletion cmd/parse/blocks/blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const (
func newAllCmd(parseConfig *parsecmdtypes.Config) *cobra.Command {
cmd := &cobra.Command{
Use: "all",
Short: "Fix missing blocks and transactions in database",
Short: "Reparse blocks and transactions ranged from the given start height to the given end height",
Long: fmt.Sprintf(`Refetch all the blocks in the specified range and stores them inside the database.
You can specify a custom blocks range by using the %s and %s flags.
By default, all the blocks fetched from the node will not be stored inside the database if they are already present.
Expand Down
1 change: 1 addition & 0 deletions cmd/parse/blocks/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func NewBlocksCmd(parseConfig *parsecmdtypes.Config) *cobra.Command {

cmd.AddCommand(
newAllCmd(parseConfig),
newMissingCmd(parseConfig),
)

return cmd
Expand Down
52 changes: 52 additions & 0 deletions cmd/parse/blocks/missing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package blocks

import (
"fmt"
"strconv"

parsecmdtypes "github.com/forbole/juno/v4/cmd/parse/types"

"github.com/spf13/cobra"

"github.com/forbole/juno/v4/parser"
"github.com/forbole/juno/v4/types/config"
)

// newMissingCmd returns a Cobra command that allows to fix missing blocks in database
func newMissingCmd(parseConfig *parsecmdtypes.Config) *cobra.Command {
cmd := &cobra.Command{
Use: "missing [start height]",
Short: "Refetch all the missing heights in the database starting from the given start height",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
startHeight, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
return fmt.Errorf("make sure the given start height is a positive integer")
}

parseCtx, err := parsecmdtypes.GetParserContext(config.Cfg, parseConfig)
if err != nil {
return err
}

workerCtx := parser.NewContext(parseCtx.EncodingConfig, parseCtx.Node, parseCtx.Database, parseCtx.Logger, parseCtx.Modules)
worker := parser.NewWorker(workerCtx, nil, 0)

dbLastHeight, err := parseCtx.Database.GetLastBlockHeight()
if err != nil {
return fmt.Errorf("error while getting DB last block height: %s", err)
}

for _, k := range parseCtx.Database.GetMissingHeights(startHeight, dbLastHeight) {
err = worker.Process(k)
if err != nil {
return fmt.Errorf("error while re-fetching block %d: %s", k, err)
}
}

return nil
},
}

return cmd
}
2 changes: 1 addition & 1 deletion cmd/start/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func enqueueMissingBlocks(exportQueue types.HeightQueue, ctx *parser.Context) {
}
} else {
ctx.Logger.Info("syncing missing blocks...", "latest_block_height", latestBlockHeight)
for i := startHeight; i <= latestBlockHeight; i++ {
for _, i := range ctx.Database.GetMissingHeights(startHeight, latestBlockHeight) {
ctx.Logger.Debug("enqueueing missing block", "height", i)
exportQueue <- i
}
Expand Down
3 changes: 3 additions & 0 deletions database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ type Database interface {
// An error is returned if the operation fails.
GetLastBlockHeight() (int64, error)

// GetMissingHeights returns a slice of missing block heights between startHeight and endHeight
GetMissingHeights(startHeight, endHeight int64) []int64

// SaveBlock will be called when a new block is parsed, passing the block itself
// and the transactions contained inside that block.
// An error is returned if the operation fails.
Expand Down
16 changes: 16 additions & 0 deletions database/postgresql/postgresql.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,22 @@ func (db *Database) GetLastBlockHeight() (int64, error) {
return height, nil
}

// GetMissingHeights returns a slice of missing block heights between startHeight and endHeight
func (db *Database) GetMissingHeights(startHeight, endHeight int64) []int64 {
var result []int64
stmt := `SELECT generate_series($1::int,$2::int) EXCEPT SELECT height FROM block ORDER BY 1;`
err := db.SQL.Select(&result, stmt, startHeight, endHeight)
if err != nil {
return nil
}

if len(result) == 0 {
return nil
}

return result
}

// SaveBlock implements database.Database
func (db *Database) SaveBlock(block *types.Block) error {
sqlStatement := `
Expand Down

0 comments on commit 86c1cc5

Please sign in to comment.