123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- package store
- import (
- "fmt"
- "sync"
- "github.com/google/uuid"
- )
- type IDer interface {
- GetID() string
- SetID(string)
- }
- type Hasher interface {
- GetHash() string
- }
- type Storable interface {
- IDer
- Hasher
- }
- type Storer[T Storable] interface {
- Create(T) (T, error)
- ReadAll() []T
- Read(string) (T, error)
- Update(T, string) (T, error)
- Delete(string) (T, error)
- }
- type FilterStorer[T Storable] interface {
- Storer[T]
- Filter([]T, func(T) bool) []T
- }
- type Store[T Storable] struct {
- ids map[string]T
- hashes map[string]T
- lock sync.RWMutex
- }
- type FilterStore[T Storable] struct {
- *Store[T]
- }
- func NewFilterStore[T Storable]() *FilterStore[T] {
- return &FilterStore[T]{NewStore[T]()}
- }
- func (fs *FilterStore[T]) Filter(slice []T, f func(T) bool) []T {
- result := make([]T, 0)
- for _, item := range slice {
- if f(item) {
- result = append(result, item)
- }
- }
- return result
- }
- func NewStore[T Storable]() *Store[T] {
- store := new(Store[T])
- store.ids = make(map[string]T)
- store.hashes = make(map[string]T)
- return store
- }
- func (s *Store[T]) Create(entity T) (T, error) {
- s.lock.Lock()
- defer s.lock.Unlock()
- if hash := entity.GetHash(); hash != "" {
- storedEntity, ok := s.hashes[hash]
- if ok {
- return storedEntity, nil
- }
- s.hashes[hash] = entity
- }
- id := entity.GetID()
- if id == "" {
- id = uuid.New().String()
- }
- entity.SetID(id)
- s.ids[id] = entity
- return entity, nil
- }
- func (s *Store[T]) ReadAll() []T {
- s.lock.Lock()
- defer s.lock.Unlock()
- result := make([]T, 0)
- for _, v := range s.ids {
- result = append(result, v)
- }
- return result
- }
- func (s *Store[T]) Read(id string) (T, error) {
- s.lock.RLock()
- defer s.lock.RUnlock()
- entity, ok := s.ids[id]
- if !ok {
- return entity, fmt.Errorf("Entity with ID %s was not found in the store.", id)
- }
- return entity, nil
- }
- func (s *Store[T]) Update(entity T, id string) (T, error) {
- sEntity, err := s.Read(id)
- if err != nil {
- return sEntity, err
- }
- s.lock.Lock()
- defer s.lock.Unlock()
- entity.SetID(id)
- s.ids[id] = entity
- if hash := entity.GetHash(); hash != "" {
- s.hashes[hash] = entity
- }
- return entity, nil
- }
- func (s *Store[T]) Delete(id string) (T, error) {
- sEntity, err := s.Read(id)
- if err != nil {
- return sEntity, err
- }
- s.lock.Lock()
- defer s.lock.Unlock()
- delete(s.ids, id)
- if hash := sEntity.GetHash(); hash != "" {
- delete(s.hashes, hash)
- }
- return sEntity, nil
- }
|