Improved interfaces

This commit is contained in:
Eduard Urbach 2023-07-12 10:58:20 +02:00
parent 620308fab5
commit 658cd6a8a3
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
7 changed files with 46 additions and 15 deletions

View File

@ -71,7 +71,7 @@ func BenchmarkDelete(b *testing.B) {
func BenchmarkNew(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ocean.New[User]("test", nil)
_, _ = ocean.New[User]("test", nil)
}
})
}

View File

@ -10,13 +10,10 @@ import (
type Collection[T any] interface {
All() <-chan *T
Clear()
Data() *sync.Map
Delete(key string)
Exists(key string) bool
Filter(func(*T) bool) <-chan *T
Get(key string) (value *T, err error)
Name() string
Root() string
Set(key string, value *T)
Sync()
}
@ -30,7 +27,7 @@ type collection[T any] struct {
}
// New creates a new collection with the given name.
func New[T any](namespace string, storage Storage[T]) (*collection[T], error) {
func New[T any](namespace string, storage Storage[T]) (Collection[T], error) {
name := reflect.TypeOf((*T)(nil)).Elem().Name()
c := &collection[T]{
name: name,
@ -94,7 +91,11 @@ func (c *collection[T]) Delete(key string) {
return
}
c.storage.Delete(key)
err := c.storage.Delete(key)
if err != nil {
panic(err)
}
}
// Exists returns whether or not the key exists.

View File

@ -15,7 +15,8 @@ go get git.akyoto.dev/go/ocean
type User struct { Name string }
// Create a new collection
users := ocean.New[User]("todolist", &storage.File[User]{})
todolist := ocean.New("todolist")
users := todolist.NewCollection[User](&storage.File[User]{})
// Store some data
users.Set("1", &User{Name: "User 1"})
@ -44,6 +45,15 @@ Data will be stored in `~/.ocean/todolist/User.dat`.
{"name":"User 3"}
```
## Benchmarks
```
BenchmarkGet-12 275126157 4.462 ns/op 0 B/op 0 allocs/op
BenchmarkSet-12 4796011 251.0 ns/op 32 B/op 2 allocs/op
BenchmarkDelete-12 471913158 2.530 ns/op 0 B/op 0 allocs/op
BenchmarkNew-12 48838576 22.89 ns/op 80 B/op 1 allocs/op
```
## Usage
1. Create all the collections you need at the start

View File

@ -1,7 +1,7 @@
package ocean
type Storage[T any] interface {
Init(c Collection[T]) error
Init(data StorageData) error
Delete(key string) error
Set(key string, value *T) error
Sync()

9
StorageData.go Normal file
View File

@ -0,0 +1,9 @@
package ocean
import "sync"
type StorageData interface {
Data() *sync.Map
Name() string
Root() string
}

View File

@ -10,15 +10,20 @@ import (
// Directory creates a directory and stores every record in a separate file.
type Directory[T any] struct {
collection ocean.Collection[T]
collection ocean.StorageData
directory string
}
// Init loads all existing records from the directory.
func (ds *Directory[T]) Init(c ocean.Collection[T]) error {
func (ds *Directory[T]) Init(c ocean.StorageData) error {
ds.collection = c
ds.directory = filepath.Join(c.Root(), c.Name())
os.Mkdir(ds.directory, 0700)
err := os.Mkdir(ds.directory, 0700)
if err != nil {
return err
}
return ds.read()
}
@ -29,7 +34,13 @@ func (ds *Directory[T]) Set(key string, value *T) error {
// Delete deletes the file for the given key.
func (ds *Directory[T]) Delete(key string) error {
return os.Remove(ds.keyFile(key))
err := os.Remove(ds.keyFile(key))
if os.IsNotExist(err) {
return nil
}
return err
}
// Sync does nothing when using directory storage.
@ -81,7 +92,7 @@ func (ds *Directory[T]) readFile(fileName string) error {
}
// writeFile writes the value for the key to disk as a JSON file.
func (ds *Directory[T]) writeFile(key string, value *T) error {
func (ds *Directory[T]) writeFile(key string, value any) error {
fileName := ds.keyFile(key)
file, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)

View File

@ -17,12 +17,12 @@ import (
const diskWriteInterval = 100 * time.Millisecond
type File[T any] struct {
collection ocean.Collection[T]
collection ocean.StorageData
dirty atomic.Uint32
sync chan struct{}
}
func (fs *File[T]) Init(c ocean.Collection[T]) error {
func (fs *File[T]) Init(c ocean.StorageData) error {
fs.collection = c
fs.sync = make(chan struct{})