mirror of
https://github.com/pocketbase/pocketbase.git
synced 2024-12-03 03:18:56 +02:00
134 lines
2.7 KiB
Go
134 lines
2.7 KiB
Go
package store
|
|
|
|
import "sync"
|
|
|
|
// Store defines a concurrent safe in memory key-value data store.
|
|
type Store[T any] struct {
|
|
mux sync.RWMutex
|
|
data map[string]T
|
|
}
|
|
|
|
// New creates a new Store[T] instance with a shallow copy of the provided data (if any).
|
|
func New[T any](data map[string]T) *Store[T] {
|
|
s := &Store[T]{}
|
|
|
|
s.Reset(data)
|
|
|
|
return s
|
|
}
|
|
|
|
// Reset clears the store and replaces the store data with a
|
|
// shallow copy of the provided newData.
|
|
func (s *Store[T]) Reset(newData map[string]T) {
|
|
s.mux.Lock()
|
|
defer s.mux.Unlock()
|
|
|
|
var clone = make(map[string]T, len(newData))
|
|
|
|
for k, v := range newData {
|
|
clone[k] = v
|
|
}
|
|
|
|
s.data = clone
|
|
}
|
|
|
|
// Length returns the current number of elements in the store.
|
|
func (s *Store[T]) Length() int {
|
|
s.mux.RLock()
|
|
defer s.mux.RUnlock()
|
|
|
|
return len(s.data)
|
|
}
|
|
|
|
// RemoveAll removes all the existing store entries.
|
|
func (s *Store[T]) RemoveAll() {
|
|
s.mux.Lock()
|
|
defer s.mux.Unlock()
|
|
|
|
s.data = make(map[string]T)
|
|
}
|
|
|
|
// Remove removes a single entry from the store.
|
|
//
|
|
// Remove does nothing if key doesn't exist in the store.
|
|
func (s *Store[T]) Remove(key string) {
|
|
s.mux.Lock()
|
|
defer s.mux.Unlock()
|
|
|
|
delete(s.data, key)
|
|
}
|
|
|
|
// Has checks if element with the specified key exist or not.
|
|
func (s *Store[T]) Has(key string) bool {
|
|
s.mux.RLock()
|
|
defer s.mux.RUnlock()
|
|
|
|
_, ok := s.data[key]
|
|
|
|
return ok
|
|
}
|
|
|
|
// Get returns a single element value from the store.
|
|
//
|
|
// If key is not set, the zero T value is returned.
|
|
func (s *Store[T]) Get(key string) T {
|
|
s.mux.RLock()
|
|
defer s.mux.RUnlock()
|
|
|
|
return s.data[key]
|
|
}
|
|
|
|
// GetAll returns a shallow copy of the current store data.
|
|
func (s *Store[T]) GetAll() map[string]T {
|
|
s.mux.RLock()
|
|
defer s.mux.RUnlock()
|
|
|
|
var clone = make(map[string]T, len(s.data))
|
|
|
|
for k, v := range s.data {
|
|
clone[k] = v
|
|
}
|
|
|
|
return clone
|
|
}
|
|
|
|
// Set sets (or overwrite if already exist) a new value for key.
|
|
func (s *Store[T]) Set(key string, value T) {
|
|
s.mux.Lock()
|
|
defer s.mux.Unlock()
|
|
|
|
if s.data == nil {
|
|
s.data = make(map[string]T)
|
|
}
|
|
|
|
s.data[key] = value
|
|
}
|
|
|
|
// SetIfLessThanLimit sets (or overwrite if already exist) a new value for key.
|
|
//
|
|
// This method is similar to Set() but **it will skip adding new elements**
|
|
// to the store if the store length has reached the specified limit.
|
|
// `false` is returned if maxAllowedElements limit is reached.
|
|
func (s *Store[T]) SetIfLessThanLimit(key string, value T, maxAllowedElements int) bool {
|
|
s.mux.Lock()
|
|
defer s.mux.Unlock()
|
|
|
|
// init map if not already
|
|
if s.data == nil {
|
|
s.data = make(map[string]T)
|
|
}
|
|
|
|
// check for existing item
|
|
_, ok := s.data[key]
|
|
|
|
if !ok && len(s.data) >= maxAllowedElements {
|
|
// cannot add more items
|
|
return false
|
|
}
|
|
|
|
// add/overwrite item
|
|
s.data[key] = value
|
|
|
|
return true
|
|
}
|