139 lines
2.6 KiB
Go
Raw Normal View History

2023-07-04 22:20:26 +00:00
package ocean
2023-07-05 21:59:49 +00:00
import (
"os"
2023-07-06 12:10:12 +00:00
"path/filepath"
2023-07-06 13:02:50 +00:00
"reflect"
2023-07-05 21:59:49 +00:00
"sync"
)
2023-07-04 22:20:26 +00:00
2023-07-05 15:41:53 +00:00
type Collection[T any] interface {
2023-07-06 12:10:12 +00:00
All() <-chan *T
Clear()
2023-07-05 20:02:16 +00:00
Delete(key string)
Exists(key string) bool
2023-07-06 21:46:47 +00:00
Filter(func(*T) bool) <-chan *T
2023-07-06 15:26:19 +00:00
Get(key string) (value *T, err error)
2023-07-06 12:10:12 +00:00
Set(key string, value *T)
2023-07-08 15:26:36 +00:00
Sync()
2023-07-04 22:20:26 +00:00
}
2023-07-05 15:23:50 +00:00
// collection is a hash map of homogeneous data.
2023-07-05 15:41:53 +00:00
type collection[T any] struct {
2023-07-07 16:05:52 +00:00
data sync.Map
storage Storage[T]
name string
root string
2023-07-04 22:20:26 +00:00
}
2023-07-06 12:27:48 +00:00
// New creates a new collection with the given name.
func New[T any](directories ...string) (*collection[T], error) {
2023-07-06 13:34:57 +00:00
name := reflect.TypeOf((*T)(nil)).Elem().Name()
2023-07-05 21:59:49 +00:00
home, err := os.UserHomeDir()
if err != nil {
return nil, err
}
2023-07-06 12:27:48 +00:00
directories = append([]string{home, ".ocean"}, directories...)
directory := filepath.Join(directories...)
2023-07-05 21:59:49 +00:00
err = os.MkdirAll(directory, 0700)
if err != nil {
return nil, err
}
c := &collection[T]{
2023-07-07 16:05:52 +00:00
name: name,
root: directory,
2023-07-08 15:26:36 +00:00
storage: &FileStorage[T]{},
2023-07-05 21:59:49 +00:00
}
2023-07-07 16:05:52 +00:00
return c, c.storage.Init(c)
2023-07-06 12:10:12 +00:00
}
// All returns a channel of all objects in the collection.
func (c *collection[T]) All() <-chan *T {
channel := make(chan *T)
go func() {
c.data.Range(func(key, value any) bool {
channel <- value.(*T)
return true
})
close(channel)
}()
return channel
2023-07-05 15:23:50 +00:00
}
2023-07-08 15:26:36 +00:00
// Clear deletes all objects from the collection.
func (c *collection[T]) Clear() {
c.data.Range(func(key, value any) bool {
c.Delete(key.(string))
return true
})
}
// Delete deletes a key from the collection.
func (c *collection[T]) Delete(key string) {
if !c.Exists(key) {
return
}
c.data.Delete(key)
c.storage.Delete(key)
}
// Exists returns whether or not the key exists.
func (c *collection[T]) Exists(key string) bool {
_, exists := c.data.Load(key)
return exists
}
// Get returns the value for the given key.
func (c *collection[T]) Get(key string) (*T, error) {
value, exists := c.data.Load(key)
if !exists {
return nil, &KeyNotFoundError{Key: key}
}
return value.(*T), nil
}
2023-07-06 21:46:47 +00:00
// Filter returns a channel of all objects that pass the given filter function.
func (c *collection[T]) Filter(filter func(*T) bool) <-chan *T {
channel := make(chan *T)
go func() {
c.data.Range(func(key, value any) bool {
if filter(value.(*T)) {
channel <- value.(*T)
}
return true
})
close(channel)
}()
return channel
}
2023-07-05 15:23:50 +00:00
// Set sets the value for the given key.
2023-07-06 12:10:12 +00:00
func (c *collection[T]) Set(key string, value *T) {
2023-07-05 15:23:50 +00:00
c.data.Store(key, value)
2023-07-07 16:05:52 +00:00
err := c.storage.Set(key, value)
2023-07-06 13:40:25 +00:00
if err != nil {
panic(err)
}
2023-07-06 12:10:12 +00:00
}
2023-07-05 21:59:49 +00:00
2023-07-08 15:26:36 +00:00
// Sync waits for all disk writes to finish before it returns.
func (c *collection[T]) Sync() {
c.storage.Sync()
2023-07-06 12:10:12 +00:00
}