Add database transactions to postgres repository
* Repository returns error when CreateBlock fails.
This commit is contained in:
parent
d3b3da7f17
commit
df9e7ebcc5
@ -24,8 +24,9 @@ func NewInMemory() *InMemory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repository *InMemory) CreateBlock(block core.Block) {
|
func (repository *InMemory) CreateBlock(block core.Block) error {
|
||||||
repository.blocks[block.Number] = &block
|
repository.blocks[block.Number] = &block
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repository *InMemory) BlockCount() int {
|
func (repository *InMemory) BlockCount() int {
|
||||||
|
@ -3,6 +3,9 @@ package repositories
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"errors"
|
||||||
"github.com/8thlight/vulcanizedb/pkg/core"
|
"github.com/8thlight/vulcanizedb/pkg/core"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
@ -12,6 +15,10 @@ type Postgres struct {
|
|||||||
Db *sqlx.DB
|
Db *sqlx.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrDBInsertFailed = errors.New("postgres: insert failed")
|
||||||
|
)
|
||||||
|
|
||||||
func (repository Postgres) MaxBlockNumber() int64 {
|
func (repository Postgres) MaxBlockNumber() int64 {
|
||||||
var highestBlockNumber int64
|
var highestBlockNumber int64
|
||||||
repository.Db.Get(&highestBlockNumber, `SELECT MAX(block_number) FROM blocks`)
|
repository.Db.Get(&highestBlockNumber, `SELECT MAX(block_number) FROM blocks`)
|
||||||
@ -57,25 +64,41 @@ func (repository Postgres) BlockCount() int {
|
|||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repository Postgres) CreateBlock(block core.Block) {
|
func (repository Postgres) CreateBlock(block core.Block) error {
|
||||||
insertedBlock := repository.Db.QueryRow(
|
tx, _ := repository.Db.BeginTx(context.Background(), nil)
|
||||||
|
var blockId int64
|
||||||
|
err := tx.QueryRow(
|
||||||
`INSERT INTO blocks
|
`INSERT INTO blocks
|
||||||
(block_number, block_gaslimit, block_gasused, block_time, block_difficulty, block_hash, block_nonce, block_parenthash, block_size, uncle_hash)
|
(block_number, block_gaslimit, block_gasused, block_time, block_difficulty, block_hash, block_nonce, block_parenthash, block_size, uncle_hash)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING id`,
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
||||||
block.Number, block.GasLimit, block.GasUsed, block.Time, block.Difficulty, block.Hash, block.Nonce, block.ParentHash, block.Size, block.UncleHash)
|
RETURNING id `,
|
||||||
var blockId int64
|
block.Number, block.GasLimit, block.GasUsed, block.Time, block.Difficulty, block.Hash, block.Nonce, block.ParentHash, block.Size, block.UncleHash).
|
||||||
insertedBlock.Scan(&blockId)
|
Scan(&blockId)
|
||||||
repository.createTransactions(blockId, block.Transactions)
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return ErrDBInsertFailed
|
||||||
|
}
|
||||||
|
err = repository.createTransactions(tx, blockId, block.Transactions)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return ErrDBInsertFailed
|
||||||
|
}
|
||||||
|
tx.Commit()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repository Postgres) createTransactions(blockId int64, transactions []core.Transaction) {
|
func (repository Postgres) createTransactions(tx *sql.Tx, blockId int64, transactions []core.Transaction) error {
|
||||||
for _, transaction := range transactions {
|
for _, transaction := range transactions {
|
||||||
repository.Db.MustExec(
|
_, err := tx.Exec(
|
||||||
`INSERT INTO transactions
|
`INSERT INTO transactions
|
||||||
(block_id, tx_hash, tx_nonce, tx_to, tx_gaslimit, tx_gasprice, tx_value)
|
(block_id, tx_hash, tx_nonce, tx_to, tx_gaslimit, tx_gasprice, tx_value)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7)`,
|
VALUES ($1, $2, $3, $4, $5, $6, $7)`,
|
||||||
blockId, transaction.Hash, transaction.Nonce, transaction.To, transaction.GasLimit, transaction.GasPrice, transaction.Value)
|
blockId, transaction.Hash, transaction.Nonce, transaction.To, transaction.GasLimit, transaction.GasPrice, transaction.Value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repository Postgres) loadBlock(blockRows *sql.Rows) core.Block {
|
func (repository Postgres) loadBlock(blockRows *sql.Rows) core.Block {
|
||||||
@ -107,7 +130,7 @@ func (repository Postgres) loadBlock(blockRows *sql.Rows) core.Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (repository Postgres) loadTransactions(blockId int64) []core.Transaction {
|
func (repository Postgres) loadTransactions(blockId int64) []core.Transaction {
|
||||||
transactionRows, _ := repository.Db.Query("SELECT tx_hash, tx_nonce, tx_to, tx_gaslimit, tx_gasprice, tx_value FROM transactions")
|
transactionRows, _ := repository.Db.Query(`SELECT tx_hash, tx_nonce, tx_to, tx_gaslimit, tx_gasprice, tx_value FROM transactions`)
|
||||||
var transactions []core.Transaction
|
var transactions []core.Transaction
|
||||||
for transactionRows.Next() {
|
for transactionRows.Next() {
|
||||||
var hash string
|
var hash string
|
||||||
|
@ -3,7 +3,7 @@ package repositories
|
|||||||
import "github.com/8thlight/vulcanizedb/pkg/core"
|
import "github.com/8thlight/vulcanizedb/pkg/core"
|
||||||
|
|
||||||
type Repository interface {
|
type Repository interface {
|
||||||
CreateBlock(block core.Block)
|
CreateBlock(block core.Block) error
|
||||||
BlockCount() int
|
BlockCount() int
|
||||||
FindBlockByNumber(blockNumber int64) *core.Block
|
FindBlockByNumber(blockNumber int64) *core.Block
|
||||||
MaxBlockNumber() int64
|
MaxBlockNumber() int64
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package repositories_test
|
package repositories_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/8thlight/vulcanizedb/pkg/config"
|
"github.com/8thlight/vulcanizedb/pkg/config"
|
||||||
"github.com/8thlight/vulcanizedb/pkg/core"
|
"github.com/8thlight/vulcanizedb/pkg/core"
|
||||||
"github.com/8thlight/vulcanizedb/pkg/repositories"
|
"github.com/8thlight/vulcanizedb/pkg/repositories"
|
||||||
@ -133,6 +136,7 @@ var _ = Describe("Repositories", func() {
|
|||||||
Expect(savedTransaction.GasPrice).To(Equal(gasPrice))
|
Expect(savedTransaction.GasPrice).To(Equal(gasPrice))
|
||||||
Expect(savedTransaction.Value).To(Equal(value))
|
Expect(savedTransaction.Value).To(Equal(value))
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("The missing block numbers", func() {
|
Describe("The missing block numbers", func() {
|
||||||
@ -219,6 +223,48 @@ var _ = Describe("Repositories", func() {
|
|||||||
Expect(db).ShouldNot(BeNil())
|
Expect(db).ShouldNot(BeNil())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("does not commit block if block is invalid", func() {
|
||||||
|
|
||||||
|
//badNonce violates db Nonce field length
|
||||||
|
badNonce := fmt.Sprintf("x %s", strings.Repeat("1", 100))
|
||||||
|
badBlock := core.Block{
|
||||||
|
Number: 123,
|
||||||
|
Nonce: badNonce,
|
||||||
|
Transactions: []core.Transaction{},
|
||||||
|
}
|
||||||
|
pgConfig := config.DbConnectionString(config.NewConfig("private").Database)
|
||||||
|
db, _ := sqlx.Connect("postgres", pgConfig)
|
||||||
|
Expect(db).ShouldNot(BeNil())
|
||||||
|
repository := repositories.NewPostgres(db)
|
||||||
|
|
||||||
|
err := repository.CreateBlock(badBlock)
|
||||||
|
savedBlock := repository.FindBlockByNumber(123)
|
||||||
|
|
||||||
|
Expect(err).ToNot(BeNil())
|
||||||
|
Expect(savedBlock).To(BeNil())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("does not commit block or transactions if transaction is invalid", func() {
|
||||||
|
|
||||||
|
//badHash violates db To field length
|
||||||
|
badHash := fmt.Sprintf("x %s", strings.Repeat("1", 100))
|
||||||
|
badTransaction := core.Transaction{To: badHash}
|
||||||
|
pgConfig := config.DbConnectionString(config.NewConfig("private").Database)
|
||||||
|
block := core.Block{
|
||||||
|
Number: 123,
|
||||||
|
Transactions: []core.Transaction{badTransaction},
|
||||||
|
}
|
||||||
|
db, _ := sqlx.Connect("postgres", pgConfig)
|
||||||
|
Expect(db).ShouldNot(BeNil())
|
||||||
|
repository := repositories.NewPostgres(db)
|
||||||
|
|
||||||
|
err := repository.CreateBlock(block)
|
||||||
|
savedBlock := repository.FindBlockByNumber(123)
|
||||||
|
|
||||||
|
Expect(err).ToNot(BeNil())
|
||||||
|
Expect(savedBlock).To(BeNil())
|
||||||
|
})
|
||||||
|
|
||||||
AssertRepositoryBehavior(func() repositories.Repository {
|
AssertRepositoryBehavior(func() repositories.Repository {
|
||||||
pgConfig := config.DbConnectionString(config.NewConfig("private").Database)
|
pgConfig := config.DbConnectionString(config.NewConfig("private").Database)
|
||||||
db, _ := sqlx.Connect("postgres", pgConfig)
|
db, _ := sqlx.Connect("postgres", pgConfig)
|
||||||
|
Loading…
Reference in New Issue
Block a user