-
Notifications
You must be signed in to change notification settings - Fork 29
/
interface.go
125 lines (103 loc) · 2.72 KB
/
interface.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package storage
import (
"sync"
"github.com/dgraph-io/badger/v3"
"github.com/0chain/gosdk/zmagmacore/errors"
)
type (
// Storage represents the main storage based on badger.DB.
Storage struct {
db *badger.DB
singleton sync.Once // used for opening connection only once
}
// Value represent value that can be stored as encoded bytes.
Value interface {
Encode() []byte
}
)
var (
// storageInst represents singleton storage.
storageInst = &Storage{}
)
// Open opens singleton connection to storage.
//
// If an error occurs during execution, the program terminates with code 2 and the error will be written in os.Stderr.
//
// Should be used only once while application is starting.
func Open(path string) {
storageInst.singleton.Do(func() {
opts := badger.DefaultOptions(path)
opts.Logger = nil
db, err := badger.Open(opts)
if err != nil {
errors.ExitErr("error while opening storage: %v", err, 2)
}
storageInst.db = db
})
}
// GetStorage returns current storage implementation.
func GetStorage() *Storage {
return storageInst
}
// Del deletes entry by the key.
func (s *Storage) Del(key []byte) error {
return s.db.Update(func(txn *badger.Txn) error {
return txn.Delete(key)
})
}
// Get retrieves entry by the key.
func (s *Storage) Get(key []byte) (value []byte, err error) {
err = s.db.View(func(txn *badger.Txn) error {
var item *badger.Item
item, err = txn.Get(key)
if err != nil {
return err
}
return item.Value(func(val []byte) error {
value = val
return nil
})
})
return
}
// Set sets encoded Value with provided key.
func (s *Storage) Set(key []byte, value Value) error {
return s.db.Update(func(txn *badger.Txn) error {
blob := value.Encode()
return txn.Set(key, blob)
})
}
// SetWithRetries sets encoded Value with provided key with retries.
func (s *Storage) SetWithRetries(key []byte, value Value, numRetries int) error {
var err error
for i := 0; i < numRetries; i++ {
if err = s.Set(key, value); err != nil {
continue
}
break
}
return err
}
// Iterate iterates all elements with provided prefix and processes it with the handler.
func (s *Storage) Iterate(handler func(item *badger.Item) error, prefix []byte) error {
return s.db.View(func(txn *badger.Txn) error {
it := txn.NewIterator(badger.DefaultIteratorOptions)
defer it.Close()
for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() {
if err := handler(it.Item()); err != nil {
return err
}
}
return nil
})
}
// NewTransaction creates new badger.Txn.
//
// For read-only transactions set update flag to false.
func (s *Storage) NewTransaction(update bool) *badger.Txn {
return s.db.NewTransaction(update)
}
// Close closes a DB.
func (s *Storage) Close() error {
return s.db.Close()
}