commit 0eb83c922b4ae5ab280c0d5efb9216f99ba9456c
parent f0aa76eaf2ee2c5a8fc782898668687d84a5f318
Author: Vetle Haflan <vetle@haflan.dev>
Date: Fri, 10 Apr 2020 16:41:17 +0200
Refactor database operation to use bucket wrapper
Diffstat:
4 files changed, 68 insertions(+), 35 deletions(-)
diff --git a/database/database.go b/database/database.go
@@ -77,7 +77,7 @@ func Init(dbFileName string) error {
// generates hash for the password and updates the database with this
// new configuration.
func Reconfigure(passphrase string, pageTitle string) error {
-
+ // TODO: Maybe this belongs elsewhere?
/* TODO: Generate a random _readable_ password if none is given
var passphraseBytes []byte
if passphrase == "" {
@@ -118,8 +118,34 @@ func Close() {
db.Close()
}
-// GetDB returns the bbolt database struct
-// TODO: Not sure how if this is a good way to do it, although it does seem to work
-func GetDB() *bbolt.DB {
- return db
+// BucketOperation operates on the given (root level) bucket if it exists, using the
+// DB.Update function if update is set true, otherwise using DB.View.
+// An error is returned if no bucket can be found for the bucketKey or any other
+// error occurs in the wrapped transaction
+func bucketOperation(update bool, bucketKey []byte, fn func(*bbolt.Bucket) error) error {
+ var operation func(func(*bbolt.Tx) error) error
+ if update {
+ operation = db.Update
+ } else {
+ operation = db.View
+ }
+ return operation(func(tx *bbolt.Tx) error {
+ bucket := tx.Bucket(bucketKey)
+ if bucket == nil {
+ return errors.New("the given bucket does not exist")
+ }
+ return fn(bucket)
+ })
+}
+
+// BucketUpdate wraps DB.Update with a general way of handling errors
+// if the bucket does not exist
+func BucketUpdate(bucketKey []byte, fn func(*bbolt.Bucket) error) error {
+ return bucketOperation(true, bucketKey, fn)
+}
+
+// BucketView wraps DB.View with a general way of handling errors
+// if the bucket does not exist
+func BucketView(bucketKey []byte, fn func(*bbolt.Bucket) error) error {
+ return bucketOperation(true, bucketKey, fn)
}
diff --git a/go.mod b/go.mod
@@ -0,0 +1,8 @@
+module sermoni
+
+go 1.13
+
+require (
+ go.etcd.io/bbolt v1.3.4
+ golang.org/x/crypto v0.0.0-20200406173513-056763e48d71
+)
diff --git a/main.go b/main.go
@@ -23,6 +23,8 @@ func main() {
Name: "Test name",
Description: "This is the description, yay",
})
- testService := services.Get("testing")
- fmt.Printf("test service: %+v\n", testService)
+ fmt.Printf("ADD ERR: %v\n", services.Add("testing", services.Service{Name: "This"}))
+ fmt.Printf("none service: %+v\n", services.Get("none"))
+ fmt.Printf("DELETE ERR: %v\n", services.Delete("none"))
+ fmt.Printf("test service: %+v\n", services.Get("testing"))
}
diff --git a/services/services.go b/services/services.go
@@ -24,24 +24,20 @@ type Service struct {
// Get returns a service struct if the identifier matches any
// keys in the services bucket. Returns nil if there are no matching buckets
-func Get(identifier string) (service Service) {
- db := database.GetDB()
- err := db.View(func(tx *bbolt.Tx) error {
- serviceBucket := tx.Bucket(database.BucketKeyServices)
- if serviceBucket == nil {
- log.Fatal("No services bucket found")
- }
- b := serviceBucket.Bucket([]byte(identifier))
- if b == nil {
+func Get(identifier string) *Service {
+ var service Service
+ err := database.BucketView(database.BucketKeyServices, func(b *bbolt.Bucket) error {
+ sb := b.Bucket([]byte(identifier))
+ if sb == nil {
return errors.New("no bucket found for the given id")
}
- if name := b.Get(keyServiceName); name != nil {
+ if name := sb.Get(keyServiceName); name != nil {
service.Name = string(name)
}
- if description := b.Get(keyServiceDescription); description != nil {
+ if description := sb.Get(keyServiceDescription); description != nil {
service.Description = string(description)
}
- if period := b.Get(keyServicePeriod); period != nil {
+ if period := sb.Get(keyServicePeriod); period != nil {
// Quick fix: Convert to string, then int
// If an error occurs (it tho)
if intPeriod, err := strconv.Atoi(string(period)); err != nil {
@@ -55,43 +51,44 @@ func Get(identifier string) (service Service) {
})
if err != nil {
log.Println(err)
+ return nil
}
- return service
+ return &service
}
// Delete deletes the given service if it exists
-func Delete(identifier string) {
- //db := database.GetDB()
+func Delete(identifier string) error {
+ return database.BucketUpdate(database.BucketKeyServices, func(b *bbolt.Bucket) error {
+ serviceKey := []byte(identifier)
+ if b.Bucket(serviceKey) == nil {
+ return errors.New("no service for the given id")
+ }
+ return b.DeleteBucket(serviceKey)
+ })
}
// Add adds a new service to monitor
func Add(identifier string, service Service) error {
- db := database.GetDB()
- return db.Update(func(tx *bbolt.Tx) error {
- serviceBucket := tx.Bucket(database.BucketKeyServices)
- if serviceBucket == nil {
- log.Fatal("No services bucket found")
- }
+ return database.BucketUpdate(database.BucketKeyServices, func(b *bbolt.Bucket) error {
serviceKey := []byte(identifier)
- if serviceBucket.Bucket(serviceKey) != nil {
+ if b.Bucket(serviceKey) != nil {
return errors.New("a service has already been registered for the given id")
}
- b, err := serviceBucket.CreateBucket(serviceKey)
+ // Create the service bucket, sb
+ sb, err := b.CreateBucket(serviceKey)
if err != nil {
return err
}
- if err = b.Put(keyServiceName, []byte(service.Name)); err != nil {
+ if err = sb.Put(keyServiceName, []byte(service.Name)); err != nil {
return err
}
- if err = b.Put(keyServiceDescription, []byte(service.Description)); err != nil {
+ if err = sb.Put(keyServiceDescription, []byte(service.Description)); err != nil {
return err
}
periodStr := strconv.Itoa(service.ExpectationPeriod)
- if err = b.Put(keyServicePeriod, []byte(periodStr)); err != nil {
+ if err = sb.Put(keyServicePeriod, []byte(periodStr)); err != nil {
return err
}
return nil
})
}
-
-// TODO: Consider a wrapper that gets the services bucket and operates on it