feat(db): boltdb soft delete

This commit is contained in:
Denis Gukov 2021-05-15 16:27:42 +05:00
parent ca05dd94db
commit bf91af5198
4 changed files with 141 additions and 20 deletions

View File

@ -27,6 +27,15 @@ type RetrieveQueryParams struct {
SortInverted bool
}
type ObjectScope int
//const (
// GlobalScope ObjectScope = iota
// ProjectScope
// UserScope
// TaskScope
//)
type ObjectProperties struct {
TableName string
SortableColumns []string

View File

@ -115,7 +115,7 @@ func (d *BoltDb) getObject(bucketID int, props db.ObjectProperties, objectID obj
return db.ErrNotFound
}
return json.Unmarshal(str, &object)
return unmarshalObject(str, object)
})
return
@ -317,21 +317,24 @@ func (d *BoltDb) getObjects(bucketID int, props db.ObjectProperties, params db.R
}
func (d *BoltDb) isObjectInUse(bucketID int, props db.ObjectProperties, objectID objectID) (inUse bool, err error) {
return false, nil
}
//func (d *BoltDb) isObjectUsedByTemplate(bucketID int, props db.ObjectProperties, objectID objectID) (inUse bool, err error) {
// if props.IsGlobal {
// return false, fmt.Errorf("global object can't be checked by usege")
// }
//
// var templates []db.Template
// objs := d.getObjects(bucketID, db.TemplateProps, db.RetrieveQueryParams{}, func (tpl interface{}) bool {
// f := reflect.ValueOf(tpl).FieldByName(props.TemplateColumnName)
// if f.IsZero() {
// return false
// }
// return f.Int() == int64(objectID)
// }, &templates)
//
// return false, nil
//}
func (d *BoltDb) deleteObject(bucketID int, props db.ObjectProperties, objectID objectID) error {
inUse, err := d.isObjectInUse(bucketID, props, objectID)
if err != nil {
return err
}
if inUse {
return db.ErrInvalidOperation
}
return d.db.Update(func (tx *bbolt.Tx) error {
b := tx.Bucket(makeBucketId(props, bucketID))
if b == nil {
@ -342,7 +345,39 @@ func (d *BoltDb) deleteObject(bucketID int, props db.ObjectProperties, objectID
}
func (d *BoltDb) deleteObjectSoft(bucketID int, props db.ObjectProperties, objectID objectID) error {
return d.deleteObject(bucketID, props, objectID)
var data interface{}
// load data
err := d.db.View(func(tx *bbolt.Tx) error {
b := tx.Bucket(makeBucketId(props, bucketID))
if b == nil {
return db.ErrNotFound
}
d := b.Get(objectID.ToBytes())
if d == nil {
return db.ErrNotFound
}
return json.Unmarshal(d, &data)
})
if err != nil {
return err
}
// store data
res, err := json.Marshal(data)
return d.db.Update(func(tx *bbolt.Tx) error {
b := tx.Bucket(makeBucketId(props, bucketID))
if b == nil {
return db.ErrNotFound
}
return b.Put(objectID.ToBytes(), res)
})
}
// updateObject updates data for object in database.
@ -355,8 +390,29 @@ func (d *BoltDb) updateObject(bucketID int, props db.ObjectProperties, object in
idValue := reflect.ValueOf(object).FieldByName("ID")
id := makeObjectId(int(idValue.Int()))
if b.Get(id) == nil {
var objectID objectID
switch idValue.Kind() {
case reflect.Int:
case reflect.Int8:
case reflect.Int16:
case reflect.Int32:
case reflect.Int64:
case reflect.Uint:
case reflect.Uint8:
case reflect.Uint16:
case reflect.Uint32:
case reflect.Uint64:
objectID = intObjectID(idValue.Int())
case reflect.String:
objectID = strObjectID(idValue.String())
}
if objectID == nil {
return fmt.Errorf("unsupported ID type")
}
if b.Get(objectID.ToBytes()) == nil {
return db.ErrNotFound
}
@ -365,7 +421,7 @@ func (d *BoltDb) updateObject(bucketID int, props db.ObjectProperties, object in
return err
}
return b.Put(id, str)
return b.Put(objectID.ToBytes(), str)
})
}

View File

@ -9,16 +9,71 @@ import (
)
type test1 struct {
ID int `db:"ID"`
FistName string `db:"first_name" json:"firstName"`
LastName string `db:"last_name" json:"lastName"`
Password string `db:"-" json:"password"`
PasswordRepeat string `db:"-" json:"passwordRepeat"`
PasswordHash string `db:"password" json:"-"`
Removed bool `db:"removed"`
}
func createBoltDb() BoltDb {
return BoltDb{
Filename: "/tmp/test_semaphore_db_" + strconv.Itoa(rand.Int()),
}
}
func createStore() db.Store {
return &BoltDb{
Filename: "/tmp/test_semaphore_db_" + strconv.Itoa(rand.Int()),
store := createBoltDb()
return &store
}
func TestDeleteObjectSoft(t *testing.T) {
store := createBoltDb()
err := store.Connect()
if err != nil {
t.Failed()
}
obj := test1{
FistName: "Denis",
LastName: "Gukov",
}
props := db.ObjectProperties{
IsGlobal: true,
TableName: "test1",
}
newObj, err := store.createObject(0, props, obj)
if err != nil {
t.Failed()
}
objID := intObjectID(newObj.(test1).ID)
err = store.deleteObjectSoft(0, props, objID)
if err != nil {
t.Failed()
}
var found test1
err = store.getObject(0, props, objID, &found)
if err != nil {
t.Failed()
}
if found.ID != int(objID) ||
found.Removed != true ||
found.Password != obj.Password ||
found.LastName != obj.LastName {
t.Failed()
}
}

View File

@ -32,6 +32,7 @@ func (d *BoltDb) GetInventories(projectID int, params db.RetrieveQueryParams) (i
}
func (d *BoltDb) DeleteInventory(projectID int, inventoryID int) error {
return d.deleteObject(projectID, db.InventoryProps, intObjectID(inventoryID))
}