Skip to content

Commit

Permalink
Add RedisStore (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
YoshiyukiMineo authored Dec 30, 2024
1 parent c8765ba commit 3cecc1d
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 79 deletions.
74 changes: 5 additions & 69 deletions v2/distributed_gobreaker_test.go
Original file line number Diff line number Diff line change
@@ -1,65 +1,14 @@
package gobreaker

import (
"context"
"errors"
"testing"
"time"

"github.com/alicebob/miniredis/v2"
"github.com/go-redsync/redsync/v4"
"github.com/go-redsync/redsync/v4/redis/goredis/v9"
"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/assert"
)

type storeAdapter struct {
ctx context.Context
client *redis.Client
rs *redsync.Redsync
mutex map[string]*redsync.Mutex
}

func newStoreAdapter(client *redis.Client) *storeAdapter {
return &storeAdapter{
ctx: context.Background(),
client: client,
rs: redsync.New(goredis.NewPool(client)),
mutex: map[string]*redsync.Mutex{},
}
}

func (sa *storeAdapter) Lock(name string) error {
mutex, ok := sa.mutex[name]
if ok {
return mutex.Lock()
}

mutex = sa.rs.NewMutex(name, redsync.WithExpiry(mutexTimeout))
sa.mutex[name] = mutex
return mutex.Lock()
}

func (sa *storeAdapter) Unlock(name string) error {
mutex, ok := sa.mutex[name]
if ok {
var err error
ok, err = mutex.Unlock()
if ok && err == nil {
return nil
}
}
return errors.New("unlock failed")
}

func (sa *storeAdapter) GetData(name string) ([]byte, error) {
return sa.client.Get(sa.ctx, name).Bytes()
}

func (sa *storeAdapter) SetData(name string, data []byte) error {
return sa.client.Set(sa.ctx, name, data, 0).Err()
}

var redisServer *miniredis.Miniredis

func setUpDCB() *DistributedCircuitBreaker[any] {
Expand All @@ -69,11 +18,7 @@ func setUpDCB() *DistributedCircuitBreaker[any] {
panic(err)
}

client := redis.NewClient(&redis.Options{
Addr: redisServer.Addr(),
})

store := newStoreAdapter(client)
store := NewRedisStore(redisServer.Addr())

dcb, err := NewDistributedCircuitBreaker[any](store, Settings{
Name: "TestBreaker",
Expand All @@ -93,9 +38,8 @@ func setUpDCB() *DistributedCircuitBreaker[any] {

func tearDownDCB(dcb *DistributedCircuitBreaker[any]) {
if dcb != nil {
store := dcb.store.(*storeAdapter)
store.client.Close()
store.client = nil
store := dcb.store.(*RedisStore)
store.Close()
}

if redisServer != nil {
Expand Down Expand Up @@ -234,11 +178,7 @@ func TestCustomDistributedCircuitBreaker(t *testing.T) {
}
defer mr.Close()

client := redis.NewClient(&redis.Options{
Addr: mr.Addr(),
})

store := newStoreAdapter(client)
store := NewRedisStore(mr.Addr())

customDCB, err = NewDistributedCircuitBreaker[any](store, Settings{
Name: "CustomBreaker",
Expand Down Expand Up @@ -327,11 +267,7 @@ func TestCustomDistributedCircuitBreakerStateTransitions(t *testing.T) {
}
defer mr.Close()

client := redis.NewClient(&redis.Options{
Addr: mr.Addr(),
})

store := newStoreAdapter(client)
store := NewRedisStore(mr.Addr())

dcb, err := NewDistributedCircuitBreaker[any](store, customSt)
assert.NoError(t, err)
Expand Down
19 changes: 9 additions & 10 deletions v2/go.mod
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
module github.com/sony/gobreaker/v2

go 1.22
go 1.22.0

toolchain go1.22.10

require github.com/stretchr/testify v1.8.4
require (
github.com/alicebob/miniredis/v2 v2.33.0
github.com/go-redsync/redsync/v4 v4.13.0
github.com/redis/go-redis/v9 v9.7.0
github.com/stretchr/testify v1.8.4
)

require (
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/yuin/gopher-lua v1.1.1 // indirect
)

require (
github.com/alicebob/miniredis/v2 v2.33.0
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-redsync/redsync/v4 v4.13.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/redis/go-redis/v9 v9.7.0
github.com/yuin/gopher-lua v1.1.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
64 changes: 64 additions & 0 deletions v2/redis_store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package gobreaker

import (
"context"
"errors"

"github.com/go-redsync/redsync/v4"
"github.com/go-redsync/redsync/v4/redis/goredis/v9"
"github.com/redis/go-redis/v9"
)

type RedisStore struct {
ctx context.Context
client *redis.Client
rs *redsync.Redsync
mutex map[string]*redsync.Mutex
}

func NewRedisStore(addr string) *RedisStore {
client := redis.NewClient(&redis.Options{
Addr: addr,
})
return &RedisStore{
ctx: context.Background(),
client: client,
rs: redsync.New(goredis.NewPool(client)),
mutex: map[string]*redsync.Mutex{},
}
}

func (rs *RedisStore) Lock(name string) error {
mutex, ok := rs.mutex[name]
if ok {
return mutex.Lock()
}

mutex = rs.rs.NewMutex(name, redsync.WithExpiry(mutexTimeout))
rs.mutex[name] = mutex
return mutex.Lock()
}

func (rs *RedisStore) Unlock(name string) error {
mutex, ok := rs.mutex[name]
if ok {
var err error
ok, err = mutex.Unlock()
if ok && err == nil {
return nil
}
}
return errors.New("unlock failed")
}

func (rs *RedisStore) GetData(name string) ([]byte, error) {
return rs.client.Get(rs.ctx, name).Bytes()
}

func (rs *RedisStore) SetData(name string, data []byte) error {
return rs.client.Set(rs.ctx, name, data, 0).Err()
}

func (rs *RedisStore) Close() {
rs.client.Close()
}

0 comments on commit 3cecc1d

Please sign in to comment.