diff --git a/README.md b/README.md index 33023aa..7a2e3e9 100644 --- a/README.md +++ b/README.md @@ -12,55 +12,180 @@ 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 either language to work +and the Ruby version, thus enabling services in either language to work together over Redis. -## Types +## Usage + +To 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. + +```go +kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2") +``` -- [Lists](#lists) -- [Slots](#slots) +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. -### Lists +To enable debug logging, simply call: ```go -l := NewIntegerList("users") +kredis.SetCommandLogging(true) +``` -n, err := l.Append(1, 2, 3) // RPUSH users 1 2 3 +## Types + +- [Counter](#counter) +- [Cycle](#cycle) +- [Enum](#enum) +- [Flag](#flag) +- [Limiter](#limiter) +- [Slot](#slot) +- [Scalar Types](#scalar-types) + +Collection types: + +- [List](#list) +- [Set](#set) +- [Hash](#hash) +- [Ordered Set](#ordered-set) +- [Unique List](#unique-list) + +All 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 + +```go +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 = l.Prepend(9, 8) // LPUSH users 9, 8 -// 2, nil +n, err := cntr.Decrement(3) // MULTI, DECRBY counter 3, EXEC +// 0, nil +cntr.Value() // GET counter +// 0 +``` -ids = make([]int, 5) -n, err := l.Elements(ids) // LRANGE users 0, 5 -// 5, nil +### Cycle -// read some elements with an offset -last_2 = make([]int, 2) -n, err = l.Elements(last_2, WithRangeStart(3)) // LRANGE users 3 5 -// 2, nil +```go +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" ``` -Different typed factories exist for these types: +### Enum -- `NewBoolList` -- `NewStringList` -- `NewTimeList` over `time.Time` -- `NewJSONList` over the `kredisJSON` alias type +```go +vals := []string{"ready", "set", "go"} -It's possible to provide a default value as well: +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 ```go -strs := NewStringWithDefault("lines", []string{"hello", "redis"}) -err := strs.Remove("hello") // LREM lines 0 "hello" +flag, err := kredis.NewFlag("flag") +flag.IsMarked() // EXISTS flag +// false +err = flag.Mark() // SETNX flag 1 // nil -n := strs.Length() // LLEN lines -// 2 +flag.IsMarked() // EXISTS flag +// true +err = flag.Remove() // DEL flag + +flag.Mark(kredis.WithFlagMarkExpiry("1s")) // SET flag 1 ex 1 nx +flag.IsMarked() // EXISTS flag +// true + +time.Sleep(2 * time.Second) + +flag.IsMarked() // EXISTS flag +// false +``` + +You can use the `WithFlagMarkForced` option function to always set the +flag (and thus not use `SET` with `nx`) + +```go +flag.Mark(kredis.WithFlagMarkExpiry("1s")) // SET flag 1 ex 1 nx +flag.Mark(kredis.WithFlagMarkExpiry("10s"), kredis.WithFlagMarkForced()) + // SET flag 1 ex 10 +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 with a failsafe on Reids errors. See the original +[Rails PR for more details](https://github.com/rails/kredis/pull/136). + +`IsExceeded()` will return `false` in the event of a Redis error. +`Poke()` does return an error, but it can easily be ignored in Go. + +```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 ```go -slot := NewSlot("slot", 3) +slot, err := kredis.NewSlot("slot", 3) slot.Reserve() // GET slot + INCR slot // true slot.IsAvailable() // GET slot @@ -98,27 +223,193 @@ slot.Reserve(func () { fmt.Println("called") }) - `NewJSON` and `NewJSONWithDefault` ```go -k, err := NewInteger("myint", Options{}) +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: + +```go +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 + +```go +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. + +```go +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 + +```go +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. + +```go +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 + +```go +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 + +```go +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](https://github.com/rails/kredis/pull/76) for this feature. + +### Unique List + +Similar to `OrderedSet`, this type exepcts a `limit` as well + +```go +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 -Implement additional Kredis data structures - -- other scalar types - - float type - - on lists and other collections - - some sort of map type (serialized as json) ?? -- document all types in README -- make API more succinct - - always use `expiresIn` when possible (lists, sets, and other collections). or refactor `ProxyOption` to not allow it for certain collection types? -- github test matrix with multiple versions of Go and Redis -- test commands with some sort of test env `ProcessHook` for redis - clients -- [pipelining](https://redis.uptrace.dev/guide/go-redis-pipelines.html) ?? - - with only kredis commands? - - with a shared redis client? +- Finish remaining code `TODOs` +- 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) +- Explore support for [pipelining](https://redis.uptrace.dev/guide/go-redis-pipelines.html) + - With only kredis commands? + - With a shared redis client? diff --git a/enum.go b/enum.go index 40c46ea..5e489bf 100644 --- a/enum.go +++ b/enum.go @@ -11,12 +11,12 @@ type Enum struct { values map[string]bool } -var EmptyValues = errors.New("values cannot be empty") -var InvalidValue = errors.New("invalid enum value") +var EnumEmptyValues = errors.New("values cannot be empty") +var EnumInvalidValue = errors.New("invalid enum value") func NewEnum(key string, defaultValue string, values []string, opts ...ProxyOption) (*Enum, error) { if len(values) == 0 { - return nil, EmptyValues + return nil, EnumEmptyValues } proxy, err := NewProxy(key, opts...) @@ -51,7 +51,7 @@ func (e *Enum) Value() string { func (e *Enum) SetValue(value string) error { if _, ok := e.values[value]; !ok { - return InvalidValue + return EnumInvalidValue } _, err := e.client.Set(e.ctx, e.key, value, time.Duration(0)).Result() diff --git a/enum_test.go b/enum_test.go index a984675..832a5be 100644 --- a/enum_test.go +++ b/enum_test.go @@ -17,7 +17,7 @@ func (s *KredisTestSuite) TestEnum() { err = enum.SetValue("badval") s.Error(err) - s.Equal(InvalidValue, err) + s.Equal(EnumInvalidValue, err) s.NoError(enum.Reset()) s.Equal("ready", enum.Value()) @@ -27,5 +27,5 @@ func (s *KredisTestSuite) TestEnum() { func (s *KredisTestSuite) TestEnumWithEmptyValues() { _, err := NewEnum("key", "ready", []string{}) s.Error(err) - s.Equal(EmptyValues, err) + s.Equal(EnumEmptyValues, err) } diff --git a/examples/counter/counter.go b/examples/counter/counter.go new file mode 100644 index 0000000..b08afca --- /dev/null +++ b/examples/counter/counter.go @@ -0,0 +1,16 @@ +package main + +import ( + "github.com/mjc-gh/kredis-go" +) + +func main() { + kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2") + kredis.SetCommandLogging(true) + + cntr, _ := kredis.NewCounter("counter") + cntr.Increment(1) + cntr.Increment(2) + cntr.Decrement(3) + cntr.Value() +} diff --git a/examples/counter/go.mod b/examples/counter/go.mod new file mode 100644 index 0000000..d783ea5 --- /dev/null +++ b/examples/counter/go.mod @@ -0,0 +1,17 @@ +module kredis-go-test + +go 1.21.4 + +replace github.com/mjc-gh/kredis-go => ../.. + +require github.com/mjc-gh/kredis-go v0.0.0-20240105225907-a793cbe772cf + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/redis/go-redis/v9 v9.0.2 // indirect + golang.org/x/sys v0.14.0 // indirect +) diff --git a/examples/counter/go.sum b/examples/counter/go.sum new file mode 100644 index 0000000..8f912ea --- /dev/null +++ b/examples/counter/go.sum @@ -0,0 +1,17 @@ +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE= +github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/examples/cycle/cycle.go b/examples/cycle/cycle.go new file mode 100644 index 0000000..7962910 --- /dev/null +++ b/examples/cycle/cycle.go @@ -0,0 +1,20 @@ +package main + +import ( + "fmt" + + "github.com/mjc-gh/kredis-go" +) + +func main() { + kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2") + kredis.SetCommandLogging(true) + + cycle, _ := kredis.NewCycle("cycle", []string{"ready", "set", "go"}) + cycle.Index() + cycle.Next() + cycle.Next() + + fmt.Println(cycle.Index()) + fmt.Println(cycle.Value()) +} diff --git a/examples/cycle/go.mod b/examples/cycle/go.mod new file mode 100644 index 0000000..d783ea5 --- /dev/null +++ b/examples/cycle/go.mod @@ -0,0 +1,17 @@ +module kredis-go-test + +go 1.21.4 + +replace github.com/mjc-gh/kredis-go => ../.. + +require github.com/mjc-gh/kredis-go v0.0.0-20240105225907-a793cbe772cf + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/redis/go-redis/v9 v9.0.2 // indirect + golang.org/x/sys v0.14.0 // indirect +) diff --git a/examples/cycle/go.sum b/examples/cycle/go.sum new file mode 100644 index 0000000..8f912ea --- /dev/null +++ b/examples/cycle/go.sum @@ -0,0 +1,17 @@ +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE= +github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/examples/enum/enum.go b/examples/enum/enum.go new file mode 100644 index 0000000..869c6eb --- /dev/null +++ b/examples/enum/enum.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + + "github.com/mjc-gh/kredis-go" +) + +func main() { + kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2") + kredis.SetCommandLogging(true) + + enum, _ := kredis.NewEnum("enum", "go", []string{"ready", "set", "go"}) + enum.Is("go") + enum.Value() + + err := enum.SetValue("set") + err = enum.SetValue("error") + + fmt.Println(err) +} diff --git a/examples/enum/go.mod b/examples/enum/go.mod new file mode 100644 index 0000000..d783ea5 --- /dev/null +++ b/examples/enum/go.mod @@ -0,0 +1,17 @@ +module kredis-go-test + +go 1.21.4 + +replace github.com/mjc-gh/kredis-go => ../.. + +require github.com/mjc-gh/kredis-go v0.0.0-20240105225907-a793cbe772cf + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/redis/go-redis/v9 v9.0.2 // indirect + golang.org/x/sys v0.14.0 // indirect +) diff --git a/examples/enum/go.sum b/examples/enum/go.sum new file mode 100644 index 0000000..8f912ea --- /dev/null +++ b/examples/enum/go.sum @@ -0,0 +1,17 @@ +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE= +github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/examples/flag/flag.go b/examples/flag/flag.go new file mode 100644 index 0000000..4eb9fd7 --- /dev/null +++ b/examples/flag/flag.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "time" + + "github.com/mjc-gh/kredis-go" +) + +func main() { + kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2") + kredis.SetCommandLogging(true) + + flag, _ := kredis.NewFlag("flag") + fmt.Println(flag.IsMarked()) + flag.Mark() + fmt.Println(flag.IsMarked()) + flag.Remove() + + flag.Mark(kredis.WithFlagMarkExpiry("1s")) + fmt.Println(flag.IsMarked()) + + time.Sleep(2 * time.Second) + + fmt.Println(flag.IsMarked()) + + flag.Mark(kredis.WithFlagMarkExpiry("1s")) + flag.Mark(kredis.WithFlagMarkExpiry("10s"), kredis.WithFlagMarkForced()) + fmt.Println(flag.IsMarked()) + + time.Sleep(2 * time.Second) + + fmt.Println(flag.IsMarked()) +} diff --git a/examples/flag/go.mod b/examples/flag/go.mod new file mode 100644 index 0000000..d783ea5 --- /dev/null +++ b/examples/flag/go.mod @@ -0,0 +1,17 @@ +module kredis-go-test + +go 1.21.4 + +replace github.com/mjc-gh/kredis-go => ../.. + +require github.com/mjc-gh/kredis-go v0.0.0-20240105225907-a793cbe772cf + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/redis/go-redis/v9 v9.0.2 // indirect + golang.org/x/sys v0.14.0 // indirect +) diff --git a/examples/flag/go.sum b/examples/flag/go.sum new file mode 100644 index 0000000..8f912ea --- /dev/null +++ b/examples/flag/go.sum @@ -0,0 +1,17 @@ +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE= +github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/examples/hash/go.mod b/examples/hash/go.mod new file mode 100644 index 0000000..d783ea5 --- /dev/null +++ b/examples/hash/go.mod @@ -0,0 +1,17 @@ +module kredis-go-test + +go 1.21.4 + +replace github.com/mjc-gh/kredis-go => ../.. + +require github.com/mjc-gh/kredis-go v0.0.0-20240105225907-a793cbe772cf + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/redis/go-redis/v9 v9.0.2 // indirect + golang.org/x/sys v0.14.0 // indirect +) diff --git a/examples/hash/go.sum b/examples/hash/go.sum new file mode 100644 index 0000000..8f912ea --- /dev/null +++ b/examples/hash/go.sum @@ -0,0 +1,17 @@ +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE= +github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/examples/hash/hash.go b/examples/hash/hash.go new file mode 100644 index 0000000..9b471f8 --- /dev/null +++ b/examples/hash/hash.go @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" + + "github.com/mjc-gh/kredis-go" +) + +func main() { + kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2") + kredis.SetCommandLogging(true) + + dogs := map[string]kredis.KredisJSON{ + "ollie": *kredis.NewKredisJSON(`{"weight":9.72}`), + "leo": *kredis.NewKredisJSON(`{"weight":23.33}`), + } + + hash, _ := kredis.NewJSONHash("pets") + hash.Update(dogs) + + val, ok := hash.Get("ollie") + fmt.Printf("%v %v\n", ok, val) + + keys, _ := hash.Keys() + vals, _ := hash.Values() + entries, _ := hash.Entries() + + fmt.Printf("%v %v %v\n", keys, vals, entries) + + hash.Clear() +} diff --git a/examples/limiter/go.mod b/examples/limiter/go.mod new file mode 100644 index 0000000..d783ea5 --- /dev/null +++ b/examples/limiter/go.mod @@ -0,0 +1,17 @@ +module kredis-go-test + +go 1.21.4 + +replace github.com/mjc-gh/kredis-go => ../.. + +require github.com/mjc-gh/kredis-go v0.0.0-20240105225907-a793cbe772cf + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/redis/go-redis/v9 v9.0.2 // indirect + golang.org/x/sys v0.14.0 // indirect +) diff --git a/examples/limiter/go.sum b/examples/limiter/go.sum new file mode 100644 index 0000000..8f912ea --- /dev/null +++ b/examples/limiter/go.sum @@ -0,0 +1,17 @@ +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE= +github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/examples/limiter/limiter.go b/examples/limiter/limiter.go new file mode 100644 index 0000000..7e03035 --- /dev/null +++ b/examples/limiter/limiter.go @@ -0,0 +1,19 @@ +package main + +import ( + "github.com/mjc-gh/kredis-go" +) + +func main() { + kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2") + kredis.SetCommandLogging(true) + + limiter, _ := kredis.NewLimiter("limiter", 5) + + for i := 0; i < 4; i++ { + limiter.Poke() + } + + limiter.IsExceeded() + limiter.Reset() +} diff --git a/examples/list/go.mod b/examples/list/go.mod new file mode 100644 index 0000000..d783ea5 --- /dev/null +++ b/examples/list/go.mod @@ -0,0 +1,17 @@ +module kredis-go-test + +go 1.21.4 + +replace github.com/mjc-gh/kredis-go => ../.. + +require github.com/mjc-gh/kredis-go v0.0.0-20240105225907-a793cbe772cf + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/redis/go-redis/v9 v9.0.2 // indirect + golang.org/x/sys v0.14.0 // indirect +) diff --git a/examples/list/go.sum b/examples/list/go.sum new file mode 100644 index 0000000..8f912ea --- /dev/null +++ b/examples/list/go.sum @@ -0,0 +1,17 @@ +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE= +github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/examples/list/list.go b/examples/list/list.go new file mode 100644 index 0000000..b0c220a --- /dev/null +++ b/examples/list/list.go @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" + + "github.com/mjc-gh/kredis-go" +) + +func main() { + kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2") + kredis.SetCommandLogging(true) + + l, _ := kredis.NewIntegerList("key") + l.Append(1, 2, 3) + l.Prepend(8, 9) + llen, _ := l.Length() + + fmt.Printf("list LLEN = %d\n", llen) + + elements := make([]int, 3) + n, _ := l.Elements(elements) + + fmt.Printf("n = %d (%v)\n", n, elements) + + lastTwo := make([]int, 2) + n, _ = l.Elements(lastTwo, kredis.WithRangeStart(3)) + + fmt.Printf("n = %d (%v)\n", n, lastTwo) + + l.Clear() +} diff --git a/examples/ordered_set/go.mod b/examples/ordered_set/go.mod new file mode 100644 index 0000000..d783ea5 --- /dev/null +++ b/examples/ordered_set/go.mod @@ -0,0 +1,17 @@ +module kredis-go-test + +go 1.21.4 + +replace github.com/mjc-gh/kredis-go => ../.. + +require github.com/mjc-gh/kredis-go v0.0.0-20240105225907-a793cbe772cf + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/redis/go-redis/v9 v9.0.2 // indirect + golang.org/x/sys v0.14.0 // indirect +) diff --git a/examples/ordered_set/go.sum b/examples/ordered_set/go.sum new file mode 100644 index 0000000..8f912ea --- /dev/null +++ b/examples/ordered_set/go.sum @@ -0,0 +1,17 @@ +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE= +github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/examples/ordered_set/ordered_set.go b/examples/ordered_set/ordered_set.go new file mode 100644 index 0000000..8695c5c --- /dev/null +++ b/examples/ordered_set/ordered_set.go @@ -0,0 +1,22 @@ +package main + +import ( + "fmt" + + "github.com/mjc-gh/kredis-go" +) + +func main() { + kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2") + kredis.SetCommandLogging(true) + + oset, _ := kredis.NewStringOrderedSet("ranks", 4) + oset.Append("a", "b", "c") + oset.Prepend("d", "e") + members, _ := oset.Members() + + fmt.Printf("%d %v\n", oset.Size(), members) + + fmt.Println(oset.Includes("d")) + fmt.Println(oset.Includes("c")) +} diff --git a/examples/scalars/scalars.go b/examples/scalars/scalars.go new file mode 100644 index 0000000..72930b9 --- /dev/null +++ b/examples/scalars/scalars.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + "time" + + "github.com/mjc-gh/kredis-go" +) + +func main() { + kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2") + kredis.SetCommandLogging(true) + + k, _ := kredis.NewTime("sessionStart", kredis.WithExpiry("1ms")) + _ = k.SetValue(time.Now()) // SET sessionStart + + time.Sleep(1 * time.Second) + + fmt.Println(k.Value()) + fmt.Println(k.TTL()) +} diff --git a/examples/set/go.mod b/examples/set/go.mod new file mode 100644 index 0000000..d783ea5 --- /dev/null +++ b/examples/set/go.mod @@ -0,0 +1,17 @@ +module kredis-go-test + +go 1.21.4 + +replace github.com/mjc-gh/kredis-go => ../.. + +require github.com/mjc-gh/kredis-go v0.0.0-20240105225907-a793cbe772cf + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/redis/go-redis/v9 v9.0.2 // indirect + golang.org/x/sys v0.14.0 // indirect +) diff --git a/examples/set/go.sum b/examples/set/go.sum new file mode 100644 index 0000000..8f912ea --- /dev/null +++ b/examples/set/go.sum @@ -0,0 +1,17 @@ +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE= +github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/examples/set/set.go b/examples/set/set.go new file mode 100644 index 0000000..477e71b --- /dev/null +++ b/examples/set/set.go @@ -0,0 +1,29 @@ +package main + +import ( + "fmt" + "time" + + "github.com/mjc-gh/kredis-go" +) + +func main() { + kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2") + kredis.SetCommandLogging(true) + + 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, _ := kredis.NewTimeSet("times") + set.Add(times...) + members, _ := set.Members() + + fmt.Println(set.Includes(t)) + fmt.Println(set.Includes(t.Add(4 * time.Hour))) + fmt.Printf("%d %v\n", set.Size(), members) + + sample := make([]time.Time, 2) + n, _ := set.Sample(sample) + + fmt.Printf("n = %d %v\n", n, sample) +} diff --git a/examples/slot/go.mod b/examples/slot/go.mod new file mode 100644 index 0000000..d783ea5 --- /dev/null +++ b/examples/slot/go.mod @@ -0,0 +1,17 @@ +module kredis-go-test + +go 1.21.4 + +replace github.com/mjc-gh/kredis-go => ../.. + +require github.com/mjc-gh/kredis-go v0.0.0-20240105225907-a793cbe772cf + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/redis/go-redis/v9 v9.0.2 // indirect + golang.org/x/sys v0.14.0 // indirect +) diff --git a/examples/slot/go.sum b/examples/slot/go.sum new file mode 100644 index 0000000..8f912ea --- /dev/null +++ b/examples/slot/go.sum @@ -0,0 +1,17 @@ +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE= +github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/examples/slot/slot.go b/examples/slot/slot.go new file mode 100644 index 0000000..5c95a12 --- /dev/null +++ b/examples/slot/slot.go @@ -0,0 +1,19 @@ +package main + +import "github.com/mjc-gh/kredis-go" + +func main() { + kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2") + kredis.SetCommandLogging(true) + + slot, _ := kredis.NewSlot("slot", 3) + slot.Reserve() + slot.IsAvailable() + slot.Taken() + slot.Reserve() + slot.Reserve() + + slot.Reserve() + slot.IsAvailable() + slot.Taken() +} diff --git a/examples/unique_list/go.mod b/examples/unique_list/go.mod new file mode 100644 index 0000000..d783ea5 --- /dev/null +++ b/examples/unique_list/go.mod @@ -0,0 +1,17 @@ +module kredis-go-test + +go 1.21.4 + +replace github.com/mjc-gh/kredis-go => ../.. + +require github.com/mjc-gh/kredis-go v0.0.0-20240105225907-a793cbe772cf + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/redis/go-redis/v9 v9.0.2 // indirect + golang.org/x/sys v0.14.0 // indirect +) diff --git a/examples/unique_list/go.sum b/examples/unique_list/go.sum new file mode 100644 index 0000000..8f912ea --- /dev/null +++ b/examples/unique_list/go.sum @@ -0,0 +1,17 @@ +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE= +github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/examples/unique_list/unique_list.go b/examples/unique_list/unique_list.go new file mode 100644 index 0000000..db70fa8 --- /dev/null +++ b/examples/unique_list/unique_list.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + + "github.com/mjc-gh/kredis-go" +) + +func main() { + kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2") + kredis.SetCommandLogging(true) + + uniq, _ := kredis.NewFloatUniqueList("uniq", 5) + uniq.Append(3.14, 2.718) + uniq.Prepend(1.1) + llen, _ := uniq.Length() + + fmt.Printf("list LLEN = %d\n", llen) + + elements := make([]float64, 3) + n, _ := uniq.Elements(elements) + + fmt.Printf("n = %d (%v)\n", n, elements) + + uniq.Clear() +} diff --git a/flag.go b/flag.go index 2b1426f..db1f3e3 100644 --- a/flag.go +++ b/flag.go @@ -28,6 +28,9 @@ func NewFlag(key string, opts ...ProxyOption) (*Flag, error) { return &Flag{Proxy: *proxy}, nil } +// TODO this should return true/false if flag was set or not +// true == flag.mark(expires_in: 1.second, force: false) #=> SET myflag 1 EX 1 NX +// false == flag.mark(expires_in: 10.seconds, force: false) #=> SET myflag 10 EX 1 NX func (f *Flag) Mark(opts ...FlagMarkOption) error { options := FlagMarkOptions{force: false} for _, opt := range opts { diff --git a/hash.go b/hash.go index d4cf8e0..1281f2e 100644 --- a/hash.go +++ b/hash.go @@ -1,6 +1,8 @@ package kredis import ( + "time" + "github.com/redis/go-redis/v9" ) @@ -39,6 +41,156 @@ func NewBoolHashWithDefault(key string, defaultElements map[string]bool, opts .. return } +// Hash[float64] type + +func NewFloatHash(key string, opts ...ProxyOption) (*Hash[float64], error) { + proxy, err := NewProxy(key, opts...) + + if err != nil { + return nil, err + } + + return &Hash[float64]{Proxy: *proxy, typed: new(float64)}, nil +} + +func NewFloatHashWithDefault(key string, defaultElements map[string]float64, opts ...ProxyOption) (h *Hash[float64], err error) { + proxy, err := NewProxy(key, opts...) + if err != nil { + return + } + + h = &Hash[float64]{Proxy: *proxy, typed: new(float64)} + err = proxy.watch(func() error { + _, err := h.Update(defaultElements) + return err + }) + if err != nil { + return nil, err + } + + return +} + +// Hash[int] type + +func NewIntegerHash(key string, opts ...ProxyOption) (*Hash[int], error) { + proxy, err := NewProxy(key, opts...) + + if err != nil { + return nil, err + } + + return &Hash[int]{Proxy: *proxy, typed: new(int)}, nil +} + +func NewIntegerHashWithDefault(key string, defaultElements map[string]int, opts ...ProxyOption) (h *Hash[int], err error) { + proxy, err := NewProxy(key, opts...) + if err != nil { + return + } + + h = &Hash[int]{Proxy: *proxy, typed: new(int)} + err = proxy.watch(func() error { + _, err := h.Update(defaultElements) + return err + }) + if err != nil { + return nil, err + } + + return +} + +// Hash[string] type + +func NewStringHash(key string, opts ...ProxyOption) (*Hash[string], error) { + proxy, err := NewProxy(key, opts...) + + if err != nil { + return nil, err + } + + return &Hash[string]{Proxy: *proxy, typed: new(string)}, nil +} + +func NewStringHashWithDefault(key string, defaultElements map[string]string, opts ...ProxyOption) (h *Hash[string], err error) { + proxy, err := NewProxy(key, opts...) + if err != nil { + return + } + + h = &Hash[string]{Proxy: *proxy, typed: new(string)} + err = proxy.watch(func() error { + _, err := h.Update(defaultElements) + return err + }) + if err != nil { + return nil, err + } + + return +} + +// Hash[time.Time] type + +func NewTimeHash(key string, opts ...ProxyOption) (*Hash[time.Time], error) { + proxy, err := NewProxy(key, opts...) + + if err != nil { + return nil, err + } + + return &Hash[time.Time]{Proxy: *proxy, typed: new(time.Time)}, nil +} + +func NewTimeHashWithDefault(key string, defaultElements map[string]time.Time, opts ...ProxyOption) (h *Hash[time.Time], err error) { + proxy, err := NewProxy(key, opts...) + if err != nil { + return + } + + h = &Hash[time.Time]{Proxy: *proxy, typed: new(time.Time)} + err = proxy.watch(func() error { + _, err := h.Update(defaultElements) + return err + }) + if err != nil { + return nil, err + } + + return +} + +// Hash[KredisJSON] type + +func NewJSONHash(key string, opts ...ProxyOption) (*Hash[KredisJSON], error) { + proxy, err := NewProxy(key, opts...) + + if err != nil { + return nil, err + } + + return &Hash[KredisJSON]{Proxy: *proxy, typed: new(KredisJSON)}, nil +} + +func NewJSONHashWithDefault(key string, defaultElements map[string]KredisJSON, opts ...ProxyOption) (h *Hash[KredisJSON], err error) { + proxy, err := NewProxy(key, opts...) + if err != nil { + return + } + + h = &Hash[KredisJSON]{Proxy: *proxy, typed: new(KredisJSON)} + err = proxy.watch(func() error { + _, err := h.Update(defaultElements) + return err + }) + if err != nil { + return nil, err + } + + return +} + // generic Hash functions func (h *Hash[T]) Get(field string) (T, bool) { diff --git a/iter_test.go b/iter_test.go index 50369e6..d8b961e 100644 --- a/iter_test.go +++ b/iter_test.go @@ -7,7 +7,7 @@ import ( ) func TestIterValues(t *testing.T) { - i := newIter([]kredisJSON{ + i := newIter([]KredisJSON{ *NewKredisJSON(`{"a":"b"}`), *NewKredisJSON(`{"c":"d"}`), *NewKredisJSON(`{"a":"b"}`), @@ -17,7 +17,7 @@ func TestIterValues(t *testing.T) { } func TestIterUnique(t *testing.T) { - i := newIter([]kredisJSON{ + i := newIter([]KredisJSON{ *NewKredisJSON(`{"a":"b"}`), *NewKredisJSON(`{"c":"d"}`), *NewKredisJSON(`{"a":"b"}`), diff --git a/kredis.go b/kredis.go index 9648ee5..6af62f1 100644 --- a/kredis.go +++ b/kredis.go @@ -9,28 +9,28 @@ import ( ) // TODO does this need to be exported?? -// type kredisJSON []byte -type kredisJSON struct { +// type KredisJSON []byte +type KredisJSON struct { s string } type KredisTyped interface { comparable - ~bool | ~int | ~float64 | ~string | kredisJSON | time.Time + ~bool | ~int | ~float64 | ~string | KredisJSON | time.Time } -// kredisJSON is a small struct wrapper for dealing with JSON strings -func NewKredisJSON(jsonStr string) *kredisJSON { - var kj kredisJSON = kredisJSON{jsonStr} +// KredisJSON is a small struct wrapper for dealing with JSON strings +func NewKredisJSON(jsonStr string) *KredisJSON { + var kj KredisJSON = KredisJSON{jsonStr} return &kj } -func (kj kredisJSON) String() string { +func (kj KredisJSON) String() string { return kj.s } -func (kj *kredisJSON) Unmarshal(data *interface{}) error { +func (kj *KredisJSON) Unmarshal(data *interface{}) error { err := json.Unmarshal([]byte(kj.s), data) if err != nil { return err @@ -44,8 +44,8 @@ func typeToInterface[T KredisTyped](t T) interface{} { switch any(t).(type) { case time.Time: return any(t).(time.Time).Format(time.RFC3339Nano) - case kredisJSON: - return any(t).(kredisJSON).String() + case KredisJSON: + return any(t).(KredisJSON).String() default: return t } @@ -78,8 +78,8 @@ func stringToTyped[T KredisTyped](value string, typed *T) (T, bool) { case string: return any(value).(T), true - case kredisJSON: - return any(NewKredisJSON(value)).(T), true + case KredisJSON: + return any(*NewKredisJSON(value)).(T), true } return any(*typed).(T), false @@ -124,8 +124,8 @@ func stringCmdToTyped[T KredisTyped](cmd *redis.StringCmd, typed *T) (T, bool) { case string: return any(cmd.Val()).(T), true - case kredisJSON: - return any(NewKredisJSON(cmd.Val())).(T), true + case KredisJSON: + return any(*NewKredisJSON(cmd.Val())).(T), true } Empty: @@ -153,7 +153,7 @@ func copyCmdSliceTo[T KredisTyped](slice []interface{}, dst []T) (total int64) { f, _ := strconv.ParseFloat(e.(string), 64) dst[i] = any(f).(T) - case kredisJSON: + case KredisJSON: j := NewKredisJSON(e.(string)) dst[i] = any(*j).(T) diff --git a/kredis_test.go b/kredis_test.go index 0c78cfe..4d01f19 100644 --- a/kredis_test.go +++ b/kredis_test.go @@ -41,4 +41,4 @@ func TestKredisTestSuit(t *testing.T) { suite.Run(t, new(KredisTestSuite)) } -// TODO tests for kredisJSON struct ?? +// TODO tests for KredisJSON struct ?? diff --git a/list.go b/list.go index 6ae43c4..ed4bd68 100644 --- a/list.go +++ b/list.go @@ -160,25 +160,25 @@ func NewTimeListWithDefault(key string, defaultElements []time.Time, opts ...Pro return } -// List[kredisJSON] type +// List[KredisJSON] type -func NewJSONList(key string, opts ...ProxyOption) (*List[kredisJSON], error) { +func NewJSONList(key string, opts ...ProxyOption) (*List[KredisJSON], error) { proxy, err := NewProxy(key, opts...) if err != nil { return nil, err } - return &List[kredisJSON]{Proxy: *proxy}, nil + return &List[KredisJSON]{Proxy: *proxy}, nil } -func NewJSONListWithDefault(key string, defaultElements []kredisJSON, opts ...ProxyOption) (l *List[kredisJSON], err error) { +func NewJSONListWithDefault(key string, defaultElements []KredisJSON, opts ...ProxyOption) (l *List[KredisJSON], err error) { proxy, err := NewProxy(key, opts...) if err != nil { return } - l = &List[kredisJSON]{Proxy: *proxy} + l = &List[KredisJSON]{Proxy: *proxy} err = proxy.watch(func() error { _, err := l.Append(defaultElements...) return err diff --git a/list_test.go b/list_test.go index 4f8469f..4c3cf30 100644 --- a/list_test.go +++ b/list_test.go @@ -229,7 +229,7 @@ func (s *KredisTestSuite) TestTimeListWithDefault() { } func (s *KredisTestSuite) TestJSONList() { - elems := make([]kredisJSON, 3) + elems := make([]KredisJSON, 3) l, e := NewJSONList("json_list") s.NoError(e) @@ -255,7 +255,7 @@ func (s *KredisTestSuite) TestJSONList() { s.NoError(err) s.Equal(int64(3), n) - s.Equal([]kredisJSON{*kj_3, *kj_1, *kj_2}, elems) + s.Equal([]KredisJSON{*kj_3, *kj_1, *kj_2}, elems) var data interface{} @@ -269,15 +269,15 @@ func (s *KredisTestSuite) TestJSONListWithDefault() { kj_1 := NewKredisJSON(`{"k1":"v1"}`) kj_2 := NewKredisJSON(`{"k2":"v2"}`) - l, _ := NewJSONListWithDefault("list_default", []kredisJSON{*kj_1, *kj_2}) + l, _ := NewJSONListWithDefault("list_default", []KredisJSON{*kj_1, *kj_2}) - NewJSONListWithDefault("list_default", []kredisJSON{*NewKredisJSON(`{"abc":"xyz"}`)}) + NewJSONListWithDefault("list_default", []KredisJSON{*NewKredisJSON(`{"abc":"xyz"}`)}) - elems := make([]kredisJSON, 3) + elems := make([]KredisJSON, 3) n, e := l.Elements(elems) s.NoError(e) s.Equal(int64(2), n) - s.Equal([]kredisJSON{*kj_1, *kj_2}, elems[0:2]) + s.Equal([]KredisJSON{*kj_1, *kj_2}, elems[0:2]) } func (s *KredisTestSuite) TestElementsWithRangeOptions() { diff --git a/ordered_set.go b/ordered_set.go index 59eb4e6..eb80f4f 100644 --- a/ordered_set.go +++ b/ordered_set.go @@ -163,24 +163,24 @@ func NewTimeOrderedSetWithDefault(key string, limit uint64, defaultMembers []tim return } -// OrderedSet[kredisJSON] type +// OrderedSet[KredisJSON] type -func NewJSONOrderedSet(key string, limit uint64, opts ...ProxyOption) (*OrderedSet[kredisJSON], error) { +func NewJSONOrderedSet(key string, limit uint64, opts ...ProxyOption) (*OrderedSet[KredisJSON], error) { proxy, err := NewProxy(key, opts...) if err != nil { return nil, err } - return &OrderedSet[kredisJSON]{Proxy: *proxy, limit: limit, typed: new(kredisJSON)}, nil + return &OrderedSet[KredisJSON]{Proxy: *proxy, limit: limit, typed: new(KredisJSON)}, nil } -func NewJSONOrderedSetWithDefault(key string, limit uint64, defaultMembers []kredisJSON, opts ...ProxyOption) (s *OrderedSet[kredisJSON], err error) { +func NewJSONOrderedSetWithDefault(key string, limit uint64, defaultMembers []KredisJSON, opts ...ProxyOption) (s *OrderedSet[KredisJSON], err error) { proxy, err := NewProxy(key, opts...) if err != nil { return nil, err } - s = &OrderedSet[kredisJSON]{Proxy: *proxy, limit: limit, typed: new(kredisJSON)} + s = &OrderedSet[KredisJSON]{Proxy: *proxy, limit: limit, typed: new(KredisJSON)} err = proxy.watch(func() error { _, _, err := s.Append(defaultMembers...) return err diff --git a/scalar.go b/scalar.go index a32b21f..d6b9635 100644 --- a/scalar.go +++ b/scalar.go @@ -284,7 +284,7 @@ func NewJSON(key string, opts ...ProxyOption) (*ScalarJSON, error) { return &ScalarJSON{Proxy: *proxy}, nil } -func NewJSONWithDefault(key string, defaultValue *kredisJSON, opts ...ProxyOption) (s *ScalarJSON, err error) { +func NewJSONWithDefault(key string, defaultValue *KredisJSON, opts ...ProxyOption) (s *ScalarJSON, err error) { proxy, err := NewProxy(key, opts...) if err != nil { return @@ -302,16 +302,16 @@ func NewJSONWithDefault(key string, defaultValue *kredisJSON, opts ...ProxyOptio } // TODO should this be returning a pointer instead struct value itself?? -func (s *ScalarJSON) Value() kredisJSON { +func (s *ScalarJSON) Value() KredisJSON { val, err := s.ValueResult() if err != nil || val == nil { - return kredisJSON{} + return KredisJSON{} } return *val } -func (s *ScalarJSON) ValueResult() (*kredisJSON, error) { +func (s *ScalarJSON) ValueResult() (*KredisJSON, error) { val, err := s.client.Get(s.ctx, s.key).Result() if err != nil { return nil, err @@ -320,6 +320,6 @@ func (s *ScalarJSON) ValueResult() (*kredisJSON, error) { return NewKredisJSON(val), nil } -func (s *ScalarJSON) SetValue(v *kredisJSON) error { +func (s *ScalarJSON) SetValue(v *KredisJSON) error { return s.client.Set(s.ctx, s.key, string(v.s), s.expiresIn).Err() } diff --git a/set.go b/set.go index 9bb3021..231fdc6 100644 --- a/set.go +++ b/set.go @@ -152,24 +152,24 @@ func NewTimeSetWithDefault(key string, defaultMembers []time.Time, opts ...Proxy return } -// Set[kredisJSON] type +// Set[KredisJSON] type -func NewJSONSet(key string, opts ...ProxyOption) (*Set[kredisJSON], error) { +func NewJSONSet(key string, opts ...ProxyOption) (*Set[KredisJSON], error) { proxy, err := NewProxy(key, opts...) if err != nil { return nil, err } - return &Set[kredisJSON]{Proxy: *proxy, typed: new(kredisJSON)}, nil + return &Set[KredisJSON]{Proxy: *proxy, typed: new(KredisJSON)}, nil } -func NewJSONSetWithDefault(key string, defaultMembers []kredisJSON, opts ...ProxyOption) (s *Set[kredisJSON], err error) { +func NewJSONSetWithDefault(key string, defaultMembers []KredisJSON, opts ...ProxyOption) (s *Set[KredisJSON], err error) { proxy, err := NewProxy(key, opts...) if err != nil { return nil, err } - s = &Set[kredisJSON]{Proxy: *proxy, typed: new(kredisJSON)} + s = &Set[KredisJSON]{Proxy: *proxy, typed: new(KredisJSON)} err = proxy.watch(func() error { _, err := s.Add(defaultMembers...) return err @@ -183,8 +183,6 @@ func NewJSONSetWithDefault(key string, defaultMembers []kredisJSON, opts ...Prox // generic Set functions -// TODO this will force an allocation onto the caller -- can this be avoided? -// are there better Go idioms for read all set members? func (s *Set[T]) Members() ([]T, error) { slice, err := s.client.Do(s.ctx, "smembers", s.key).Slice() if err != nil { diff --git a/unique_list.go b/unique_list.go index 0ab4845..d5a556f 100644 --- a/unique_list.go +++ b/unique_list.go @@ -11,9 +11,6 @@ type UniqueList[T KredisTyped] struct { limit uint64 } -// TODO finish generic Default factories -// TODO use expiresIn - // UniqueList[bool] type func NewBoolUniqueList(key string, limit uint64, opts ...ProxyOption) (*UniqueList[bool], error) { @@ -162,25 +159,25 @@ func NewTimeUniqueListWithDefault(key string, limit uint64, defaultElements []ti return } -// UniqueList[kredisJSON] type +// UniqueList[KredisJSON] type -func NewJSONUniqueList(key string, limit uint64, opts ...ProxyOption) (*UniqueList[kredisJSON], error) { +func NewJSONUniqueList(key string, limit uint64, opts ...ProxyOption) (*UniqueList[KredisJSON], error) { proxy, err := NewProxy(key, opts...) if err != nil { return nil, err } - return &UniqueList[kredisJSON]{Proxy: *proxy, limit: limit}, nil + return &UniqueList[KredisJSON]{Proxy: *proxy, limit: limit}, nil } -func NewJSONUniqueListWithDefault(key string, limit uint64, defaultElements []kredisJSON, opts ...ProxyOption) (l *UniqueList[kredisJSON], err error) { +func NewJSONUniqueListWithDefault(key string, limit uint64, defaultElements []KredisJSON, opts ...ProxyOption) (l *UniqueList[KredisJSON], err error) { proxy, err := NewProxy(key, opts...) if err != nil { return } - l = &UniqueList[kredisJSON]{Proxy: *proxy, limit: limit} + l = &UniqueList[KredisJSON]{Proxy: *proxy, limit: limit} err = proxy.watch(func() error { _, err := l.Append(defaultElements...) return err