Improve database storage put method

This commit is contained in:
Daniel 2020-04-15 17:27:33 +02:00
parent 812c1e26c5
commit 558486483b
13 changed files with 56 additions and 45 deletions

View file

@ -36,26 +36,30 @@ func (s *StorageInterface) Get(key string) (record.Record, error) {
}
// Put stores a record in the database.
func (s *StorageInterface) Put(r record.Record) error {
func (s *StorageInterface) Put(r record.Record) (record.Record, error) {
if r.Meta().Deleted > 0 {
return setConfigOption(r.DatabaseKey(), nil, false)
return r, setConfigOption(r.DatabaseKey(), nil, false)
}
acc := r.GetAccessor(r)
if acc == nil {
return errors.New("invalid data")
return nil, errors.New("invalid data")
}
val, ok := acc.Get("Value")
if !ok || val == nil {
return setConfigOption(r.DatabaseKey(), nil, false)
err := setConfigOption(r.DatabaseKey(), nil, false)
if err != nil {
return nil, err
}
return s.Get(r.DatabaseKey())
}
optionsLock.RLock()
option, ok := options[r.DatabaseKey()]
optionsLock.RUnlock()
if !ok {
return errors.New("config option does not exist")
return nil, errors.New("config option does not exist")
}
var value interface{}
@ -70,14 +74,14 @@ func (s *StorageInterface) Put(r record.Record) error {
value, ok = acc.GetBool("Value")
}
if !ok {
return errors.New("received invalid value in \"Value\"")
return nil, errors.New("received invalid value in \"Value\"")
}
err := setConfigOption(r.DatabaseKey(), value, false)
if err != nil {
return err
return nil, err
}
return nil
return option.Export()
}
// Delete deletes a record from the database.

View file

@ -70,14 +70,14 @@ func (option *Option) Export() (record.Record, error) {
}
if option.activeValue != nil {
data, err = sjson.SetBytes(data, "Value", option.activeValue)
data, err = sjson.SetBytes(data, "Value", option.activeValue.getData(option))
if err != nil {
return nil, err
}
}
if option.activeDefaultValue != nil {
data, err = sjson.SetBytes(data, "DefaultValue", option.activeDefaultValue)
data, err = sjson.SetBytes(data, "DefaultValue", option.activeDefaultValue.getData(option))
if err != nil {
return nil, err
}

View file

@ -1,6 +1,7 @@
package database
import (
"errors"
"sync"
"github.com/tevino/abool"
@ -119,10 +120,13 @@ func (c *Controller) Put(r record.Record) (err error) {
}
}
err = c.storage.Put(r)
r, err = c.storage.Put(r)
if err != nil {
return err
}
if r == nil {
return errors.New("storage returned nil record after successful put operation")
}
// process subscriptions
for _, sub := range c.subscriptions {

View file

@ -82,16 +82,19 @@ func (b *Badger) Get(key string) (record.Record, error) {
}
// Put stores a record in the database.
func (b *Badger) Put(r record.Record) error {
func (b *Badger) Put(r record.Record) (record.Record, error) {
data, err := r.MarshalRecord(r)
if err != nil {
return err
return nil, err
}
err = b.db.Update(func(txn *badger.Txn) error {
return txn.Set([]byte(r.DatabaseKey()), data)
})
return err
if err != nil {
return nil, err
}
return r, nil
}
// Delete deletes a record from the database.

View file

@ -86,10 +86,10 @@ func (b *BBolt) Get(key string) (record.Record, error) {
}
// Put stores a record in the database.
func (b *BBolt) Put(r record.Record) error {
func (b *BBolt) Put(r record.Record) (record.Record, error) {
data, err := r.MarshalRecord(r)
if err != nil {
return err
return nil, err
}
err = b.db.Update(func(tx *bbolt.Tx) error {
@ -100,9 +100,9 @@ func (b *BBolt) Put(r record.Record) error {
return nil
})
if err != nil {
return err
return nil, err
}
return nil
return r, nil
}
// PutMany stores many records in the database.

View file

@ -65,7 +65,7 @@ func TestBBolt(t *testing.T) {
a.SetKey("test:A")
// put record
err = db.Put(a)
_, err = db.Put(a)
if err != nil {
t.Fatal(err)
}
@ -100,15 +100,15 @@ func TestBBolt(t *testing.T) {
qZ.SetKey("test:z")
qZ.CreateMeta()
// put
err = db.Put(qA)
_, err = db.Put(qA)
if err == nil {
err = db.Put(qB)
_, err = db.Put(qB)
}
if err == nil {
err = db.Put(qC)
_, err = db.Put(qC)
}
if err == nil {
err = db.Put(qZ)
_, err = db.Put(qZ)
}
if err != nil {
t.Fatal(err)

View file

@ -104,15 +104,15 @@ func (fst *FSTree) Get(key string) (record.Record, error) {
}
// Put stores a record in the database.
func (fst *FSTree) Put(r record.Record) error {
func (fst *FSTree) Put(r record.Record) (record.Record, error) {
dstPath, err := fst.buildFilePath(r.DatabaseKey(), true)
if err != nil {
return err
return nil, err
}
data, err := r.MarshalRecord(r)
if err != nil {
return err
return nil, err
}
err = writeFile(dstPath, data, defaultFileMode)
@ -120,15 +120,15 @@ func (fst *FSTree) Put(r record.Record) error {
// create dir and try again
err = os.MkdirAll(filepath.Dir(dstPath), defaultDirMode)
if err != nil {
return fmt.Errorf("fstree: failed to create directory %s: %s", filepath.Dir(dstPath), err)
return nil, fmt.Errorf("fstree: failed to create directory %s: %s", filepath.Dir(dstPath), err)
}
err = writeFile(dstPath, data, defaultFileMode)
if err != nil {
return fmt.Errorf("fstree: could not write file %s: %s", dstPath, err)
return nil, fmt.Errorf("fstree: could not write file %s: %s", dstPath, err)
}
}
return nil
return r, nil
}
// Delete deletes a record from the database.

View file

@ -44,12 +44,12 @@ func (hm *HashMap) Get(key string) (record.Record, error) {
}
// Put stores a record in the database.
func (hm *HashMap) Put(r record.Record) error {
func (hm *HashMap) Put(r record.Record) (record.Record, error) {
hm.dbLock.Lock()
defer hm.dbLock.Unlock()
hm.db[r.DatabaseKey()] = r
return nil
return r, nil
}
// PutMany stores many records in the database.

View file

@ -57,7 +57,7 @@ func TestHashMap(t *testing.T) {
a.SetKey("test:A")
// put record
err = db.Put(a)
_, err = db.Put(a)
if err != nil {
t.Fatal(err)
}
@ -86,15 +86,15 @@ func TestHashMap(t *testing.T) {
qZ.SetKey("test:z")
qZ.CreateMeta()
// put
err = db.Put(qA)
_, err = db.Put(qA)
if err == nil {
err = db.Put(qB)
_, err = db.Put(qB)
}
if err == nil {
err = db.Put(qC)
_, err = db.Put(qC)
}
if err == nil {
err = db.Put(qZ)
_, err = db.Put(qZ)
}
if err != nil {
t.Fatal(err)

View file

@ -21,8 +21,8 @@ func (i *InjectBase) Get(key string) (record.Record, error) {
}
// Put stores a record in the database.
func (i *InjectBase) Put(m record.Record) error {
return errNotImplemented
func (i *InjectBase) Put(m record.Record) (record.Record, error) {
return nil, errNotImplemented
}
// PutMany stores many records in the database.

View file

@ -9,7 +9,7 @@ import (
// Interface defines the database storage API.
type Interface interface {
Get(key string) (record.Record, error)
Put(m record.Record) error
Put(m record.Record) (record.Record, error)
Delete(key string) error
Query(q *query.Query, local, internal bool) (*iterator.Iterator, error)

View file

@ -36,8 +36,8 @@ func (s *Sinkhole) Get(key string) (record.Record, error) {
}
// Put stores a record in the database.
func (s *Sinkhole) Put(m record.Record) error {
return nil
func (s *Sinkhole) Put(r record.Record) (record.Record, error) {
return r, nil
}
// PutMany stores many records in the database.

View file

@ -111,26 +111,26 @@ func (s *StorageInterface) processQuery(q *query.Query, it *iterator.Iterator) {
}
// Put stores a record in the database.
func (s *StorageInterface) Put(r record.Record) error {
func (s *StorageInterface) Put(r record.Record) (record.Record, error) {
// record is already locked!
key := r.DatabaseKey()
n, err := EnsureNotification(r)
if err != nil {
return ErrInvalidData
return nil, ErrInvalidData
}
// transform key
if strings.HasPrefix(key, "all/") {
key = strings.TrimPrefix(key, "all/")
} else {
return ErrInvalidPath
return nil, ErrInvalidPath
}
// continue in goroutine
go UpdateNotification(n, key)
return nil
return n, nil
}
// UpdateNotification updates a notification with input from a database action. Notification will not be saved/propagated if there is no valid change.