Skip to content

Commit

Permalink
more updates
Browse files Browse the repository at this point in the history
  • Loading branch information
mjc-gh committed Dec 27, 2023
1 parent 3eba1d5 commit 7773a92
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 24 deletions.
38 changes: 17 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,7 @@ A port of [Rails' Kredis](https://github.com/rails/kredis) for Go.
structures around a single key, so you can interact with them as
coherent objects rather than isolated procedural commands.

## Example

```go
k, e := NewInteger("foo", Options{})
k.SetValue(1234)

// prints: 1234
fmt.Println(k.Value())
```

### Lists
## Lists

```go
l := NewIntegerList("users")
Expand Down Expand Up @@ -53,7 +43,7 @@ n := strs.Length() // LLEN lines
// 2
```

### Slots
## Slots

```go
slot := NewSlot("slot", 3)
Expand Down Expand Up @@ -85,31 +75,37 @@ slot.Reserve(func () { fmt.Println("called") })
// true
```

### Scalar types
## Scalar types

- `NewBool` and `NewBoolWithDefault`
- `NewInteger` and `NewIntegerWithDefault`
- `NewString` and `NewStringWithDefault`
- `NewTime` and `NewTimeWithDefault`
- `NewJSON` and `NewJSONWithDefault`

```go
k, err := NewInteger("myint", Options{})
err = k.SetValue(1024) // SET myint 1024
// nil
k.Value() // GET myint
// 1024
```

## TODO

Implement additional Kredis data structures

- enum
- counters
- flags
- Collections
- sets
- unique lists
- hashs
- scalar types
- float type (lists and other collections)
- other scalar types
- float type
- on lists and other collections
- some sort of map type (serialized as json) ??
- debug logging
- use zerolog
- like Ruby, log redis commands in "development" mode
- document all types in README
- 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?
5 changes: 2 additions & 3 deletions elements.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ func newIter[T KredisTyped](elements []T) iterator[T] {
return &iter[T]{elements}
}

func (i *iter[T]) next() (T, bool) {
func (i *iter[T]) next() (val T, ok bool) {
if len(i.elements) == 0 {
var zero T
return zero, false
return // no elements - return empty values
}

elem := i.elements[0]
Expand Down
68 changes: 68 additions & 0 deletions enum.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package kredis

import (
"errors"
"time"
)

type Enum struct {
Proxy
defaultValue string
values map[string]bool
}

var EmptyValues = errors.New("values cannot be empty")
var InvalidValue = errors.New("invalid enum value")

func NewEnum(key string, defaultValue string, values []string, opts ...ProxyOption) (*Enum, error) {
if len(values) == 0 {
return nil, EmptyValues
}

proxy, err := NewProxy(key, opts...)
if err != nil {
return nil, err
}

// TODO return runtime error if expiresIn option is used -- this option just
// doesn't fit well into this Kredis data structure

enum := &Enum{Proxy: *proxy, defaultValue: defaultValue, values: map[string]bool{}}
for _, value := range values {
enum.values[value] = true
}

err = enum.SetValue(defaultValue)
if err != nil {
return nil, err
}

return enum, nil
}

func (e *Enum) Is(value string) bool {
return e.Value() == value
}

func (e *Enum) Value() string {
value, _ := e.client.Get(e.ctx, e.key).Result()
return value
}

func (e *Enum) SetValue(value string) error {
if _, ok := e.values[value]; !ok {
return InvalidValue
}

_, err := e.client.Set(e.ctx, e.key, value, time.Duration(0)).Result()
return err
}

func (e *Enum) Reset() (err error) {
pipe := e.client.TxPipeline()
pipe.Del(e.ctx, e.key)
pipe.Set(e.ctx, e.key, e.defaultValue, time.Duration(0))

_, err = pipe.Exec(e.ctx)
return
}
31 changes: 31 additions & 0 deletions enum_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package kredis

func (s *KredisTestSuite) TestEnum() {
enum, err := NewEnum("e", "ready", []string{"ready", "set", "go"})
s.NoError(err)

s.Equal("ready", enum.Value())
s.True(enum.Is("ready"))

s.NoError(enum.SetValue("set"))
s.Equal("set", enum.Value())
s.True(enum.Is("set"))

s.NoError(enum.SetValue("go"))
s.Equal("go", enum.Value())
s.True(enum.Is("go"))

err = enum.SetValue("badval")
s.Error(err)
s.Equal(InvalidValue, err)

s.NoError(enum.Reset())
s.Equal("ready", enum.Value())
s.True(enum.Is("ready"))
}

func (s *KredisTestSuite) TestEnumWithEmptyValues() {
_, err := NewEnum("key", "ready", []string{})
s.Error(err)
s.Equal(EmptyValues, err)
}
38 changes: 38 additions & 0 deletions flag_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,43 @@
package kredis

import "time"

func (s *KredisTestSuite) TestFlag() {
flag, err := NewFlag("flag")
s.NoError(err)
s.False(flag.IsMarked())

s.NoError(flag.Mark())
s.True(flag.IsMarked())

s.NoError(flag.Remove())
s.False(flag.IsMarked())
}

func (s *KredisTestSuite) TestFlagWithMarkOptions() {
flag, _ := NewFlag("flag_ex")

s.NoError(flag.Mark(WithFlagMarkExpiry("2ms")))
s.True(flag.IsMarked())

time.Sleep(1 * time.Millisecond)

s.NoError(flag.Mark(WithFlagMarkExpiry("2ms")))
s.True(flag.IsMarked())

time.Sleep(2 * time.Millisecond)

s.False(flag.IsMarked())

s.NoError(flag.Mark(WithFlagMarkExpiry("2ms")))
s.True(flag.IsMarked())

time.Sleep(1 * time.Millisecond)

s.NoError(flag.Mark(WithFlagMarkExpiry("5ms"), WithFlagMarkForced()))
s.True(flag.IsMarked())

time.Sleep(2 * time.Millisecond)

s.True(flag.IsMarked()) // still marked because of forced SET cmd
}
8 changes: 8 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ func WithExpiry(expires string) ProxyOption {
}
}

// TODO WithContext ProxyOption for providing a user-defined context.Context for the Proxy
// struct and thus the redis client commands

// func WithContext(ctx context.Context) ProxyOption {
// return func(o *ProxyOptions) {
// }
// }

// For range options (list, unique lists)

type RangeOptions struct {
Expand Down

0 comments on commit 7773a92

Please sign in to comment.