Hey everyone,
I’m building a blockchain storage on top of badger and as i understand, the fastest way to iterate on all keys is to use the badger stream framework. I tried to find a complete exemple to using it to retrieve a list of values with attributes matching a specific value but without success.
Is anyone can provide me an exemple for the following on GetWithRoleAt
function ?
package main
import (
"errors"
"math"
"github.com/dgraph-io/badger/v4"
"github.com/fxamacker/cbor/v2"
)
type Account struct {
Address string `cbor:"1,keyasint"`
Group string `cbor:"2,keyasint"`
}
const (
AccountPrefix string = "account_"
)
type AccountTable struct {
bdb *badger.DB
currentTxn *badger.Txn
}
func (db *AccountTable) SetCurrentTxn(tx *badger.Txn) {
db.currentTxn = tx
}
func (db *AccountTable) Exists(address string) (bool, error) {
var at uint64
at = math.MaxUint64
return db.ExistsAt(address, at)
}
func (db *AccountTable) ExistsAt(address string, at uint64) (bool, error) {
key := []byte(AccountPrefix + address)
txn := db.bdb.NewTransactionAt(at, false)
if _, err := txn.Get([]byte(key)); err != nil {
if errors.Is(err, badger.ErrKeyNotFound) {
return false, nil
} else {
return false, err
}
} else {
return true, nil
}
}
func (db *AccountTable) Get(address string) (Account, error) {
var at uint64
at = math.MaxUint64
return db.GetAt(address, at)
}
func (db *AccountTable) GetAt(address string, at uint64) (Account, error) {
var account Account
key := []byte(AccountPrefix + address)
txn := db.bdb.NewTransactionAt(at, false)
item, err := txn.Get([]byte(key))
if err != nil {
return Account{}, err
}
value, err := item.ValueCopy(nil)
if err != nil {
return Account{}, err
}
err = cbor.Unmarshal(value, &account)
if err != nil {
return Account{}, err
}
return account, nil
}
func (db *AccountTable) Insert(account Account) error {
key := []byte(AccountPrefix + account.Address)
exists, err := db.ExistsAt(account.Address, db.currentTxn.ReadTs())
if err != nil {
return err
}
if exists {
return errors.New("global account already exists")
}
value, err := cbor.Marshal(account)
if err != nil {
return err
}
return db.currentTxn.Set(key, value)
}
func (db *AccountTable) Update(account Account) error {
key := []byte(AccountPrefix + account.Address)
exists, err := db.ExistsAt(account.Address, db.currentTxn.ReadTs())
if err != nil {
return err
}
if !exists {
return errors.New("global account doesn't exists")
}
value, err := cbor.Marshal(account)
if err != nil {
return err
}
return db.currentTxn.Set(key, value)
}
func (db *AccountTable) Upsert(account Account) error {
key := []byte(AccountPrefix + account.Address)
value, err := cbor.Marshal(account)
if err != nil {
return err
}
return db.currentTxn.Set(key, value)
}
func (db *AccountTable) Delete(address string) error {
key := []byte(AccountPrefix + address)
return db.currentTxn.Delete(key)
}
func (db *AccountTable) GetAll() ([]Account, error) {
var at uint64
at = math.MaxUint64
return db.GetAllAt(at)
}
func (db *AccountTable) GetAllAt(at uint64) ([]Account, error) {
var accounts []Account
txn := db.bdb.NewTransactionAt(at, false)
it := txn.NewIterator(badger.DefaultIteratorOptions)
defer it.Close()
prefix := []byte(AccountPrefix)
for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() {
item := it.Item()
var account Account
value, err := item.ValueCopy(nil)
if err != nil {
return []Account{}, err
}
err = cbor.Unmarshal(value, &account)
if err != nil {
return []Account{}, err
}
accounts = append(accounts, account)
}
return accounts, nil
}
func (db *AccountTable) GetWithRoleAt(role string, at uint64) ([]Account, error) {
var accounts []Account
//Exemple
return accounts, nil
}
func NewAccountTable(db *badger.DB) *AccountTable {
return &AccountTable{
bdb: db,
}
}