func (b *BadgerStore) StoreLogs(logs []*raft.Log) error {
	maxBatchSize := b.db.MaxBatchSize()
	min := uint64(0)
	max := uint64(len(logs))
	ranges := b.generateRanges(min, max, maxBatchSize)
	for _, r := range ranges {
		txn := b.db.NewTransaction(true)
		defer txn.Discard()
		for index := r.from; index < r.to; index++ {
			log := logs[index]
			key := []byte(fmt.Sprintf("%s%d", dbLogsPrefix, log.Index))
			var out bytes.Buffer
			enc := gob.NewEncoder(&out)
			enc.Encode(log)
			if err := txn.Set(key, out.Bytes()); err != nil {
				return err
			}
		}
		if err := txn.Commit(nil); err != nil {
			return err
		}
	}
	return nil
}
StoreLogs is used to store a set of raft logs
package raftbadgerdb
import (
	"bytes"
	"encoding/binary"
	"encoding/gob"
	"errors"
	"fmt"
	"log"
	"math"
	"strconv"
	"github.com/dgraph-io/badger"
	"github.com/hashicorp/raft"
)
var (
	dbLogsPrefix = []byte("logs")
	dbConfPrefix = []byte("conf")
	ErrKeyNotFound = errors.New("not found")
)
type BadgerStore struct {
	db   *badger.DB
	path string
}
type Options struct {
	BadgerOptions *badger.Options
	Path string
}
func NewBadgerStore(path string) (*BadgerStore, error) {
	opts := Options{Path: path, BadgerOptions: &badger.DefaultOptions}
	return New(opts)
}
func New(options Options) (*BadgerStore, error) {
	options.BadgerOptions.Dir = options.Path + "/badger"
	options.BadgerOptions.ValueDir = options.Path + "/badger"
	db, err := badger.Open(*options.BadgerOptions)
	if err != nil {
		log.Fatal(err)
	}
	store := &BadgerStore{
		db:   db,
		path: options.Path,
	}
	return store, nil
}
func (b *BadgerStore) Close() error {
	return b.db.Close()
}
func bytesToUint64(b []byte) uint64 {
	return binary.BigEndian.Uint64(b)
}
func uint64ToBytes(u uint64) []byte {
	buf := make([]byte, 8)
	binary.BigEndian.PutUint64(buf, u)
	return buf
}
func (b *BadgerStore) FirstIndex() (uint64, error) {
	first := uint64(0)
	err := b.db.View(func(txn *badger.Txn) error {
		it := txn.NewIterator(badger.DefaultIteratorOptions)
		defer it.Close()
		it.Seek(dbLogsPrefix)
		if it.ValidForPrefix(dbLogsPrefix) {
			item := it.Item()
			k := string(item.Key()[len(dbLogsPrefix):])
			idx, err := strconv.ParseUint(k, 10, 64)
			if err != nil {
				return err
			}
			first = idx
		}
		return nil
	})
	if err != nil {
		return 0, err
	}
	return first, nil
}
func (b *BadgerStore) LastIndex() (uint64, error) {
	last := uint64(0)
	if err := b.db.View(func(txn *badger.Txn) error {
		opts := badger.DefaultIteratorOptions
		opts.Reverse = true
		it := txn.NewIterator(opts)
		defer it.Close()
		seekKey := append(dbLogsPrefix, 0xFF)
		it.Seek(seekKey)
		if it.ValidForPrefix(dbLogsPrefix) {
			item := it.Item()
			k := string(item.Key()[len(dbLogsPrefix):])
			idx, err := strconv.ParseUint(k, 10, 64)
			if err != nil {
				return err
			}
			last = idx
		}
		return nil
	}); err != nil {
		return 0, err
	}
	return last, nil
}
func (b *BadgerStore) GetLog(idx uint64, log *raft.Log) error {
	return b.db.View(func(txn *badger.Txn) error {
		item, err := txn.Get([]byte(fmt.Sprintf("%s%d", dbLogsPrefix, idx)))
		if item == nil {
			return raft.ErrLogNotFound
		}
		v, err := item.Value()
		if err != nil {
			return err
		}
		buf := bytes.NewBuffer(v)
		dec := gob.NewDecoder(buf)
		return dec.Decode(&log)
	})
}
func (b *BadgerStore) StoreLog(log *raft.Log) error {
	return b.StoreLogs([]*raft.Log{log})
}