changed store.Store to accept generic key type
This commit is contained in:
		
							parent
							
								
									e18116d859
								
							
						
					
					
						commit
						39df26ee21
					
				|  | @ -18,6 +18,9 @@ | ||||||
|     With this change the "multi-match" operators are also normalized in case the targetted colletion doesn't have any records |     With this change the "multi-match" operators are also normalized in case the targetted colletion doesn't have any records | ||||||
|     (_or in other words, `@collection.example.someField != "test"` will result to `true` if `example` collection has no records because it satisfies the condition that all available "example" records mustn't have `someField` equal to "test"_). |     (_or in other words, `@collection.example.someField != "test"` will result to `true` if `example` collection has no records because it satisfies the condition that all available "example" records mustn't have `someField` equal to "test"_). | ||||||
| 
 | 
 | ||||||
|  | - ⚠️ Changed the type definition of `store.Store[T any]` to `store.Store[K comparable, T any]` to allow support for custom store key types. | ||||||
|  |     For most users it should be non-breaking change, BUT if you are creating manually `store.New[any](nil)` instances you'll have to specify the key generic type, aka. `store.New[string, any](nil)`. | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| ## v0.23.12 | ## v0.23.12 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -111,7 +111,7 @@ func checkCollectionRateLimit(e *core.RequestEvent, collection *core.Collection, | ||||||
| //
 | //
 | ||||||
| //nolint:unused
 | //nolint:unused
 | ||||||
| func isClientRateLimited(e *core.RequestEvent, rtId string) bool { | func isClientRateLimited(e *core.RequestEvent, rtId string) bool { | ||||||
| 	rateLimiters, ok := e.App.Store().Get(rateLimitersStoreKey).(*store.Store[*rateLimiter]) | 	rateLimiters, ok := e.App.Store().Get(rateLimitersStoreKey).(*store.Store[string, *rateLimiter]) | ||||||
| 	if !ok || rateLimiters == nil { | 	if !ok || rateLimiters == nil { | ||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
|  | @ -146,7 +146,7 @@ func checkRateLimit(e *core.RequestEvent, rtId string, rule core.RateLimitRule) | ||||||
| 
 | 
 | ||||||
| 	rateLimiters := e.App.Store().GetOrSet(rateLimitersStoreKey, func() any { | 	rateLimiters := e.App.Store().GetOrSet(rateLimitersStoreKey, func() any { | ||||||
| 		return initRateLimitersStore(e.App) | 		return initRateLimitersStore(e.App) | ||||||
| 	}).(*store.Store[*rateLimiter]) | 	}).(*store.Store[string, *rateLimiter]) | ||||||
| 	if rateLimiters == nil { | 	if rateLimiters == nil { | ||||||
| 		e.App.Logger().Warn("Failed to retrieve app rate limiters store") | 		e.App.Logger().Warn("Failed to retrieve app rate limiters store") | ||||||
| 		return nil | 		return nil | ||||||
|  | @ -198,9 +198,9 @@ func destroyRateLimitersStore(app core.App) { | ||||||
| 	app.Store().Remove(rateLimitersStoreKey) | 	app.Store().Remove(rateLimitersStoreKey) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func initRateLimitersStore(app core.App) *store.Store[*rateLimiter] { | func initRateLimitersStore(app core.App) *store.Store[string, *rateLimiter] { | ||||||
| 	app.Cron().Add(rateLimitersCronKey, "2 * * * *", func() { // offset a little since too many cleanup tasks execute at 00
 | 	app.Cron().Add(rateLimitersCronKey, "2 * * * *", func() { // offset a little since too many cleanup tasks execute at 00
 | ||||||
| 		limitersStore, ok := app.Store().Get(rateLimitersStoreKey).(*store.Store[*rateLimiter]) | 		limitersStore, ok := app.Store().Get(rateLimitersStoreKey).(*store.Store[string, *rateLimiter]) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  | @ -225,7 +225,7 @@ func initRateLimitersStore(app core.App) *store.Store[*rateLimiter] { | ||||||
| 		}, | 		}, | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	return store.New[*rateLimiter](nil) | 	return store.New[string, *rateLimiter](nil) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func newRateLimiter(maxAllowed int, intervalInSec int64, minDeleteIntervalInSec int64) *rateLimiter { | func newRateLimiter(maxAllowed int, intervalInSec int64, minDeleteIntervalInSec int64) *rateLimiter { | ||||||
|  |  | ||||||
|  | @ -71,7 +71,7 @@ type App interface { | ||||||
| 	Settings() *Settings | 	Settings() *Settings | ||||||
| 
 | 
 | ||||||
| 	// Store returns the app runtime store.
 | 	// Store returns the app runtime store.
 | ||||||
| 	Store() *store.Store[any] | 	Store() *store.Store[string, any] | ||||||
| 
 | 
 | ||||||
| 	// Cron returns the app cron instance.
 | 	// Cron returns the app cron instance.
 | ||||||
| 	Cron() *cron.Cron | 	Cron() *cron.Cron | ||||||
|  |  | ||||||
|  | @ -70,7 +70,7 @@ var _ App = (*BaseApp)(nil) | ||||||
| type BaseApp struct { | type BaseApp struct { | ||||||
| 	config              *BaseAppConfig | 	config              *BaseAppConfig | ||||||
| 	txInfo              *txAppInfo | 	txInfo              *txAppInfo | ||||||
| 	store               *store.Store[any] | 	store               *store.Store[string, any] | ||||||
| 	cron                *cron.Cron | 	cron                *cron.Cron | ||||||
| 	settings            *Settings | 	settings            *Settings | ||||||
| 	subscriptionsBroker *subscriptions.Broker | 	subscriptionsBroker *subscriptions.Broker | ||||||
|  | @ -194,7 +194,7 @@ type BaseApp struct { | ||||||
| func NewBaseApp(config BaseAppConfig) *BaseApp { | func NewBaseApp(config BaseAppConfig) *BaseApp { | ||||||
| 	app := &BaseApp{ | 	app := &BaseApp{ | ||||||
| 		settings:            newDefaultSettings(), | 		settings:            newDefaultSettings(), | ||||||
| 		store:               store.New[any](nil), | 		store:               store.New[string, any](nil), | ||||||
| 		cron:                cron.New(), | 		cron:                cron.New(), | ||||||
| 		subscriptionsBroker: subscriptions.NewBroker(), | 		subscriptionsBroker: subscriptions.NewBroker(), | ||||||
| 		config:              &config, | 		config:              &config, | ||||||
|  | @ -532,7 +532,7 @@ func (app *BaseApp) Settings() *Settings { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Store returns the app runtime store.
 | // Store returns the app runtime store.
 | ||||||
| func (app *BaseApp) Store() *store.Store[any] { | func (app *BaseApp) Store() *store.Store[string, any] { | ||||||
| 	return app.store | 	return app.store | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ import ( | ||||||
| 	"github.com/spf13/cast" | 	"github.com/spf13/cast" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var cachedColors = store.New[*color.Color](nil) | var cachedColors = store.New[string, *color.Color](nil) | ||||||
| 
 | 
 | ||||||
| // getColor returns [color.Color] object and cache it (if not already).
 | // getColor returns [color.Color] object and cache it (if not already).
 | ||||||
| func getColor(attrs ...color.Attribute) (c *color.Color) { | func getColor(attrs ...color.Attribute) (c *color.Color) { | ||||||
|  |  | ||||||
|  | @ -37,9 +37,9 @@ var ( | ||||||
| type Record struct { | type Record struct { | ||||||
| 	collection       *Collection | 	collection       *Collection | ||||||
| 	originalData     map[string]any | 	originalData     map[string]any | ||||||
| 	customVisibility *store.Store[bool] | 	customVisibility *store.Store[string, bool] | ||||||
| 	data             *store.Store[any] | 	data             *store.Store[string, any] | ||||||
| 	expand           *store.Store[any] | 	expand           *store.Store[string, any] | ||||||
| 
 | 
 | ||||||
| 	BaseModel | 	BaseModel | ||||||
| 
 | 
 | ||||||
|  | @ -537,8 +537,8 @@ func newRecordsFromNullStringMaps(collection *Collection, rows []dbx.NullStringM | ||||||
| func NewRecord(collection *Collection) *Record { | func NewRecord(collection *Collection) *Record { | ||||||
| 	record := &Record{ | 	record := &Record{ | ||||||
| 		collection:       collection, | 		collection:       collection, | ||||||
| 		data:             store.New[any](nil), | 		data:             store.New[string, any](nil), | ||||||
| 		customVisibility: store.New[bool](nil), | 		customVisibility: store.New[string, bool](nil), | ||||||
| 		originalData:     make(map[string]any, len(collection.Fields)), | 		originalData:     make(map[string]any, len(collection.Fields)), | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -681,7 +681,7 @@ func (m *Record) Expand() map[string]any { | ||||||
| // SetExpand replaces the current Record's expand with the provided expand arg data (shallow copied).
 | // SetExpand replaces the current Record's expand with the provided expand arg data (shallow copied).
 | ||||||
| func (m *Record) SetExpand(expand map[string]any) { | func (m *Record) SetExpand(expand map[string]any) { | ||||||
| 	if m.expand == nil { | 	if m.expand == nil { | ||||||
| 		m.expand = store.New[any](nil) | 		m.expand = store.New[string, any](nil) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	m.expand.Reset(expand) | 	m.expand.Reset(expand) | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ import ( | ||||||
| 	"github.com/spf13/cast" | 	"github.com/spf13/cast" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var cachedPatterns = store.New[*regexp.Regexp](nil) | var cachedPatterns = store.New[string, *regexp.Regexp](nil) | ||||||
| 
 | 
 | ||||||
| // SubtractSlice returns a new slice with only the "base" elements
 | // SubtractSlice returns a new slice with only the "base" elements
 | ||||||
| // that don't exist in "subtract".
 | // that don't exist in "subtract".
 | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ type Event struct { | ||||||
| 
 | 
 | ||||||
| 	hook.Event | 	hook.Event | ||||||
| 
 | 
 | ||||||
| 	data store.Store[any] | 	data store.Store[string, any] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // RWUnwrapper specifies that an http.ResponseWriter could be "unwrapped"
 | // RWUnwrapper specifies that an http.ResponseWriter could be "unwrapped"
 | ||||||
|  |  | ||||||
|  | @ -9,15 +9,15 @@ import ( | ||||||
| const ShrinkThreshold = 200 // the number is arbitrary chosen
 | const ShrinkThreshold = 200 // the number is arbitrary chosen
 | ||||||
| 
 | 
 | ||||||
| // Store defines a concurrent safe in memory key-value data store.
 | // Store defines a concurrent safe in memory key-value data store.
 | ||||||
| type Store[T any] struct { | type Store[K comparable, T any] struct { | ||||||
| 	data    map[string]T | 	data    map[K]T | ||||||
| 	mu      sync.RWMutex | 	mu      sync.RWMutex | ||||||
| 	deleted int64 | 	deleted int64 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // New creates a new Store[T] instance with a shallow copy of the provided data (if any).
 | // 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] { | func New[K comparable, T any](data map[K]T) *Store[K, T] { | ||||||
| 	s := &Store[T]{} | 	s := &Store[K, T]{} | ||||||
| 
 | 
 | ||||||
| 	s.Reset(data) | 	s.Reset(data) | ||||||
| 
 | 
 | ||||||
|  | @ -26,24 +26,24 @@ func New[T any](data map[string]T) *Store[T] { | ||||||
| 
 | 
 | ||||||
| // Reset clears the store and replaces the store data with a
 | // Reset clears the store and replaces the store data with a
 | ||||||
| // shallow copy of the provided newData.
 | // shallow copy of the provided newData.
 | ||||||
| func (s *Store[T]) Reset(newData map[string]T) { | func (s *Store[K, T]) Reset(newData map[K]T) { | ||||||
| 	s.mu.Lock() | 	s.mu.Lock() | ||||||
| 	defer s.mu.Unlock() | 	defer s.mu.Unlock() | ||||||
| 
 | 
 | ||||||
| 	if len(newData) > 0 { | 	if len(newData) > 0 { | ||||||
| 		s.data = make(map[string]T, len(newData)) | 		s.data = make(map[K]T, len(newData)) | ||||||
| 		for k, v := range newData { | 		for k, v := range newData { | ||||||
| 			s.data[k] = v | 			s.data[k] = v | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		s.data = make(map[string]T) | 		s.data = make(map[K]T) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	s.deleted = 0 | 	s.deleted = 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Length returns the current number of elements in the store.
 | // Length returns the current number of elements in the store.
 | ||||||
| func (s *Store[T]) Length() int { | func (s *Store[K, T]) Length() int { | ||||||
| 	s.mu.RLock() | 	s.mu.RLock() | ||||||
| 	defer s.mu.RUnlock() | 	defer s.mu.RUnlock() | ||||||
| 
 | 
 | ||||||
|  | @ -51,14 +51,14 @@ func (s *Store[T]) Length() int { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // RemoveAll removes all the existing store entries.
 | // RemoveAll removes all the existing store entries.
 | ||||||
| func (s *Store[T]) RemoveAll() { | func (s *Store[K, T]) RemoveAll() { | ||||||
| 	s.Reset(nil) | 	s.Reset(nil) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Remove removes a single entry from the store.
 | // Remove removes a single entry from the store.
 | ||||||
| //
 | //
 | ||||||
| // Remove does nothing if key doesn't exist in the store.
 | // Remove does nothing if key doesn't exist in the store.
 | ||||||
| func (s *Store[T]) Remove(key string) { | func (s *Store[K, T]) Remove(key K) { | ||||||
| 	s.mu.Lock() | 	s.mu.Lock() | ||||||
| 	defer s.mu.Unlock() | 	defer s.mu.Unlock() | ||||||
| 
 | 
 | ||||||
|  | @ -69,7 +69,7 @@ func (s *Store[T]) Remove(key string) { | ||||||
| 	//
 | 	//
 | ||||||
| 	// @todo remove after https://github.com/golang/go/issues/20135
 | 	// @todo remove after https://github.com/golang/go/issues/20135
 | ||||||
| 	if s.deleted >= ShrinkThreshold { | 	if s.deleted >= ShrinkThreshold { | ||||||
| 		newData := make(map[string]T, len(s.data)) | 		newData := make(map[K]T, len(s.data)) | ||||||
| 		for k, v := range s.data { | 		for k, v := range s.data { | ||||||
| 			newData[k] = v | 			newData[k] = v | ||||||
| 		} | 		} | ||||||
|  | @ -79,7 +79,7 @@ func (s *Store[T]) Remove(key string) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Has checks if element with the specified key exist or not.
 | // Has checks if element with the specified key exist or not.
 | ||||||
| func (s *Store[T]) Has(key string) bool { | func (s *Store[K, T]) Has(key K) bool { | ||||||
| 	s.mu.RLock() | 	s.mu.RLock() | ||||||
| 	defer s.mu.RUnlock() | 	defer s.mu.RUnlock() | ||||||
| 
 | 
 | ||||||
|  | @ -91,7 +91,7 @@ func (s *Store[T]) Has(key string) bool { | ||||||
| // Get returns a single element value from the store.
 | // Get returns a single element value from the store.
 | ||||||
| //
 | //
 | ||||||
| // If key is not set, the zero T value is returned.
 | // If key is not set, the zero T value is returned.
 | ||||||
| func (s *Store[T]) Get(key string) T { | func (s *Store[K, T]) Get(key K) T { | ||||||
| 	s.mu.RLock() | 	s.mu.RLock() | ||||||
| 	defer s.mu.RUnlock() | 	defer s.mu.RUnlock() | ||||||
| 
 | 
 | ||||||
|  | @ -99,7 +99,7 @@ func (s *Store[T]) Get(key string) T { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetOk is similar to Get but returns also a boolean indicating whether the key exists or not.
 | // GetOk is similar to Get but returns also a boolean indicating whether the key exists or not.
 | ||||||
| func (s *Store[T]) GetOk(key string) (T, bool) { | func (s *Store[K, T]) GetOk(key K) (T, bool) { | ||||||
| 	s.mu.RLock() | 	s.mu.RLock() | ||||||
| 	defer s.mu.RUnlock() | 	defer s.mu.RUnlock() | ||||||
| 
 | 
 | ||||||
|  | @ -109,11 +109,11 @@ func (s *Store[T]) GetOk(key string) (T, bool) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetAll returns a shallow copy of the current store data.
 | // GetAll returns a shallow copy of the current store data.
 | ||||||
| func (s *Store[T]) GetAll() map[string]T { | func (s *Store[K, T]) GetAll() map[K]T { | ||||||
| 	s.mu.RLock() | 	s.mu.RLock() | ||||||
| 	defer s.mu.RUnlock() | 	defer s.mu.RUnlock() | ||||||
| 
 | 
 | ||||||
| 	var clone = make(map[string]T, len(s.data)) | 	var clone = make(map[K]T, len(s.data)) | ||||||
| 
 | 
 | ||||||
| 	for k, v := range s.data { | 	for k, v := range s.data { | ||||||
| 		clone[k] = v | 		clone[k] = v | ||||||
|  | @ -123,7 +123,7 @@ func (s *Store[T]) GetAll() map[string]T { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Values returns a slice with all of the current store values.
 | // Values returns a slice with all of the current store values.
 | ||||||
| func (s *Store[T]) Values() []T { | func (s *Store[K, T]) Values() []T { | ||||||
| 	s.mu.RLock() | 	s.mu.RLock() | ||||||
| 	defer s.mu.RUnlock() | 	defer s.mu.RUnlock() | ||||||
| 
 | 
 | ||||||
|  | @ -137,12 +137,12 @@ func (s *Store[T]) Values() []T { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Set sets (or overwrite if already exist) a new value for key.
 | // Set sets (or overwrite if already exist) a new value for key.
 | ||||||
| func (s *Store[T]) Set(key string, value T) { | func (s *Store[K, T]) Set(key K, value T) { | ||||||
| 	s.mu.Lock() | 	s.mu.Lock() | ||||||
| 	defer s.mu.Unlock() | 	defer s.mu.Unlock() | ||||||
| 
 | 
 | ||||||
| 	if s.data == nil { | 	if s.data == nil { | ||||||
| 		s.data = make(map[string]T) | 		s.data = make(map[K]T) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	s.data[key] = value | 	s.data[key] = value | ||||||
|  | @ -150,7 +150,7 @@ func (s *Store[T]) Set(key string, value T) { | ||||||
| 
 | 
 | ||||||
| // GetOrSet retrieves a single existing value for the provided key
 | // GetOrSet retrieves a single existing value for the provided key
 | ||||||
| // or stores a new one if it doesn't exist.
 | // or stores a new one if it doesn't exist.
 | ||||||
| func (s *Store[T]) GetOrSet(key string, setFunc func() T) T { | func (s *Store[K, T]) GetOrSet(key K, setFunc func() T) T { | ||||||
| 	// lock only reads to minimize locks contention
 | 	// lock only reads to minimize locks contention
 | ||||||
| 	s.mu.RLock() | 	s.mu.RLock() | ||||||
| 	v, ok := s.data[key] | 	v, ok := s.data[key] | ||||||
|  | @ -160,7 +160,7 @@ func (s *Store[T]) GetOrSet(key string, setFunc func() T) T { | ||||||
| 		s.mu.Lock() | 		s.mu.Lock() | ||||||
| 		v = setFunc() | 		v = setFunc() | ||||||
| 		if s.data == nil { | 		if s.data == nil { | ||||||
| 			s.data = make(map[string]T) | 			s.data = make(map[K]T) | ||||||
| 		} | 		} | ||||||
| 		s.data[key] = v | 		s.data[key] = v | ||||||
| 		s.mu.Unlock() | 		s.mu.Unlock() | ||||||
|  | @ -174,12 +174,12 @@ func (s *Store[T]) GetOrSet(key string, setFunc func() T) T { | ||||||
| // This method is similar to Set() but **it will skip adding new elements**
 | // 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.
 | // to the store if the store length has reached the specified limit.
 | ||||||
| // false is returned if maxAllowedElements limit is reached.
 | // false is returned if maxAllowedElements limit is reached.
 | ||||||
| func (s *Store[T]) SetIfLessThanLimit(key string, value T, maxAllowedElements int) bool { | func (s *Store[K, T]) SetIfLessThanLimit(key K, value T, maxAllowedElements int) bool { | ||||||
| 	s.mu.Lock() | 	s.mu.Lock() | ||||||
| 	defer s.mu.Unlock() | 	defer s.mu.Unlock() | ||||||
| 
 | 
 | ||||||
| 	if s.data == nil { | 	if s.data == nil { | ||||||
| 		s.data = make(map[string]T) | 		s.data = make(map[K]T) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// check for existing item
 | 	// check for existing item
 | ||||||
|  | @ -200,8 +200,8 @@ func (s *Store[T]) SetIfLessThanLimit(key string, value T, maxAllowedElements in | ||||||
| // provided JSON data into the store.
 | // provided JSON data into the store.
 | ||||||
| //
 | //
 | ||||||
| // The store entries that match with the ones from the data will be overwritten with the new value.
 | // The store entries that match with the ones from the data will be overwritten with the new value.
 | ||||||
| func (s *Store[T]) UnmarshalJSON(data []byte) error { | func (s *Store[K, T]) UnmarshalJSON(data []byte) error { | ||||||
| 	raw := map[string]T{} | 	raw := map[K]T{} | ||||||
| 	if err := json.Unmarshal(data, &raw); err != nil { | 	if err := json.Unmarshal(data, &raw); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | @ -210,7 +210,7 @@ func (s *Store[T]) UnmarshalJSON(data []byte) error { | ||||||
| 	defer s.mu.Unlock() | 	defer s.mu.Unlock() | ||||||
| 
 | 
 | ||||||
| 	if s.data == nil { | 	if s.data == nil { | ||||||
| 		s.data = make(map[string]T) | 		s.data = make(map[K]T) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for k, v := range raw { | 	for k, v := range raw { | ||||||
|  | @ -222,6 +222,6 @@ func (s *Store[T]) UnmarshalJSON(data []byte) error { | ||||||
| 
 | 
 | ||||||
| // MarshalJSON implements [json.Marshaler] and export the current
 | // MarshalJSON implements [json.Marshaler] and export the current
 | ||||||
| // store data into valid JSON.
 | // store data into valid JSON.
 | ||||||
| func (s *Store[T]) MarshalJSON() ([]byte, error) { | func (s *Store[K, T]) MarshalJSON() ([]byte, error) { | ||||||
| 	return json.Marshal(s.GetAll()) | 	return json.Marshal(s.GetAll()) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -227,7 +227,7 @@ func TestValues(t *testing.T) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestSet(t *testing.T) { | func TestSet(t *testing.T) { | ||||||
| 	s := store.Store[int]{} | 	s := store.Store[string, int]{} | ||||||
| 
 | 
 | ||||||
| 	data := map[string]int{"test1": 0, "test2": 1, "test3": 3} | 	data := map[string]int{"test1": 0, "test2": 1, "test3": 3} | ||||||
| 
 | 
 | ||||||
|  | @ -281,7 +281,7 @@ func TestGetOrSet(t *testing.T) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestSetIfLessThanLimit(t *testing.T) { | func TestSetIfLessThanLimit(t *testing.T) { | ||||||
| 	s := store.Store[int]{} | 	s := store.Store[string, int]{} | ||||||
| 
 | 
 | ||||||
| 	limit := 2 | 	limit := 2 | ||||||
| 
 | 
 | ||||||
|  | @ -316,7 +316,7 @@ func TestSetIfLessThanLimit(t *testing.T) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestUnmarshalJSON(t *testing.T) { | func TestUnmarshalJSON(t *testing.T) { | ||||||
| 	s := store.Store[string]{} | 	s := store.Store[string, string]{} | ||||||
| 	s.Set("b", "old")   // should be overwritten
 | 	s.Set("b", "old")   // should be overwritten
 | ||||||
| 	s.Set("c", "test3") // ensures that the old values are not removed
 | 	s.Set("c", "test3") // ensures that the old values are not removed
 | ||||||
| 
 | 
 | ||||||
|  | @ -339,7 +339,7 @@ func TestUnmarshalJSON(t *testing.T) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestMarshalJSON(t *testing.T) { | func TestMarshalJSON(t *testing.T) { | ||||||
| 	s := &store.Store[string]{} | 	s := &store.Store[string, string]{} | ||||||
| 	s.Set("a", "test1") | 	s.Set("a", "test1") | ||||||
| 	s.Set("b", "test2") | 	s.Set("b", "test2") | ||||||
| 
 | 
 | ||||||
|  | @ -356,7 +356,7 @@ func TestMarshalJSON(t *testing.T) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestShrink(t *testing.T) { | func TestShrink(t *testing.T) { | ||||||
| 	s := &store.Store[int]{} | 	s := &store.Store[string, int]{} | ||||||
| 
 | 
 | ||||||
| 	total := 1000 | 	total := 1000 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,13 +9,13 @@ import ( | ||||||
| 
 | 
 | ||||||
| // Broker defines a struct for managing subscriptions clients.
 | // Broker defines a struct for managing subscriptions clients.
 | ||||||
| type Broker struct { | type Broker struct { | ||||||
| 	store *store.Store[Client] | 	store *store.Store[string, Client] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NewBroker initializes and returns a new Broker instance.
 | // NewBroker initializes and returns a new Broker instance.
 | ||||||
| func NewBroker() *Broker { | func NewBroker() *Broker { | ||||||
| 	return &Broker{ | 	return &Broker{ | ||||||
| 		store: store.New[Client](nil), | 		store: store.New[string, Client](nil), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -37,7 +37,7 @@ import ( | ||||||
| // Use the Registry.Load* methods to load templates into the registry.
 | // Use the Registry.Load* methods to load templates into the registry.
 | ||||||
| func NewRegistry() *Registry { | func NewRegistry() *Registry { | ||||||
| 	return &Registry{ | 	return &Registry{ | ||||||
| 		cache: store.New[*Renderer](nil), | 		cache: store.New[string, *Renderer](nil), | ||||||
| 		funcs: template.FuncMap{ | 		funcs: template.FuncMap{ | ||||||
| 			"raw": func(str string) template.HTML { | 			"raw": func(str string) template.HTML { | ||||||
| 				return template.HTML(str) | 				return template.HTML(str) | ||||||
|  | @ -50,7 +50,7 @@ func NewRegistry() *Registry { | ||||||
| //
 | //
 | ||||||
| // Use the Registry.Load* methods to load templates into the registry.
 | // Use the Registry.Load* methods to load templates into the registry.
 | ||||||
| type Registry struct { | type Registry struct { | ||||||
| 	cache *store.Store[*Renderer] | 	cache *store.Store[string, *Renderer] | ||||||
| 	funcs template.FuncMap | 	funcs template.FuncMap | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue