Skip to content

Commit

Permalink
Add backup logic
Browse files Browse the repository at this point in the history
  • Loading branch information
zivkovicmilos committed Oct 3, 2023
1 parent f0fa1a9 commit a31f8bb
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 12 deletions.
138 changes: 130 additions & 8 deletions backup/backup.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,145 @@
package backup

import (
"encoding/json"
"fmt"
"os"

"github.com/gnolang/tx-archive/backup/client"
"github.com/gnolang/tx-archive/log"
"github.com/gnolang/tx-archive/types"
)

// ExecuteBackup executes the node backup process
func ExecuteBackup(
_ client.Client,
_ log.Logger,
_ Config,
client client.Client,
logger log.Logger,
cfg Config,
) error {
// Verify the output file can be generated
// TODO add functionality
// Verify the config
if cfgErr := ValidateConfig(cfg); cfgErr != nil {
return fmt.Errorf("invalid config, %w", cfgErr)
}

// Open the file for writing
outputFile, openErr := os.OpenFile(
cfg.OutputFile,
os.O_RDWR|os.O_CREATE|os.O_TRUNC,
0o755,
)
if openErr != nil {
return fmt.Errorf("unable to open file %s, %w", cfg.OutputFile, openErr)
}

closeFile := func() error {
if err := outputFile.Close(); err != nil {
logger.Error("unable to close output file", "err", err.Error())

return err
}

return nil
}

teardown := func() {
if err := closeFile(); err != nil {
if removeErr := os.Remove(outputFile.Name()); removeErr != nil {
logger.Error("unable to remove file", "err", err.Error())
}
}
}

// Set up the teardown
defer teardown()

// Determine the right bound
// TODO add functionality
toBlock, boundErr := determineRightBound(client, cfg.ToBlock)
if boundErr != nil {
return fmt.Errorf("unable to determine right bound, %w", boundErr)
}

// Gather the chain data from the node
// TODO add functionality
blockData, blockDataErr := getBlockData(client, logger, cfg.FromBlock, toBlock)
if blockDataErr != nil {
return fmt.Errorf("unable to fetch block data, %w", blockDataErr)
}

// Marshal the response
blockDataRaw, marshalErr := json.Marshal(blockData)
if marshalErr != nil {
return fmt.Errorf("unable to marshal block data JSON, %w", marshalErr)
}

// Write the chain data to a file
// TODO add functionality
_, writeErr := outputFile.Write(blockDataRaw)
if writeErr != nil {
return fmt.Errorf("unable to write block data JSON, %w", writeErr)
}

return nil
}

// determineRightBound determines the
// right bound for the chain backup (block height)
func determineRightBound(
client client.Client,
potentialTo *uint64,
) (uint64, error) {
// Get the latest block height from the chain
latestBlockNumber, err := client.GetLatestBlockNumber()
if err != nil {
return 0, fmt.Errorf("unable to fetch latest block number, %w", err)
}

// Check if the chain has the block
if potentialTo != nil && *potentialTo < latestBlockNumber {
// Requested right bound is valid, use it
return *potentialTo, nil
}

// Requested right bound is not valid, use the latest block number
return latestBlockNumber, nil
}

// getBlockData fetches the block data from the chain
func getBlockData(
client client.Client,
logger log.Logger,
from,
to uint64,
) ([]*types.BlockData, error) {
blockData := make([]*types.BlockData, 0, to-from+1)

for block := from; block < to; block++ {
txs, txErr := client.GetBlockTransactions(block)
if txErr != nil {
return nil, fmt.Errorf("unable to fetch block transactions, %w", txErr)
}

// Save the block transaction data
data := &types.BlockData{
Txs: txs,
BlockNum: block,
}
blockData = append(blockData, data)

// Log the progress
logProgress(logger, from, to, block)
}

return blockData, nil
}

// logProgress logs the backup progress
func logProgress(logger log.Logger, from, to, current uint64) {
total := to - from
progress := 100 * (float64(current) - float64(from)) / float64(total)

logger.Info(
fmt.Sprintf("Total of %d blocks backed up", current-from+1),
"total", total,
"from", from,
"to", true,
"status", fmt.Sprintf("%.2f%%", progress),
)
}
7 changes: 6 additions & 1 deletion backup/client/client.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
package client

type Client interface{}
import "github.com/gnolang/gno/tm2/pkg/std"

type Client interface {
GetLatestBlockNumber() (uint64, error)
GetBlockTransactions(uint64) ([]std.Tx, error)
}
6 changes: 3 additions & 3 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "github.com/gnolang/gno/tm2/pkg/std"

// Archive wraps the backed-up chain data
type Archive struct {
ChainData ChainData `json:"chainData"`
ChainData BlockData `json:"chainData"`
Metadata Metadata `json:"metadata"`
}

Expand All @@ -17,8 +17,8 @@ type Metadata struct {
LatestTxHash uint64 `json:"latestTxHash"`
}

// ChainData contains the historical transaction data
type ChainData struct {
// BlockData contains the historical transaction data
type BlockData struct {
Txs []std.Tx `json:"txs"`
BlockNum uint64 `json:"blockNum"`
}

0 comments on commit a31f8bb

Please sign in to comment.