kredis

package module
v0.0.1-alpha3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 17, 2024 License: MIT Imports: 11 Imported by: 0

README

Kredis

kredis-go Go Reference

A port of Rails' Kredis for Go.

Kredis (Keyed Redis) encapsulates higher-level types and data structures around a single key, so you can interact with them as coherent objects rather than isolated procedural commands.

Motivation

I wrote a Go version of Kredis to help me learn Go and the Redis client package. This exercise also helped me explore generics in detail.

In theory, there should be full interoperability between this Go package and the Ruby version, thus enabling services in either language to work together over Redis.

Usage

To use Kredis, you must first configure a connection. The default connection configuration is named "shared". SetConfiguration expects a config name string, optional namespace (pass an empty string for no namespace), and a Redis URL connection string.

kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")

Kredis comes with a simple logger, which is useful for testing and development. The logger will output the Redis commands that are executed and how long they took. It's nearly identical to the output the we see in the Ruby Kredis version.

To enable debug logging, simply call:

kredis.EnableDebugLogging()
Failsafe

Kredis wraps calls in Redis in a failsafe. To match this design, certain functions around reading values intentionally omit returning an error and will return zero values when a read fails.

If you need to handle errors and do not want the "failsafe" behavior, most types also offer functions that end in Result that return the value and an error using standard Go idioms. For example:

slot, _ := kredis.NewSlot("slot", 3)
slot.Reserve()

// some time later when Redis is down...

t := slot.Taken()
// 0
t, err := slot.TakenResult() // func TakenResult() (int64, error)
// 0, dial tcp [::1]:6379: connect: connection refused

Types

Collection types:

All factory functions for the various types accept the following option functions:

  • WithConfigName sets the Redis config to use. The function accepts a string name and should match the value passed to SetConfiguration.
  • WithContext allows the user to specify the context.Context value passed to the underlying Redis client commands.
  • WithExpiry sets the expiration for type's key. The function accepts a string value that is parsed by time.ParseDuration to get a time.Duration value. When this option is used for scalar and other basic types, it usually means the Redis SET command is called with an expiration value. For collection types, whenever the collection is mutated (Append, Prepend, Add, Remove, etc.), the key is refreshed by calling the EXPIRE command after the mutation commands. Additionally, when this option is used, you can call RefreshTTL() at any point to refresh the key's expiration. The function returns a (bool, error), where the boolean value indicates whether the key was refreshed or not.
Counter
cntr, err := kredis.NewCounter("counter")
n, err := cntr.Increment(1) // MULTI, INCRBY counter 1, EXEC
// 1, nil
n, err := cntr.Increment(2) // MULTI, INCRBY counter 2, EXEC
// 3, nil
n, err := cntr.Decrement(3) // MULTI, DECRBY counter 3, EXEC
// 0, nil
cntr.Value()                // GET counter
// 0
Cycle
cycle, err := kredis.NewCycle("cycle", []string{"ready", "set", "go"})
cycle.Index()        // GET counter
// 0
err := cycle.Next()  // GET counter, SET counter 1
// nil
err = cycle.Next()   // GET counter, SET counter 2
// nil
cycle.Index()        // GET counter
// 2
val := cycle.Value() // GET counter
// "go"
Enum
vals := []string{"ready", "set", "go"}

enum, _ := kredis.NewEnum("enum", "go", vals) // SET enum go
enum.Is("go")                                 // GET enum
// true
val := enum.Value()                           // GET enum
// "go"
err := enum.SetValue("set")                   // SET enum set
// nil
err = enum.SetValue("error")
// invalid enum value (Kredis.EmptyValues error)
Flag

By default the Mark() function does not call SET with nx

flag, err := kredis.NewFlag("flag")
flag.IsMarked()                            // EXISTS flag
// false
err = flag.Mark()                          // SETNX flag 1
// nil
flag.IsMarked()                            // EXISTS flag
// true
err = flag.Remove()                        // DEL flag

flag.Mark(kredis.WithFlagMarkExpiry("1s")) // SET flag 1 ex 1
flag.IsMarked()                            // EXISTS flag
// true

time.Sleep(2 * time.Second)

flag.IsMarked()                            // EXISTS flag
// false

The SoftMark() function will call set with NX

flag.SoftMark(kredis.WithFlagMarkExpiry("1s"))  // SET flag 1 ex 1 nx
flag.SoftMark(kredis.WithFlagMarkExpiry("10s")) // SET flag 1 ex 10 nx
flag.IsMarked()                                 // EXISTS flag
// true

time.Sleep(2 * time.Second)

flag.IsMarked()                                 // EXISTS flag
// true
Limiter

The Limiter type is based off the Counter type and provides a simple rate limiting type with a failsafe on Reids errors. See the original Rails PR for more details.

IsExceeded() will return false in the event of a Redis error. Poke() does return an error, but it can easily be ignored in Go.

limiter, _ := kredis.NewLimiter("limiter", 5)
limiter.Poke()         // MULTI, INCRBY limiter 1 EXEC
limiter.Poke()         // MULTI, INCRBY limiter 1 EXEC
limiter.Poke()         // MULTI, INCRBY limiter 1 EXEC
limiter.Poke()         // MULTI, INCRBY limiter 1 EXEC

limiter.IsExceeded()   // GET limiter
// true
err := limiter.Reset() // DEL limiter
// nil
limiter.IsExceeded()   // GET limiter
// false
Slots
slot, err := kredis.NewSlot("slot", 3)
slot.Reserve()     // GET slot + INCR slot
// true
slot.IsAvailable() // GET slot
// true
slot.Taken()       // GET slot
// 1
slot.Reserve()     // GET slot + INCR slot
// true
slot.Reserve()     // GET slot + INCR slot
// true

slot.Reserve()     // GET slot
// false
slot.IsAvailable() // GET slot
// false
slot.Taken()       // GET slot
// 3

// Reserve() with one or more callbacks will always call Release() even
// if the callbacks are not invoked and there are no slots available
slot.Reserve(func () { fmt.Println("not called") })
// GET slot + DECR slot
// false
slot.Reserve(func () { fmt.Println("called") })
// GET slot + INCR slot + DECR slot
// true
Scalar types
  • NewBool and NewBoolWithDefault
  • NewInteger and NewIntegerWithDefault
  • NewString and NewStringWithDefault
  • NewTime and NewTimeWithDefault
  • NewJSON and NewJSONWithDefault
k, err := kredis.NewInteger("myint", Options{})
err = k.SetValue(1024)  // SET myint 1024
// nil
k.Value()               // GET myint
// 1024

With expiration through the WithExpiry option function:

k, err := kredis.NewTime("sessionStart", kredis.WithExpiry("30m"))
err = k.SetValue(time.Now()) // SET sessionStart 2024-01-06T13:30:35.613332-05:00 ex 1800
// nil
val := k.Value()             // GET sessionStart
// 2024-01-01 12:00:00 -0500 EST
dur := k.TTL()               // TTL sessionStart
// 30m0s

// over 30 minutes later
k.Value()                    // GET sessionStart
// nil
k.TTL()                      // TTL sessionStart
// -2ns (key does not exit now)
List
l := kredis.NewIntegerList("users")
n, err := l.Append(1, 2, 3)  // RPUSH users 1 2 3
// 3, nil
n, err = l.Prepend(9, 8)     // LPUSH users 9, 8
// 2, nil

ids = make([]int, 5)
n, err := l.Elements(ids)    // LRANGE users 0, 5
// 5, nil

// read some elements with an offset
lastTwo = make([]int, 2)
n, err = l.Elements(lastTwo, WithRangeStart(3)) // LRANGE users 3 5
// 2, nil

Different typed factories exist for the List struct:

  • NewBoolList
  • NewFloatList
  • NewStringList
  • NewTimeList over time.Time
  • NewJSONList over the KredisJSON alias type

It's possible to provide a default value as well, which will use WATCH to transactionally set the value if the key does not already exist. For lists, this entails calling Append and using RPUSH to add the default elements.

strs, err := kredis.NewStringListWithDefault("lines", []string{"hello", "redis"},)
// WATCH lines
// EXISTS lines
// RPUSH lines hello redis
// UNWATCH

err = strs.Remove("hello") // LREM lines 0 "hello"
// nil
n := strs.Length()          // LLEN lines
// 2
Set
t := time.Date(2021, 8, 28, 23, 0, 0, 0, time.UTC)
times := []time.Time{t, t.Add(1 * time.Hour), t.Add(2 * time.Hour), t.Add(3 * time.Hour)}
set, err := kredis.NewTimeSet("times")
set.Add(times...)                  // SADD times 2021-08-28T23:00:00Z 2021-08-29T00:00:00Z 2021-08-29T01:00:00Z 2021-08-29T02:00:00Z
// 4, nil
members, err := set.Members()      // SMEMBERS times
// []time.Time{...}, nil
set.Size()                         // SCARD times
// 4
set.Includes(t)                    // SISMEMBER times 2021-08-28T23:00:00Z
// true
set.Includes(t.Add(4 * time.Hour)) // SISMEMBER times 2021-08-29T03:00:00Z
// false
sample := make([]time.Time{}, 2)
n, err := set.Sample(sample)       // SRANDMEMBER times 2
// 2, nil

fmt.Println(sample)

Different factory functions exist for various Set types (this is the case for all collection types). It's possible to provide a default using the WithDefault factories.

kredis.NewStringSetWithDefault("set", []string{"a", "b", "c"})
// WATCH strings
// EXISTS strings
// SADD strings a b c
// UNWATCH

The Add function is used to set the default. Thus, SADD is used when the key does not already exist.

Hash
dogs := map[string]kredis.KredisJSON{"ollie": *kredis.NewKredisJSON(`{"weight":9.72}`), "leo": *kredis.NewKredisJSON(`{"weight":23.33}`)}
hash, _ := kredis.NewJSONHash("pets")

n, err := hash.Update(dogs)     // HSET pets ollie {"weight":9.72} leo {"weight":23.33}
// 2, nil
val, ok := hash.Get("ollie")    // HGET pets ollie
// {"weight":9.72}, true
keys, err := hash.Keys()        // HKEYS pets
// []string{"ollie", "leo"}, nil
vals, err := hash.Values()      // HVALS pets
// [{"weight":9.72} {"weight":23.33}], nil
entries, err := hash.Entries()  // HGETALL pets
// map[leo:{"weight":23.33}
//     ollie:{"weight":9.72}], nil
hash.Clear()                    // DEL pets
Ordered Set
oset, err := kredis.NewStringOrderedSet("ranks", 4)
add, rm, err := oset.Append("a", "b", "c") // MULTI
// 3, 0, nil                                  ZADD ranks 1.704562075576027e+09 a 1.7045620755760288e+09 b 1.7045620755760298e+09 c
                                           // ZREMRANGEBYRANK ranks 0 -5
                                           // EXEC
add, rm, err := oset.Append("a", "b", "c") // MULTI
// 2, 1, nil                                  ZADD ranks -1.704562075576382e+09 d -1.7045620755763829e+09 e
                                           // ZREMRANGEBYRANK ranks 4 -1
                                           // EXEC
members, _ := oset.Members()               // ZRANGE ranks 0 -1
// [e d a b]
oset.Size()                                // ZCARD ranks
// 4
oset.Includes("d")                         // ZSCORE ranks d
// true
oset.Includes("c")                         // ZSCORE ranks c
// false

For more details on the underlying Redis implementation for the OrderSet type, refer to the original Ruby PR for this feature.

Unique List

Similar to OrderedSet, this type exepcts a limit as well

uniq, err := kredis.NewFloatUniqueList("uniq", 5)
n, err := uniq.Append(3.14, 2.718) // MULTI, LREM uniq 0 3.14, LREM uniq 0 2.718, RPUSH uniq 3.14 2.718, LTRIM uniq -5 -1, EXEC
// 2, nil
n, err = uniq.Prepend(1.1)         // MULTI, LLREM uniq 0 1.1, LPUSH uniq 1.1, LTRIM uniq -5 -1, EXEC
// 1, nil
llen, _ := uniq.Length()           // LLEN uniq
// 3, nil

elements := make([]float64, 3)
n, err := uniq.Elements(elements) // LRANGE uniq 0 3
// 3, nil

uniq.Clear()                      // DEL uniq

TODO

  • More test coverage:
    • Better coverage all possible generic types for collections
    • Test Redis commands with some sort of test env ProcessHook. This is useful when checking expiration is set correctly without using time.Sleep in tests.
Future Features
  • Other scalar types
    • Some sort of map type (serialized as json)
  • Hash type
    • Add a way to call HINCRBY (limited to Hash[int])
  • OrderedSet type
    • Let the user control the ranking
    • Add a Rank function to call ZRANK
  • Explore support for pipelining
    • With only kredis commands?
    • With a shared redis client?

Documentation

Index

Constants

This section is empty.

Variables

View Source
var EnumEmptyValues = errors.New("values cannot be empty")
View Source
var EnumExpiryNotSupported = errors.New("cannot use WithExpiry with Enum")
View Source
var EnumInvalidValue = errors.New("invalid enum value")

Functions

func DisableDebugLogging

func DisableDebugLogging()

Turn off debug logging.

func EnableDebugLogging

func EnableDebugLogging()

Enable logging of Redis commands and errors that are ignored by functions with failsafes. This is useful for development and tests. Logging is disabled by default.

func SetConfiguration

func SetConfiguration(name, namespace, url string, opts ...RedisOption) error

func SetDebugLogger

func SetDebugLogger(userLogger logging)

Types

type Counter

type Counter struct {
	Proxy
}

func NewCounter

func NewCounter(key string, opts ...ProxyOption) (*Counter, error)

func NewCounterWithDefault

func NewCounterWithDefault(key string, defaultValue int64, opts ...ProxyOption) (c *Counter, err error)

func (*Counter) Decrement

func (c *Counter) Decrement(by int64) (int64, error)

func (*Counter) Increment

func (c *Counter) Increment(by int64) (int64, error)

func (*Counter) Reset

func (c *Counter) Reset() (err error)

func (*Counter) Value

func (c *Counter) Value() (v int64)

An empty value returned when there is a Redis error as a failsafe

func (*Counter) ValueResult

func (c *Counter) ValueResult() (int64, error)

type Cycle

type Cycle struct {
	Proxy
	// contains filtered or unexported fields
}

func NewCycle

func NewCycle(key string, values []string, opts ...ProxyOption) (*Cycle, error)

func (*Cycle) Index

func (c *Cycle) Index() (idx int64)

func (*Cycle) IndexResult

func (c *Cycle) IndexResult() (int64, error)

func (*Cycle) Next

func (c *Cycle) Next() (err error)

func (*Cycle) Value

func (c *Cycle) Value() string

type Enum

type Enum struct {
	Proxy
	// contains filtered or unexported fields
}

func NewEnum

func NewEnum(key string, defaultValue string, values []string, opts ...ProxyOption) (*Enum, error)

func (*Enum) Is

func (e *Enum) Is(value string) bool

func (*Enum) Reset

func (e *Enum) Reset() (err error)

func (*Enum) SetValue

func (e *Enum) SetValue(value string) error

func (*Enum) Value

func (e *Enum) Value() string

type Flag

type Flag struct {
	Proxy
}

func NewFlag

func NewFlag(key string, opts ...ProxyOption) (*Flag, error)

func NewMarkedFlag

func NewMarkedFlag(key string, opts ...ProxyOption) (*Flag, error)

func (*Flag) IsMarked

func (f *Flag) IsMarked() bool

func (*Flag) Mark

func (f *Flag) Mark(opts ...FlagMarkOption) error

func (*Flag) Remove

func (f *Flag) Remove() (err error)

func (*Flag) SoftMark

func (f *Flag) SoftMark(opts ...FlagMarkOption) error

type FlagMarkOption

type FlagMarkOption func(*FlagMarkOptions)

func WithFlagExpiry

func WithFlagExpiry(expires string) FlagMarkOption

type FlagMarkOptions

type FlagMarkOptions struct {
	// contains filtered or unexported fields
}

type Hash

type Hash[T KredisTyped] struct {
	Proxy
	// contains filtered or unexported fields
}

func NewBoolHash

func NewBoolHash(key string, opts ...ProxyOption) (*Hash[bool], error)

func NewBoolHashWithDefault

func NewBoolHashWithDefault(key string, defaultElements map[string]bool, opts ...ProxyOption) (h *Hash[bool], err error)

func NewFloatHash

func NewFloatHash(key string, opts ...ProxyOption) (*Hash[float64], error)

func NewFloatHashWithDefault

func NewFloatHashWithDefault(key string, defaultElements map[string]float64, opts ...ProxyOption) (h *Hash[float64], err error)

func NewIntegerHash

func NewIntegerHash(key string, opts ...ProxyOption) (*Hash[int], error)

func NewIntegerHashWithDefault

func NewIntegerHashWithDefault(key string, defaultElements map[string]int, opts ...ProxyOption) (h *Hash[int], err error)

func NewJSONHash

func NewJSONHash(key string, opts ...ProxyOption) (*Hash[KredisJSON], error)

func NewJSONHashWithDefault

func NewJSONHashWithDefault(key string, defaultElements map[string]KredisJSON, opts ...ProxyOption) (h *Hash[KredisJSON], err error)

func NewStringHash

func NewStringHash(key string, opts ...ProxyOption) (*Hash[string], error)

func NewStringHashWithDefault

func NewStringHashWithDefault(key string, defaultElements map[string]string, opts ...ProxyOption) (h *Hash[string], err error)

func NewTimeHash

func NewTimeHash(key string, opts ...ProxyOption) (*Hash[time.Time], error)

func NewTimeHashWithDefault

func NewTimeHashWithDefault(key string, defaultElements map[string]time.Time, opts ...ProxyOption) (h *Hash[time.Time], err error)

func (*Hash[T]) Clear

func (h *Hash[T]) Clear() error

func (Hash[T]) Delete

func (h Hash[T]) Delete(fields ...string) (int64, error)

func (*Hash[T]) Entries

func (h *Hash[T]) Entries() (entries map[string]T, err error)

func (*Hash[T]) Get

func (h *Hash[T]) Get(field string) (T, bool)

func (*Hash[T]) Keys

func (h *Hash[T]) Keys() (keys []string, err error)

func (*Hash[T]) Set

func (h *Hash[T]) Set(field string, entry T) (err error)

func (*Hash[T]) Update

func (h *Hash[T]) Update(entries map[string]T) (int64, error)

func (*Hash[T]) Values

func (h *Hash[T]) Values() (values []T, err error)

func (*Hash[T]) ValuesAt

func (h *Hash[T]) ValuesAt(fields ...string) (values []T, err error)

type KredisJSON

type KredisJSON struct {
	// contains filtered or unexported fields
}

func NewKredisJSON

func NewKredisJSON(jsonStr string) *KredisJSON

KredisJSON is a small struct wrapper for dealing with JSON strings

func (KredisJSON) String

func (kj KredisJSON) String() string

func (*KredisJSON) Unmarshal

func (kj *KredisJSON) Unmarshal(data any) error

type KredisTyped

type KredisTyped interface {
	comparable
	~bool | ~int | ~float64 | ~string | KredisJSON | time.Time
}

type Limiter

type Limiter struct {
	Proxy
	// contains filtered or unexported fields
}

From the Kredis code docs:

A limiter is a specialized form of a counter that can be checked whether it has been exceeded and is provided fail safe. This means it can be used to guard login screens from brute force attacks without denying access in case Redis is offline.

func NewLimiter

func NewLimiter(key string, limit uint64, opts ...ProxyOption) (*Limiter, error)

func NewLimiterWithDefault

func NewLimiterWithDefault(key string, limit uint64, defaultValue int64, opts ...ProxyOption) (l *Limiter, err error)

Similarly to the Poke func, the error be ignored, depending on the use case

func (*Limiter) IsExceeded

func (l *Limiter) IsExceeded() bool

It's possible for this func to return false even if we're above the limit due to a potential race condition.

func (*Limiter) Poke

func (l *Limiter) Poke() error

Depending on the use case, the error can and should be ignored.

You can "poke" yourself above the limit and should use the func IsExceeded() to know if the limit is reached.

func (*Limiter) Reset

func (l *Limiter) Reset() (err error)

type List

type List[T KredisTyped] struct {
	Proxy
	// contains filtered or unexported fields
}

func NewBoolList

func NewBoolList(key string, opts ...ProxyOption) (*List[bool], error)

func NewBoolListWithDefault

func NewBoolListWithDefault(key string, defaultElements []bool, opts ...ProxyOption) (l *List[bool], err error)

func NewFloatList

func NewFloatList(key string, opts ...ProxyOption) (*List[float64], error)

func NewFloatListWithDefault

func NewFloatListWithDefault(key string, defaultElements []float64, opts ...ProxyOption) (l *List[float64], err error)

func NewIntegerList

func NewIntegerList(key string, opts ...ProxyOption) (*List[int], error)

func NewIntegerListWithDefault

func NewIntegerListWithDefault(key string, defaultElements []int, opts ...ProxyOption) (l *List[int], err error)

func NewJSONList

func NewJSONList(key string, opts ...ProxyOption) (*List[KredisJSON], error)

func NewJSONListWithDefault

func NewJSONListWithDefault(key string, defaultElements []KredisJSON, opts ...ProxyOption) (l *List[KredisJSON], err error)

func NewStringList

func NewStringList(key string, opts ...ProxyOption) (*List[string], error)

func NewStringListWithDefault

func NewStringListWithDefault(key string, defaultElements []string, opts ...ProxyOption) (l *List[string], err error)

func NewTimeList

func NewTimeList(key string, opts ...ProxyOption) (*List[time.Time], error)

func NewTimeListWithDefault

func NewTimeListWithDefault(key string, defaultElements []time.Time, opts ...ProxyOption) (l *List[time.Time], err error)

func (*List[T]) Append

func (l *List[T]) Append(elements ...T) (int64, error)

func (*List[T]) Clear

func (l *List[T]) Clear() error

func (*List[T]) Elements

func (l *List[T]) Elements(elements []T, opts ...RangeOption) (total int64, err error)

NOTE we're using Do() for the "LRANGE" command instead of LRange() as to seemingly avoid an []string allocation from StringSliceCmd#Result()

func (List[T]) Last

func (l List[T]) Last() (T, bool)

func (List[T]) LastN

func (l List[T]) LastN(elements []T) (total int64, err error)

func (*List[T]) Length

func (l *List[T]) Length() (llen int64, err error)

func (List[T]) Prepend

func (l List[T]) Prepend(elements ...T) (int64, error)

func (*List[T]) Remove

func (l *List[T]) Remove(elements ...T) (err error)

type OrderedSet

type OrderedSet[T KredisTyped] struct {
	Proxy
	// contains filtered or unexported fields
}

Backed by Sorted Sets in redis

func NewBoolOrderedSet

func NewBoolOrderedSet(key string, limit uint64, opts ...ProxyOption) (*OrderedSet[bool], error)

func NewBoolOrderedSetWithDefault

func NewBoolOrderedSetWithDefault(key string, limit uint64, defaultMembers []bool, opts ...ProxyOption) (s *OrderedSet[bool], err error)

func NewFloatOrderedSet

func NewFloatOrderedSet(key string, limit uint64, opts ...ProxyOption) (*OrderedSet[float64], error)

func NewFloatOrderedSetWithDefault

func NewFloatOrderedSetWithDefault(key string, limit uint64, defaultMembers []float64, opts ...ProxyOption) (s *OrderedSet[float64], err error)

func NewIntegerOrderedSet

func NewIntegerOrderedSet(key string, limit uint64, opts ...ProxyOption) (*OrderedSet[int], error)

func NewIntegerOrderedSetWithDefault

func NewIntegerOrderedSetWithDefault(key string, limit uint64, defaultMembers []int, opts ...ProxyOption) (s *OrderedSet[int], err error)

func NewJSONOrderedSet

func NewJSONOrderedSet(key string, limit uint64, opts ...ProxyOption) (*OrderedSet[KredisJSON], error)

func NewJSONOrderedSetWithDefault

func NewJSONOrderedSetWithDefault(key string, limit uint64, defaultMembers []KredisJSON, opts ...ProxyOption) (s *OrderedSet[KredisJSON], err error)

func NewStringOrderedSet

func NewStringOrderedSet(key string, limit uint64, opts ...ProxyOption) (*OrderedSet[string], error)

func NewStringOrderedSetWithDefault

func NewStringOrderedSetWithDefault(key string, limit uint64, defaultMembers []string, opts ...ProxyOption) (s *OrderedSet[string], err error)

func NewTimeOrderedSet

func NewTimeOrderedSet(key string, limit uint64, opts ...ProxyOption) (*OrderedSet[time.Time], error)

func NewTimeOrderedSetWithDefault

func NewTimeOrderedSetWithDefault(key string, limit uint64, defaultMembers []time.Time, opts ...ProxyOption) (s *OrderedSet[time.Time], err error)

func (*OrderedSet[T]) Append

func (s *OrderedSet[T]) Append(members ...T) (added int64, removed int64, err error)

func (*OrderedSet[T]) Clear

func (s *OrderedSet[T]) Clear() error

func (*OrderedSet[T]) Includes

func (s *OrderedSet[T]) Includes(member T) bool

func (*OrderedSet[T]) Members

func (s *OrderedSet[T]) Members() ([]T, error)

func (*OrderedSet[T]) Prepend

func (s *OrderedSet[T]) Prepend(members ...T) (added int64, removed int64, err error)

func (*OrderedSet[T]) Remove

func (s *OrderedSet[T]) Remove(members ...T) (removed int64, err error)

func (*OrderedSet[T]) SetLimit

func (s *OrderedSet[T]) SetLimit(limit uint64)

func (*OrderedSet[T]) Size

func (s *OrderedSet[T]) Size() int64

type Proxy

type Proxy struct {
	// contains filtered or unexported fields
}

func NewProxy

func NewProxy(key string, opts ...ProxyOption) (*Proxy, error)

func (*Proxy) Client

func (p *Proxy) Client() *redis.Client

func (*Proxy) Key

func (p *Proxy) Key() string

func (*Proxy) RefreshTTL

func (p *Proxy) RefreshTTL() (bool, error)

Set the key's EXPIRE using the configured expiresIn. If there is no value configured, nothing happens.

func (*Proxy) TTL

func (p *Proxy) TTL() (time.Duration, error)

Get the key's current TTL. Redis is only called if the type was configured WithExpiry(). If no expiry is configured, a zero value Duration is returned

type ProxyOption

type ProxyOption func(*ProxyOptions)

func WithConfigName

func WithConfigName(name string) ProxyOption

func WithContext

func WithContext(ctx context.Context) ProxyOption

func WithExpiry

func WithExpiry(expires string) ProxyOption

type ProxyOptions

type ProxyOptions struct {
	// contains filtered or unexported fields
}

func (*ProxyOptions) Config

func (o *ProxyOptions) Config() string

func (*ProxyOptions) ExpiresIn

func (o *ProxyOptions) ExpiresIn() time.Duration

type RangeOption

type RangeOption func(*RangeOptions)

func WithRangeStart

func WithRangeStart(s int64) RangeOption

type RangeOptions

type RangeOptions struct {
	// contains filtered or unexported fields
}

type RedisOption

type RedisOption func(*redis.Options)

type ScalarBool

type ScalarBool struct{ Proxy }

func NewBool

func NewBool(key string, opts ...ProxyOption) (*ScalarBool, error)

func NewBoolWithDefault

func NewBoolWithDefault(key string, defaultValue bool, opts ...ProxyOption) (s *ScalarBool, err error)

func (*ScalarBool) SetValue

func (s *ScalarBool) SetValue(v bool) error

func (*ScalarBool) Value

func (s *ScalarBool) Value() bool

func (*ScalarBool) ValueResult

func (s *ScalarBool) ValueResult() (*bool, error)

type ScalarFloat

type ScalarFloat struct{ Proxy }

func NewFloat

func NewFloat(key string, opts ...ProxyOption) (*ScalarFloat, error)

func NewFloatWithDefault

func NewFloatWithDefault(key string, defaultValue float64, opts ...ProxyOption) (s *ScalarFloat, err error)

func (*ScalarFloat) SetValue

func (s *ScalarFloat) SetValue(v float64) error

func (*ScalarFloat) Value

func (s *ScalarFloat) Value() float64

func (*ScalarFloat) ValueResult

func (s *ScalarFloat) ValueResult() (*float64, error)

type ScalarInteger

type ScalarInteger struct{ Proxy }

func NewInteger

func NewInteger(key string, opts ...ProxyOption) (*ScalarInteger, error)

func NewIntegerWithDefault

func NewIntegerWithDefault(key string, defaultValue int, opts ...ProxyOption) (s *ScalarInteger, err error)

func (*ScalarInteger) SetValue

func (s *ScalarInteger) SetValue(v int) error

func (*ScalarInteger) Value

func (s *ScalarInteger) Value() int

func (*ScalarInteger) ValueResult

func (s *ScalarInteger) ValueResult() (*int, error)

type ScalarJSON

type ScalarJSON struct{ Proxy }

func NewJSON

func NewJSON(key string, opts ...ProxyOption) (*ScalarJSON, error)

func NewJSONWithDefault

func NewJSONWithDefault(key string, defaultValue *KredisJSON, opts ...ProxyOption) (s *ScalarJSON, err error)

func (*ScalarJSON) SetValue

func (s *ScalarJSON) SetValue(v *KredisJSON) error

func (*ScalarJSON) Value

func (s *ScalarJSON) Value() KredisJSON

func (*ScalarJSON) ValueResult

func (s *ScalarJSON) ValueResult() (*KredisJSON, error)

type ScalarString

type ScalarString struct{ Proxy }

func NewString

func NewString(key string, opts ...ProxyOption) (*ScalarString, error)

func NewStringWithDefault

func NewStringWithDefault(key string, defaultValue string, opts ...ProxyOption) (s *ScalarString, err error)

func (*ScalarString) SetValue

func (s *ScalarString) SetValue(v string) error

func (*ScalarString) Value

func (s *ScalarString) Value() string

func (*ScalarString) ValueResult

func (s *ScalarString) ValueResult() (*string, error)

type ScalarTime

type ScalarTime struct{ Proxy }

func NewTime

func NewTime(key string, opts ...ProxyOption) (*ScalarTime, error)

func NewTimeWithDefault

func NewTimeWithDefault(key string, defaultValue time.Time, opts ...ProxyOption) (s *ScalarTime, err error)

func (*ScalarTime) SetValue

func (s *ScalarTime) SetValue(v time.Time) error

func (*ScalarTime) Value

func (s *ScalarTime) Value() time.Time

func (*ScalarTime) ValueResult

func (s *ScalarTime) ValueResult() (*time.Time, error)

type Set

type Set[T KredisTyped] struct {
	Proxy
	// contains filtered or unexported fields
}

func NewBoolSet

func NewBoolSet(key string, opts ...ProxyOption) (*Set[bool], error)

func NewBoolSetWithDefault

func NewBoolSetWithDefault(key string, defaultMembers []bool, opts ...ProxyOption) (s *Set[bool], err error)

func NewFloatSet

func NewFloatSet(key string, opts ...ProxyOption) (*Set[float64], error)

func NewFloatSetWithDefault

func NewFloatSetWithDefault(key string, defaultMembers []float64, opts ...ProxyOption) (s *Set[float64], err error)

func NewIntegerSet

func NewIntegerSet(key string, opts ...ProxyOption) (*Set[int], error)

func NewIntegerSetWithDefault

func NewIntegerSetWithDefault(key string, defaultMembers []int, opts ...ProxyOption) (s *Set[int], err error)

func NewJSONSet

func NewJSONSet(key string, opts ...ProxyOption) (*Set[KredisJSON], error)

func NewJSONSetWithDefault

func NewJSONSetWithDefault(key string, defaultMembers []KredisJSON, opts ...ProxyOption) (s *Set[KredisJSON], err error)

func NewStringSet

func NewStringSet(key string, opts ...ProxyOption) (*Set[string], error)

func NewStringSetWithDefault

func NewStringSetWithDefault(key string, defaultMembers []string, opts ...ProxyOption) (s *Set[string], err error)

func NewTimeSet

func NewTimeSet(key string, opts ...ProxyOption) (*Set[time.Time], error)

func NewTimeSetWithDefault

func NewTimeSetWithDefault(key string, defaultMembers []time.Time, opts ...ProxyOption) (s *Set[time.Time], err error)

func (*Set[T]) Add

func (s *Set[T]) Add(members ...T) (added int64, err error)

func (*Set[T]) Clear

func (s *Set[T]) Clear() error

func (*Set[T]) Includes

func (s *Set[T]) Includes(member T) bool

func (*Set[T]) Members

func (s *Set[T]) Members() ([]T, error)

func (*Set[T]) MembersMap

func (s *Set[T]) MembersMap() (map[T]struct{}, error)

func (*Set[T]) Remove

func (s *Set[T]) Remove(members ...T) (removed int64, err error)

func (*Set[T]) Replace

func (s *Set[T]) Replace(members ...T) (int64, error)

func (*Set[T]) Sample

func (s *Set[T]) Sample(members []T) (total int64, err error)

func (*Set[T]) Size

func (s *Set[T]) Size() int64

func (*Set[T]) Take

func (s *Set[T]) Take() (T, bool)

func (*Set[T]) TakeN

func (s *Set[T]) TakeN(members []T) (total int64, err error)

type Slot

type Slot struct {
	Proxy
	// contains filtered or unexported fields
}

func NewSlot

func NewSlot(key string, available int64, opts ...ProxyOption) (*Slot, error)

func (*Slot) IsAvailable

func (s *Slot) IsAvailable() bool

func (*Slot) Release

func (s *Slot) Release() bool

func (*Slot) Reserve

func (s *Slot) Reserve(callbacks ...SlotCallback) (reserved bool)

func (*Slot) Reset

func (s *Slot) Reset() error

func (*Slot) Taken

func (s *Slot) Taken() int64

func (*Slot) TakenResult

func (s *Slot) TakenResult() (t int64, err error)

type SlotCallback

type SlotCallback func()

type UniqueList

type UniqueList[T KredisTyped] struct {
	Proxy
	// contains filtered or unexported fields
}

func NewBoolUniqueList

func NewBoolUniqueList(key string, limit uint64, opts ...ProxyOption) (*UniqueList[bool], error)

func NewBoolUniqueListWithDefault

func NewBoolUniqueListWithDefault(key string, limit uint64, defaultElements []bool, opts ...ProxyOption) (l *UniqueList[bool], err error)

func NewFloatUniqueList

func NewFloatUniqueList(key string, limit uint64, opts ...ProxyOption) (*UniqueList[float64], error)

func NewFloatUniqueListWithDefault

func NewFloatUniqueListWithDefault(key string, limit uint64, defaultElements []float64, opts ...ProxyOption) (l *UniqueList[float64], err error)

func NewIntegerUniqueList

func NewIntegerUniqueList(key string, limit uint64, opts ...ProxyOption) (*UniqueList[int], error)

func NewIntegerUniqueListWithDefault

func NewIntegerUniqueListWithDefault(key string, limit uint64, defaultElements []int, opts ...ProxyOption) (l *UniqueList[int], err error)

func NewJSONUniqueList

func NewJSONUniqueList(key string, limit uint64, opts ...ProxyOption) (*UniqueList[KredisJSON], error)

func NewJSONUniqueListWithDefault

func NewJSONUniqueListWithDefault(key string, limit uint64, defaultElements []KredisJSON, opts ...ProxyOption) (l *UniqueList[KredisJSON], err error)

func NewStringUniqueList

func NewStringUniqueList(key string, limit uint64, opts ...ProxyOption) (*UniqueList[string], error)

func NewStringUniqueListWithDefault

func NewStringUniqueListWithDefault(key string, limit uint64, defaultElements []string, opts ...ProxyOption) (l *UniqueList[string], err error)

func NewTimeUniqueList

func NewTimeUniqueList(key string, limit uint64, opts ...ProxyOption) (*UniqueList[time.Time], error)

func NewTimeUniqueListWithDefault

func NewTimeUniqueListWithDefault(key string, limit uint64, defaultElements []time.Time, opts ...ProxyOption) (l *UniqueList[time.Time], err error)

func (*UniqueList[T]) Append

func (l *UniqueList[T]) Append(elements ...T) (int64, error)

func (*UniqueList[T]) Clear

func (l *UniqueList[T]) Clear() error

func (*UniqueList[T]) Elements

func (l *UniqueList[T]) Elements(elements []T, opts ...RangeOption) (total int64, err error)

NOTE we're using Do() for the "LRANGE" command instead of LRange() as to seemingly avoid an []string allocation from StringSliceCmd#Result()

func (UniqueList[T]) Last

func (l UniqueList[T]) Last() (T, bool)

func (UniqueList[T]) LastN

func (l UniqueList[T]) LastN(elements []T) (total int64, err error)

func (*UniqueList[T]) Length

func (l *UniqueList[T]) Length() (llen int64, err error)

func (UniqueList[T]) Prepend

func (l UniqueList[T]) Prepend(elements ...T) (int64, error)

func (*UniqueList[T]) Remove

func (l *UniqueList[T]) Remove(elements ...T) (err error)

func (*UniqueList[T]) SetLimit

func (l *UniqueList[T]) SetLimit(limit uint64)

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL