Browse Source

Add Bucket shorthand, Makefile, and comments

Signed-off-by: jolheiser <john.olheiser@gmail.com>
main v0.0.1
jolheiser 1 year ago
parent
commit
116a4c0ac9
No known key found for this signature in database GPG Key ID: 83E486E71AFEB820
  1. 13
      Makefile
  2. 32
      bucket.go
  3. 2
      options.go
  4. 4
      serial.go
  5. 10
      shock.go
  6. 15
      store.go
  7. 9
      store_test.go

13
Makefile

@ -0,0 +1,13 @@
GO ?= go
.PHONY: fmt
fmt:
$(GO) fmt ./...
.PHONY: test
test:
$(GO) test --race ./...
.PHONY: vet
vet:
$(GO) vet ./...

32
bucket.go

@ -0,0 +1,32 @@
package shock
// Bucket is a shorthand way to group a database bucket together
type Bucket struct {
Name string
DB *DB
}
// Put adds a new value to the bucket
func (b *Bucket) Put(val Sequencer) error {
return b.DB.Put(b.Name, val)
}
// Get returns a value from the bucket with the specified sequence ID
func (b *Bucket) Get(seq uint64, val interface{}) error {
return b.DB.Get(b.Name, seq, val)
}
// Count returns the number of objects in the bucket
func (b *Bucket) Count() (int, error) {
return b.DB.Count(b.Name)
}
// ViewEach iterates over each object in the bucket in read-only mode
func (b *Bucket) ViewEach(fn EachFunc) error {
return b.DB.ViewEach(b.Name, fn)
}
// UpdateEach iterates over each object in the bucket in write mode
func (b *Bucket) UpdateEach(fn EachFunc) error {
return b.DB.UpdateEach(b.Name, fn)
}

2
options.go

@ -2,11 +2,13 @@ package shock
import "go.etcd.io/bbolt"
// Options are Shock init options
type Options struct {
Bolt *bbolt.Options
Serializer Serializer
}
// DefaultOptions are the default options used to init Shock
var DefaultOptions = &Options{
Bolt: bbolt.DefaultOptions,
Serializer: JSONSerializer{},

4
serial.go

@ -2,17 +2,21 @@ package shock
import "encoding/json"
// Serializer defines a way to encode/decode objects in the database
type Serializer interface {
Marshal(v interface{}) ([]byte, error)
Unmarshal(data []byte, v interface{}) error
}
// JSONSerializer is a Serializer that uses JSON
type JSONSerializer struct{}
// Marshal encodes an object to JSON
func (j JSONSerializer) Marshal(v interface{}) ([]byte, error) {
return json.Marshal(v)
}
// Unmarshal decodes an object from JSON
func (j JSONSerializer) Unmarshal(data []byte, v interface{}) error {
return json.Unmarshal(data, &v)
}

10
shock.go

@ -6,11 +6,13 @@ import (
"go.etcd.io/bbolt"
)
// DB is a Shock (BBolt) database
type DB struct {
Bolt *bbolt.DB
Serializer Serializer
}
// Open creates a connection to a database file
func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
if options == nil {
options = DefaultOptions
@ -24,3 +26,11 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
Serializer: options.Serializer,
}, nil
}
// Bucket returns a shorthand wrapper for interacting with a specific bucket
func (d *DB) Bucket(name string) *Bucket {
return &Bucket{
Name: name,
DB: d,
}
}

15
store.go

@ -6,10 +6,12 @@ import (
"go.etcd.io/bbolt"
)
// Sequencer defines a way to assign a unique sequence ID to an object
type Sequencer interface {
AssignSeq(uint64)
}
// Put adds a new value to a bucket
func (d *DB) Put(bucket string, val Sequencer) error {
if err := d.initBucket(bucket); err != nil {
return err
@ -31,6 +33,7 @@ func (d *DB) Put(bucket string, val Sequencer) error {
})
}
// Get returns a value from a bucket with the specified sequence ID
func (d *DB) Get(bucket string, seq uint64, val interface{}) error {
if err := d.initBucket(bucket); err != nil {
return err
@ -44,6 +47,7 @@ func (d *DB) Get(bucket string, seq uint64, val interface{}) error {
return nil
}
// Count returns the number of objects in a bucket
func (d *DB) Count(bucket string) (int, error) {
count := 0
if err := d.initBucket(bucket); err != nil {
@ -60,17 +64,20 @@ func (d *DB) Count(bucket string) (int, error) {
return count, nil
}
type eachFn func(seq, serial []byte) error
// EachFunc defines a way to interact with each object in a bucket while iterating
type EachFunc func(seq, serial []byte) error
func (d *DB) ViewEach(bucket string, fn eachFn) error {
// ViewEach iterates over each object in a bucket in read-only mode
func (d *DB) ViewEach(bucket string, fn EachFunc) error {
return d.forEach(bucket, false, fn)
}
func (d *DB) UpdateEach(bucket string, fn eachFn) error {
// UpdateEach iterates over each object in a bucket in write mode
func (d *DB) UpdateEach(bucket string, fn EachFunc) error {
return d.forEach(bucket, true, fn)
}
func (d *DB) forEach(bucket string, writable bool, fn eachFn) error {
func (d *DB) forEach(bucket string, writable bool, fn EachFunc) error {
if err := d.initBucket(bucket); err != nil {
return err
}

9
store_test.go

@ -40,15 +40,16 @@ func TestStore(t *testing.T) {
},
}
bucket := db.Bucket("test")
for _, tc := range tt {
t.Run(tc.Name, func(t *testing.T) {
if err := db.Put("test", tc); err != nil {
if err := bucket.Put(tc); err != nil {
t.Log(err)
t.FailNow()
}
var tcc Test
err := db.Get("test", tc.ID, &tcc)
err := bucket.Get(tc.ID, &tcc)
if err != nil {
t.Log(err)
t.FailNow()
@ -62,7 +63,7 @@ func TestStore(t *testing.T) {
}
t.Run("count", func(t *testing.T) {
count, err := db.Count("test")
count, err := bucket.Count()
if err != nil {
t.Log(err)
t.FailNow()
@ -76,7 +77,7 @@ func TestStore(t *testing.T) {
t.Run("list", func(t *testing.T) {
list := make([]Test, 0, len(tt))
if err := db.ViewEach("test", func(_, serial []byte) error {
if err := bucket.ViewEach(func(_, serial []byte) error {
var t Test
if err := db.Serializer.Unmarshal(serial, &t); err != nil {
return err

Loading…
Cancel
Save