Skip to content

Commit

Permalink
Merge pull request #18 from hyp3rd/development
Browse files Browse the repository at this point in the history
Redis backend support, ISerializer interface, refactoring
  • Loading branch information
hyp3rd authored Jan 16, 2023
2 parents 5c2b46d + e945b56 commit 283ec1e
Show file tree
Hide file tree
Showing 20 changed files with 642 additions and 273 deletions.
111 changes: 84 additions & 27 deletions backend/options.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,58 @@
package backend

import (
"github.com/go-redis/redis"
"github.com/go-redis/redis/v9"
"github.com/hyp3rd/hypercache/libs/serializer"
"github.com/hyp3rd/hypercache/models"
"github.com/hyp3rd/hypercache/types"
)

// ISortableBackend is an interface that defines the methods that a backend should implement to be sortable.
type iSortableBackend interface {
// setSortAscending indicates whether the items should be sorted in ascending order.
setSortAscending(ascending bool)
// setSortBy sets the field to sort the items by.
setSortBy(sortBy string)
}

// setSortAscending sets the `SortAscending` field of the `InMemory` backend.
func (inm *InMemory) setSortAscending(ascending bool) {
inm.SortAscending = ascending
}

// setSortAscending sets the `SortAscending` field of the `RedisBackend` backend.
func (rb *RedisBackend) setSortAscending(ascending bool) {
rb.SortAscending = ascending
}

// setSortBy sets the `SortBy` field of the `InMemory` backend.
func (inm *InMemory) setSortBy(sortBy string) {
inm.SortBy = sortBy
}

// setSortBy sets the `SortBy` field of the `RedisBackend` backend.
func (rb *RedisBackend) setSortBy(sortBy string) {
rb.SortBy = sortBy
}

// FilterFunc is a predicate that takes a `Item` as an argument and returns a boolean indicating whether the item should be included in the cache.
type FilterFunc func(item *models.Item) bool // filters applied when listing the items in the cache

// IFilterableBackend is an interface that defines the methods that a backend should implement to be filterable.
type IFilterableBackend interface {
setFilterFunc(filterFunc FilterFunc)
}

// setFilterFunc sets the `FilterFunc` field of the `InMemory` backend.
func (inm *InMemory) setFilterFunc(filterFunc FilterFunc) {
inm.FilterFunc = filterFunc
}

// setFilterFunc sets the `FilterFunc` field of the `RedisBackend` backend.
func (rb *RedisBackend) setFilterFunc(filterFunc FilterFunc) {
rb.FilterFunc = filterFunc
}

// Option is a function type that can be used to configure the `HyperCache` struct.
type Option[T IBackendConstrain] func(*T)

Expand All @@ -26,49 +73,53 @@ func WithCapacity[T InMemory](capacity int) Option[InMemory] {
// WithRedisClient is an option that sets the redis client to use.
func WithRedisClient[T RedisBackend](client *redis.Client) Option[RedisBackend] {
return func(backend *RedisBackend) {
backend.client = client
backend.rdb = client
}
}

// WithKeysSetName is an option that sets the name of the set that holds the keys of the items in the cache
func WithKeysSetName[T RedisBackend](keysSetName string) Option[RedisBackend] {
return func(backend *RedisBackend) {
backend.keysSetName = keysSetName
}
}

// WithSerializer is an option that sets the serializer to use. The serializer is used to serialize and deserialize the items in the cache.
// - The default serializer is `serializer.MsgpackSerializer`.
// - The `serializer.JSONSerializer` can be used to serialize and deserialize the items in the cache as JSON.
// - The interface `serializer.ISerializer` can be implemented to use a custom serializer.
func WithSerializer[T RedisBackend](serializer serializer.ISerializer) Option[RedisBackend] {
return func(backend *RedisBackend) {
backend.Serializer = serializer
}
}

// FilterOption is a function type that can be used to configure the `Filter` struct.
type FilterOption[T any] func(*T)

// ApplyFilterOptions applies the given options to the given filter.
func ApplyFilterOptions[T any](backend *T, options ...FilterOption[T]) {
func ApplyFilterOptions[T IBackendConstrain](backend *T, options ...FilterOption[T]) {
for _, option := range options {
option(backend)
}
}

// WithSortBy is an option that sets the field to sort the items by.
// The field can be any of the fields in the `Item` struct.
func WithSortBy[T any](field types.SortingField) FilterOption[T] {
func WithSortBy[T IBackendConstrain](field types.SortingField) FilterOption[T] {
return func(a *T) {
switch filter := any(a).(type) {
case *InMemory:
filter.SortBy = field.String()
if sortable, ok := any(a).(iSortableBackend); ok {
sortable.setSortBy(field.String())
}
}
}

// WithSortAscending is an option that sets the sort order to ascending.
// When sorting the items in the cache, they will be sorted in ascending order based on the field specified with the `WithSortBy` option.
func WithSortAscending[T any]() FilterOption[T] {
// WithSortOrderAsc is an option that sets the sort order to ascending or descending.
// When sorting the items in the cache, they will be sorted in ascending or descending order based on the field specified with the `WithSortBy` option.
func WithSortOrderAsc[T IBackendConstrain](ascending bool) FilterOption[T] {
return func(a *T) {
switch filter := any(a).(type) {
case *InMemory:
filter.SortAscending = true
}
}
}

// WithSortDescending is an option that sets the sort order to descending.
// When sorting the items in the cache, they will be sorted in descending order based on the field specified with the `WithSortBy` option.
func WithSortDescending[T any]() FilterOption[T] {
return func(a *T) {
switch filter := any(a).(type) {
case *InMemory:
filter.SortAscending = false
if sortable, ok := any(a).(iSortableBackend); ok {
sortable.setSortAscending(ascending)
}
}
}
Expand All @@ -77,9 +128,15 @@ func WithSortDescending[T any]() FilterOption[T] {
// The filter function is a predicate that takes a `Item` as an argument and returns a boolean indicating whether the item should be included in the cache.
func WithFilterFunc[T any](fn func(item *models.Item) bool) FilterOption[T] {
return func(a *T) {
switch filter := any(a).(type) {
case *InMemory:
filter.FilterFunc = fn
if filterable, ok := any(a).(IFilterableBackend); ok {
filterable.setFilterFunc(fn)
}
}

// return func(a *T) {
// switch filter := any(a).(type) {
// case *InMemory:
// filter.FilterFunc = fn
// }
// }
}
Loading

0 comments on commit 283ec1e

Please sign in to comment.