Skip to content

Commit

Permalink
Merge pull request #68 from dwelch0/metric-proxy-rw-lock
Browse files Browse the repository at this point in the history
utilize rwlock to address race condition - add tests
  • Loading branch information
dwelch0 authored Sep 28, 2022
2 parents ae92c78 + 320f9ce commit f70c42c
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 1 deletion.
4 changes: 3 additions & 1 deletion pkg/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type MetricProxyItem struct {

type MetricProxy struct {
metrics map[string]*MetricProxyItem
mutex sync.Mutex
mutex sync.RWMutex
}

func NewMetricProxy() *MetricProxy {
Expand All @@ -24,6 +24,8 @@ func NewMetricProxy() *MetricProxy {
}

func (mp *MetricProxy) GetMetricById(id string) (*MetricProxyItem, error) {
mp.mutex.RLock()
defer mp.mutex.RUnlock()
if m, ok := mp.metrics[id]; ok {
if time.Since(m.creationTime).Seconds() > float64(m.ttl) {
return nil, errors.New("metric ttl has expired")
Expand Down
104 changes: 104 additions & 0 deletions pkg/proxy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package pkg

import (
"math"
"reflect"
"testing"
"time"
)

func TestGetMetricById(t *testing.T) {
type args struct {
mp *MetricProxy
key string
}
now := time.Now()
tests := []struct {
name string
args args
want *MetricProxyItem
}{
{
name: "Attempt retrieving value by providing valid id (key exists)",
args: args{
mp: &MetricProxy{
metrics: map[string]*MetricProxyItem{
"valid": &MetricProxyItem{
value: "value",
ttl: math.MaxInt32,
creationTime: now,
},
},
},
key: "valid",
},
want: &MetricProxyItem{
value: "value",
ttl: math.MaxInt32,
creationTime: now,
},
},
{
name: "Attempt retrieving value by providing valid id but ttl expired",
args: args{
mp: &MetricProxy{
metrics: map[string]*MetricProxyItem{
"expired": &MetricProxyItem{
value: 100,
ttl: 1,
creationTime: now,
},
},
},
key: "expired",
},
want: nil,
},
}

time.Sleep(2 * time.Second) //ensure ttl for second test expires

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got, _ := tt.args.mp.GetMetricById(tt.args.key); !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetMetricById() = %v, want %v", got, tt.want)
}
})
}
}

func TestStoreMetricById(t *testing.T) {
type args struct {
mp *MetricProxy
key string
value interface{}
ttl int
}
tests := []struct {
name string
args args
want *MetricProxyItem
}{
{
name: "Attempt storing new metric by id",
args: args{
mp: NewMetricProxy(),
key: "new",
value: 1,
ttl: math.MaxInt32,
},
want: &MetricProxyItem{
value: 1,
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.args.mp.StoreMetricById(tt.args.key, tt.args.value, tt.args.ttl)
if got, err := tt.args.mp.GetMetricById(tt.args.key); got.value != tt.want.value || err != nil {
t.Errorf("StoreMetricById() = %v, want %v", got.value, tt.want.value)
}
})
}
}

0 comments on commit f70c42c

Please sign in to comment.