Skip to content

Commit

Permalink
more refactoring and README updates
Browse files Browse the repository at this point in the history
  • Loading branch information
mjc-gh committed Jan 21, 2024
1 parent 01e8f89 commit 5186327
Show file tree
Hide file tree
Showing 19 changed files with 101 additions and 36 deletions.
35 changes: 32 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,31 @@ in the Ruby Kredis version.
To enable debug logging, simply call:

```go
kredis.SetCommandLogging(true)
kredis.EnableDebugLogging()
```

### Failsafe

Kredis wraps calls in Redis in a
[failsafe](https://github.com/rails/kredis/blob/4fbb2f5613ed049f72cba337317c5eae2a6bba28/lib/kredis/types/proxy/failsafe.rb#L9-L13).
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:

```go
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
Expand All @@ -58,7 +82,8 @@ Collection types:
- [Ordered Set](#ordered-set)
- [Unique List](#unique-list)

All types accept the following option functions:
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`.
Expand Down Expand Up @@ -414,7 +439,11 @@ uniq.Clear() // DEL uniq

- Other scalar types
- Some sort of map type (serialized as json)
- Add a way to call `HINCRBY` for `Hash[int]` type
- `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](https://redis.uptrace.dev/guide/go-redis-pipelines.html)
- With only kredis commands?
- With a shared redis client?
17 changes: 4 additions & 13 deletions connections.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,6 @@ type config struct {

var configs map[string]*config = map[string]*config{}
var connections map[string]*redis.Client = map[string]*redis.Client{}
var connectionLogging bool

func SetCommandLogging(v bool) {
connectionLogging = v
}

// TODO add a way to configure a user provided value that implements the
// cmdLogging interface
// func SetCommandLogger(userLogger cmdLogging)

type RedisOption func(*redis.Options)

Expand Down Expand Up @@ -56,18 +47,18 @@ func getConnection(name string) (*redis.Client, *string, error) {
conn = redis.NewClient(config.options)
connections[name] = conn

if connectionLogging {
conn.AddHook(newCmdLoggingHook(NewStdoutLogger()))
if debugLogger != nil {
conn.AddHook(newCmdLoggingHook(debugLogger))
}

return conn, &config.namespace, nil
}

type cmdLoggingHook struct {
cmdLogger cmdLogging
cmdLogger logging
}

func newCmdLoggingHook(clog cmdLogging) *cmdLoggingHook {
func newCmdLoggingHook(clog logging) *cmdLoggingHook {
return &cmdLoggingHook{clog}
}

Expand Down
1 change: 1 addition & 0 deletions counter.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func (c *Counter) Decrement(by int64) (int64, error) {
return decr.Val(), nil
}

// An empty value returned when there is a Redis error as a failsafe
func (c *Counter) Value() (v int64) {
v, err := c.client.Get(c.ctx, c.key).Int64()
if err != nil && err != redis.Nil {
Expand Down
2 changes: 1 addition & 1 deletion examples/counter/counter.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (

func main() {
kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")
kredis.SetCommandLogging(true)
kredis.EnableDebugLogging()

cntr, _ := kredis.NewCounter("counter")
cntr.Increment(1)
Expand Down
2 changes: 1 addition & 1 deletion examples/cycle/cycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

func main() {
kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")
kredis.SetCommandLogging(true)
kredis.EnableDebugLogging()

cycle, _ := kredis.NewCycle("cycle", []string{"ready", "set", "go"})
cycle.Index()
Expand Down
2 changes: 1 addition & 1 deletion examples/enum/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

func main() {
kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")
kredis.SetCommandLogging(true)
kredis.EnableDebugLogging()

enum, _ := kredis.NewEnum("enum", "go", []string{"ready", "set", "go"})
enum.Is("go")
Expand Down
2 changes: 1 addition & 1 deletion examples/flag/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

func main() {
kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")
kredis.SetCommandLogging(true)
kredis.EnableDebugLogging()

flag, _ := kredis.NewFlag("flag")
fmt.Println(flag.IsMarked())
Expand Down
2 changes: 1 addition & 1 deletion examples/hash/hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

func main() {
kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")
kredis.SetCommandLogging(true)
kredis.EnableDebugLogging()

dogs := map[string]kredis.KredisJSON{
"ollie": *kredis.NewKredisJSON(`{"weight":9.72}`),
Expand Down
2 changes: 1 addition & 1 deletion examples/limiter/limiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (

func main() {
kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")
kredis.SetCommandLogging(true)
kredis.EnableDebugLogging()

limiter, _ := kredis.NewLimiter("limiter", 5)

Expand Down
2 changes: 1 addition & 1 deletion examples/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

func main() {
kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")
kredis.SetCommandLogging(true)
kredis.EnableDebugLogging()

l, _ := kredis.NewIntegerList("key")
l.Append(1, 2, 3)
Expand Down
30 changes: 30 additions & 0 deletions examples/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package main

import (
"fmt"
"time"

"github.com/mjc-gh/kredis-go"
)

func main() {
kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")
kredis.EnableDebugLogging()

slot, err := kredis.NewSlot("slot", 3)
if err != nil {
panic(err)
}

slot.Reserve()
fmt.Println(slot.Taken())

// some time later when Redis is down...
time.Sleep(10 * time.Second)

fmt.Println(slot.Taken())
n, err := slot.TakenResult() // 0,
fmt.Println(n, err)

fmt.Println(err)
}
2 changes: 1 addition & 1 deletion examples/ordered_set/ordered_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

func main() {
kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")
kredis.SetCommandLogging(true)
kredis.EnableDebugLogging()

oset, _ := kredis.NewStringOrderedSet("ranks", 4)
oset.Append("a", "b", "c")
Expand Down
2 changes: 1 addition & 1 deletion examples/scalars/scalars.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

func main() {
kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")
kredis.SetCommandLogging(true)
kredis.EnableDebugLogging()

k, _ := kredis.NewTime("sessionStart", kredis.WithExpiry("1ms"))
_ = k.SetValue(time.Now()) // SET sessionStart
Expand Down
2 changes: 1 addition & 1 deletion examples/set/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

func main() {
kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")
kredis.SetCommandLogging(true)
kredis.EnableDebugLogging()

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)}
Expand Down
2 changes: 1 addition & 1 deletion examples/slot/slot.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "github.com/mjc-gh/kredis-go"

func main() {
kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")
kredis.SetCommandLogging(true)
kredis.EnableDebugLogging()

slot, _ := kredis.NewSlot("slot", 3)
slot.Reserve()
Expand Down
2 changes: 1 addition & 1 deletion examples/unique_list/unique_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

func main() {
kredis.SetConfiguration("shared", "ns", "redis://localhost:6379/2")
kredis.SetCommandLogging(true)
kredis.EnableDebugLogging()

uniq, _ := kredis.NewFloatUniqueList("uniq", 5)
uniq.Append(3.14, 2.718)
Expand Down
2 changes: 1 addition & 1 deletion kredis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func (suite *KredisTestSuite) SetupTest() {
SetConfiguration("shared", "ns", "redis://localhost:6379/2")
SetConfiguration("badconn", "", "redis://localhost:1234/0")

SetCommandLogging(true)
EnableDebugLogging()
}

func (suite *KredisTestSuite) TearDownTest() {
Expand Down
24 changes: 21 additions & 3 deletions logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,30 @@ import (
"github.com/redis/go-redis/v9"
)

type cmdLogging interface {
type logging interface {
Info(redis.Cmder, time.Duration)
Warn(string, error)
}

type stdLogger struct{}

func NewStdoutLogger() stdLogger {
return stdLogger{}
var debugLogger logging

// 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 EnableDebugLogging() {
debugLogger = stdLogger{}
}

// Turn off debug logging.
func DisableDebugLogging() {
debugLogger = nil
}

// TODO add a way to configure a user provided value that implements the logging interface
// func SetCommandLogger(userLogger cmdLogging)

func (log stdLogger) Info(cmd redis.Cmder, dur time.Duration) {
name, key, args := cmdLogParts(cmd)

Expand All @@ -31,6 +45,10 @@ func (log stdLogger) Info(cmd redis.Cmder, dur time.Duration) {
}
}

func (log stdLogger) Warn(msg string, err error) {

}

var cmdColor = color.New(color.FgYellow).SprintFunc()
var keyColor = color.New(color.FgCyan).SprintFunc()
var argsColor = color.New(color.FgGreen).SprintFunc()
Expand Down
4 changes: 0 additions & 4 deletions ordered_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,6 @@ func (s *OrderedSet[T]) SetLimit(limit uint64) {
s.limit = limit
}

// TODO
//func (s OrderedSet[T]) Rank(member T) int64 {
//}

func (s *OrderedSet[T]) appendScore(index int) float64 {
baseScore := s.baseScore()
incrementalScore := float64(index) * 0.000001
Expand Down

0 comments on commit 5186327

Please sign in to comment.