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) { func BenchmarkNew(b *testing.B) {
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { 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 { type Collection[T any] interface {
All() <-chan *T All() <-chan *T
Clear() Clear()
Data() *sync.Map
Delete(key string) Delete(key string)
Exists(key string) bool Exists(key string) bool
Filter(func(*T) bool) <-chan *T Filter(func(*T) bool) <-chan *T
Get(key string) (value *T, err error) Get(key string) (value *T, err error)
Name() string
Root() string
Set(key string, value *T) Set(key string, value *T)
Sync() Sync()
} }
@ -30,7 +27,7 @@ type collection[T any] struct {
} }
// New creates a new collection with the given name. // 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() name := reflect.TypeOf((*T)(nil)).Elem().Name()
c := &collection[T]{ c := &collection[T]{
name: name, name: name,
@ -94,7 +91,11 @@ func (c *collection[T]) Delete(key string) {
return return
} }
c.storage.Delete(key) err := c.storage.Delete(key)
if err != nil {
panic(err)
}
} }
// Exists returns whether or not the key exists. // 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 } type User struct { Name string }
// Create a new collection // 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 // Store some data
users.Set("1", &User{Name: "User 1"}) users.Set("1", &User{Name: "User 1"})
@ -44,6 +45,15 @@ Data will be stored in `~/.ocean/todolist/User.dat`.
{"name":"User 3"} {"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 ## Usage
1. Create all the collections you need at the start 1. Create all the collections you need at the start

View File

@ -1,7 +1,7 @@
package ocean package ocean
type Storage[T any] interface { type Storage[T any] interface {
Init(c Collection[T]) error Init(data StorageData) error
Delete(key string) error Delete(key string) error
Set(key string, value *T) error Set(key string, value *T) error
Sync() 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. // Directory creates a directory and stores every record in a separate file.
type Directory[T any] struct { type Directory[T any] struct {
collection ocean.Collection[T] collection ocean.StorageData
directory string directory string
} }
// Init loads all existing records from the directory. // 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.collection = c
ds.directory = filepath.Join(c.Root(), c.Name()) 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() 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. // Delete deletes the file for the given key.
func (ds *Directory[T]) Delete(key string) error { 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. // 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. // 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) fileName := ds.keyFile(key)
file, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600) 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 const diskWriteInterval = 100 * time.Millisecond
type File[T any] struct { type File[T any] struct {
collection ocean.Collection[T] collection ocean.StorageData
dirty atomic.Uint32 dirty atomic.Uint32
sync chan struct{} 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.collection = c
fs.sync = make(chan struct{}) fs.sync = make(chan struct{})