Skip to content

Commit b2b49e3

Browse files
authored
Update some mailgun deps to remove dependency on mgo (#223)
1 parent 07d2d56 commit b2b49e3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+3218
-548
lines changed

.golangci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
run:
22
deadline: 5m
33
skip-files: [ ]
4-
skip-dirs: [ ]
4+
skip-dirs: ["internal/holsterv4"]
55

66
linters-settings:
77
govet:

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export GO111MODULE=on
55
default: clean checks test
66

77
test: clean
8-
go test -race -cover ./...
8+
go test -race -cover -count 1 ./...
99

1010
test-verbose: clean
1111
go test -v -race -cover ./...

cbreaker/cbreaker.go

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ import (
3131
"sync"
3232
"time"
3333

34-
"github.com/mailgun/timetools"
3534
log "github.com/sirupsen/logrus"
35+
"github.com/vulcand/oxy/internal/holsterv4/clock"
3636
"github.com/vulcand/oxy/memmetrics"
3737
"github.com/vulcand/oxy/utils"
3838
)
@@ -51,18 +51,16 @@ type CircuitBreaker struct {
5151
onStandby SideEffect
5252

5353
state cbState
54-
until time.Time
54+
until clock.Time
5555

5656
rc *ratioController
5757

5858
checkPeriod time.Duration
59-
lastCheck time.Time
59+
lastCheck clock.Time
6060

6161
fallback http.Handler
6262
next http.Handler
6363

64-
clock timetools.TimeProvider
65-
6664
log *log.Logger
6765
}
6866

@@ -72,7 +70,6 @@ func New(next http.Handler, expression string, options ...CircuitBreakerOption)
7270
m: &sync.RWMutex{},
7371
next: next,
7472
// Default values. Might be overwritten by options below.
75-
clock: &timetools.RealTime{},
7673
checkPeriod: defaultCheckPeriod,
7774
fallbackDuration: defaultFallbackDuration,
7875
recoveryDuration: defaultRecoveryDuration,
@@ -151,16 +148,16 @@ func (c *CircuitBreaker) activateFallback(_ http.ResponseWriter, _ *http.Request
151148
// someone else has set it to standby just now
152149
return false
153150
case stateTripped:
154-
if c.clock.UtcNow().Before(c.until) {
151+
if clock.Now().UTC().Before(c.until) {
155152
return true
156153
}
157154
// We have been in active state enough, enter recovering state
158155
c.setRecovering()
159156
fallthrough
160157
case stateRecovering:
161158
// We have been in recovering state enough, enter standby and allow request
162-
if c.clock.UtcNow().After(c.until) {
163-
c.setState(stateStandby, c.clock.UtcNow())
159+
if clock.Now().UTC().After(c.until) {
160+
c.setState(stateStandby, clock.Now().UTC())
164161
return false
165162
}
166163
// ratio controller allows this request
@@ -173,12 +170,12 @@ func (c *CircuitBreaker) activateFallback(_ http.ResponseWriter, _ *http.Request
173170
}
174171

175172
func (c *CircuitBreaker) serve(w http.ResponseWriter, req *http.Request) {
176-
start := c.clock.UtcNow()
173+
start := clock.Now().UTC()
177174
p := utils.NewProxyWriterWithLogger(w, c.log)
178175

179176
c.next.ServeHTTP(p, req)
180177

181-
latency := c.clock.UtcNow().Sub(start)
178+
latency := clock.Now().UTC().Sub(start)
182179
c.metrics.Record(p.StatusCode(), latency)
183180

184181
// Note that this call is less expensive than it looks -- checkCondition only performs the real check
@@ -229,7 +226,7 @@ func (c *CircuitBreaker) setState(state cbState, until time.Time) {
229226
func (c *CircuitBreaker) timeToCheck() bool {
230227
c.m.RLock()
231228
defer c.m.RUnlock()
232-
return c.clock.UtcNow().After(c.lastCheck)
229+
return clock.Now().UTC().After(c.lastCheck)
233230
}
234231

235232
// Checks if tripping condition matches and sets circuit breaker to the tripped state.
@@ -242,10 +239,10 @@ func (c *CircuitBreaker) checkAndSet() {
242239
defer c.m.Unlock()
243240

244241
// Other goroutine could have updated the lastCheck variable before we grabbed mutex
245-
if !c.clock.UtcNow().After(c.lastCheck) {
242+
if !clock.Now().UTC().After(c.lastCheck) {
246243
return
247244
}
248-
c.lastCheck = c.clock.UtcNow().Add(c.checkPeriod)
245+
c.lastCheck = clock.Now().UTC().Add(c.checkPeriod)
249246

250247
if c.state == stateTripped {
251248
c.log.Debugf("%v skip set tripped", c)
@@ -256,28 +253,19 @@ func (c *CircuitBreaker) checkAndSet() {
256253
return
257254
}
258255

259-
c.setState(stateTripped, c.clock.UtcNow().Add(c.fallbackDuration))
256+
c.setState(stateTripped, clock.Now().UTC().Add(c.fallbackDuration))
260257
c.metrics.Reset()
261258
}
262259

263260
func (c *CircuitBreaker) setRecovering() {
264-
c.setState(stateRecovering, c.clock.UtcNow().Add(c.recoveryDuration))
265-
c.rc = newRatioController(c.clock, c.recoveryDuration, c.log)
261+
c.setState(stateRecovering, clock.Now().UTC().Add(c.recoveryDuration))
262+
c.rc = newRatioController(c.recoveryDuration, c.log)
266263
}
267264

268265
// CircuitBreakerOption represents an option you can pass to New.
269266
// See the documentation for the individual options below.
270267
type CircuitBreakerOption func(*CircuitBreaker) error
271268

272-
// Clock allows you to fake che CircuitBreaker's view of the current time.
273-
// Intended for unit tests.
274-
func Clock(clock timetools.TimeProvider) CircuitBreakerOption {
275-
return func(c *CircuitBreaker) error {
276-
c.clock = clock
277-
return nil
278-
}
279-
}
280-
281269
// FallbackDuration is how long the CircuitBreaker will remain in the Tripped
282270
// state before trying to recover.
283271
func FallbackDuration(d time.Duration) CircuitBreakerOption {
@@ -357,9 +345,9 @@ const (
357345
)
358346

359347
const (
360-
defaultFallbackDuration = 10 * time.Second
361-
defaultRecoveryDuration = 10 * time.Second
362-
defaultCheckPeriod = 100 * time.Millisecond
348+
defaultFallbackDuration = 10 * clock.Second
349+
defaultRecoveryDuration = 10 * clock.Second
350+
defaultCheckPeriod = 100 * clock.Millisecond
363351
)
364352

365353
var defaultFallback = &fallback{}

cbreaker/cbreaker_test.go

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/stretchr/testify/assert"
1313
"github.com/stretchr/testify/require"
14+
"github.com/vulcand/oxy/internal/holsterv4/clock"
1415
"github.com/vulcand/oxy/memmetrics"
1516
"github.com/vulcand/oxy/testutils"
1617
)
@@ -39,9 +40,10 @@ func TestFullCycle(t *testing.T) {
3940
_, _ = w.Write([]byte("hello"))
4041
})
4142

42-
clock := testutils.GetClock()
43+
done := testutils.FreezeTime()
44+
defer done()
4345

44-
cb, err := New(handler, triggerNetRatio, Clock(clock))
46+
cb, err := New(handler, triggerNetRatio)
4547
require.NoError(t, err)
4648

4749
srv := httptest.NewServer(cb)
@@ -52,27 +54,27 @@ func TestFullCycle(t *testing.T) {
5254
assert.Equal(t, http.StatusOK, re.StatusCode)
5355

5456
cb.metrics = statsNetErrors(0.6)
55-
clock.CurrentTime = clock.CurrentTime.Add(defaultCheckPeriod + time.Millisecond)
57+
clock.Advance(defaultCheckPeriod + clock.Millisecond)
5658
_, _, err = testutils.Get(srv.URL)
5759
require.NoError(t, err)
5860
assert.Equal(t, cbState(stateTripped), cb.state)
5961

6062
// Some time has passed, but we are still in trapped state.
61-
clock.CurrentTime = clock.CurrentTime.Add(9 * time.Second)
63+
clock.Advance(9 * clock.Second)
6264
re, _, err = testutils.Get(srv.URL)
6365
require.NoError(t, err)
6466
assert.Equal(t, http.StatusServiceUnavailable, re.StatusCode)
6567
assert.Equal(t, cbState(stateTripped), cb.state)
6668

6769
// We should be in recovering state by now
68-
clock.CurrentTime = clock.CurrentTime.Add(time.Second*1 + time.Millisecond)
70+
clock.Advance(clock.Second*1 + clock.Millisecond)
6971
re, _, err = testutils.Get(srv.URL)
7072
require.NoError(t, err)
7173
assert.Equal(t, http.StatusServiceUnavailable, re.StatusCode)
7274
assert.Equal(t, cbState(stateRecovering), cb.state)
7375

7476
// 5 seconds after we should be allowing some requests to pass
75-
clock.CurrentTime = clock.CurrentTime.Add(5 * time.Second)
77+
clock.Advance(5 * clock.Second)
7678
allowed := 0
7779
for i := 0; i < 100; i++ {
7880
re, _, err = testutils.Get(srv.URL)
@@ -83,7 +85,7 @@ func TestFullCycle(t *testing.T) {
8385
assert.NotEqual(t, 0, allowed)
8486

8587
// After some time, all is good and we should be in stand by mode again
86-
clock.CurrentTime = clock.CurrentTime.Add(5*time.Second + time.Millisecond)
88+
clock.Advance(5*clock.Second + clock.Millisecond)
8789
re, _, err = testutils.Get(srv.URL)
8890
assert.Equal(t, cbState(stateStandby), cb.state)
8991
require.NoError(t, err)
@@ -101,7 +103,7 @@ func TestRedirectWithPath(t *testing.T) {
101103
})
102104
require.NoError(t, err)
103105

104-
cb, err := New(handler, triggerNetRatio, Clock(testutils.GetClock()), Fallback(fallbackRedirectPath))
106+
cb, err := New(handler, triggerNetRatio, Fallback(fallbackRedirectPath))
105107
require.NoError(t, err)
106108

107109
srv := httptest.NewServer(cb)
@@ -131,7 +133,7 @@ func TestRedirect(t *testing.T) {
131133
fallbackRedirect, err := NewRedirectFallback(Redirect{URL: "http://localhost:5000"})
132134
require.NoError(t, err)
133135

134-
cb, err := New(handler, triggerNetRatio, Clock(testutils.GetClock()), Fallback(fallbackRedirect))
136+
cb, err := New(handler, triggerNetRatio, Fallback(fallbackRedirect))
135137
require.NoError(t, err)
136138

137139
srv := httptest.NewServer(cb)
@@ -158,9 +160,10 @@ func TestTriggerDuringRecovery(t *testing.T) {
158160
_, _ = w.Write([]byte("hello"))
159161
})
160162

161-
clock := testutils.GetClock()
163+
done := testutils.FreezeTime()
164+
defer done()
162165

163-
cb, err := New(handler, triggerNetRatio, Clock(clock), CheckPeriod(time.Microsecond))
166+
cb, err := New(handler, triggerNetRatio, CheckPeriod(clock.Microsecond))
164167
require.NoError(t, err)
165168

166169
srv := httptest.NewServer(cb)
@@ -172,14 +175,14 @@ func TestTriggerDuringRecovery(t *testing.T) {
172175
assert.Equal(t, cbState(stateTripped), cb.state)
173176

174177
// We should be in recovering state by now
175-
clock.CurrentTime = clock.CurrentTime.Add(10*time.Second + time.Millisecond)
178+
clock.Advance(10*clock.Second + clock.Millisecond)
176179
re, _, err := testutils.Get(srv.URL)
177180
require.NoError(t, err)
178181
assert.Equal(t, http.StatusServiceUnavailable, re.StatusCode)
179182
assert.Equal(t, cbState(stateRecovering), cb.state)
180183

181184
// We have matched error condition during recovery state and are going back to tripped state
182-
clock.CurrentTime = clock.CurrentTime.Add(5 * time.Second)
185+
clock.Advance(5 * clock.Second)
183186
cb.metrics = statsNetErrors(0.6)
184187
allowed := 0
185188
for i := 0; i < 100; i++ {
@@ -234,9 +237,10 @@ func TestSideEffects(t *testing.T) {
234237
_, _ = w.Write([]byte("hello"))
235238
})
236239

237-
clock := testutils.GetClock()
240+
done := testutils.FreezeTime()
241+
defer done()
238242

239-
cb, err := New(handler, triggerNetRatio, Clock(clock), CheckPeriod(time.Microsecond), OnTripped(onTripped), OnStandby(onStandby))
243+
cb, err := New(handler, triggerNetRatio, CheckPeriod(clock.Microsecond), OnTripped(onTripped), OnStandby(onStandby))
240244
require.NoError(t, err)
241245

242246
srv := httptest.NewServer(cb)
@@ -254,19 +258,19 @@ func TestSideEffects(t *testing.T) {
254258
assert.Equal(t, "/post.json", req.URL.Path)
255259
assert.Equal(t, `{"Key": ["val1", "val2"]}`, string(srv1Body))
256260
assert.Equal(t, "application/json", req.Header.Get("Content-Type"))
257-
case <-time.After(time.Second):
261+
case <-clock.After(clock.Second):
258262
t.Error("timeout waiting for side effect to kick off")
259263
}
260264

261265
// Transition to recovering state
262-
clock.CurrentTime = clock.CurrentTime.Add(10*time.Second + time.Millisecond)
266+
clock.Advance(10*clock.Second + clock.Millisecond)
263267
cb.metrics = statsOK()
264268
_, _, err = testutils.Get(srv.URL)
265269
require.NoError(t, err)
266270
assert.Equal(t, cbState(stateRecovering), cb.state)
267271

268272
// Going back to standby
269-
clock.CurrentTime = clock.CurrentTime.Add(10*time.Second + time.Millisecond)
273+
clock.Advance(10*clock.Second + clock.Millisecond)
270274
_, _, err = testutils.Get(srv.URL)
271275
require.NoError(t, err)
272276
assert.Equal(t, cbState(stateStandby), cb.state)
@@ -276,7 +280,7 @@ func TestSideEffects(t *testing.T) {
276280
assert.Equal(t, http.MethodPost, req.Method)
277281
assert.Equal(t, "/post", req.URL.Path)
278282
assert.Equal(t, url.Values{"key": []string{"val1", "val2"}}, req.Form)
279-
case <-time.After(time.Second):
283+
case <-clock.After(clock.Second):
280284
t.Error("timeout waiting for side effect to kick off")
281285
}
282286
}

cbreaker/predicates.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package cbreaker
22

33
import (
44
"fmt"
5-
"time"
65

6+
"github.com/vulcand/oxy/internal/holsterv4/clock"
77
"github.com/vulcand/predicate"
88
)
99

@@ -53,7 +53,7 @@ func latencyAtQuantile(quantile float64) toInt {
5353
c.log.Errorf("Failed to get latency histogram, for %v error: %v", c, err)
5454
return 0
5555
}
56-
return int(h.LatencyAtQuantile(quantile) / time.Millisecond)
56+
return int(h.LatencyAtQuantile(quantile) / clock.Millisecond)
5757
}
5858
}
5959

cbreaker/predicates_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ package cbreaker
22

33
import (
44
"testing"
5-
"time"
65

76
"github.com/stretchr/testify/assert"
87
"github.com/stretchr/testify/require"
8+
"github.com/vulcand/oxy/internal/holsterv4/clock"
99
"github.com/vulcand/oxy/memmetrics"
1010
)
1111

@@ -27,12 +27,12 @@ func TestTripped(t *testing.T) {
2727
},
2828
{
2929
expression: "LatencyAtQuantileMS(50.0) > 50",
30-
metrics: statsLatencyAtQuantile(50, time.Millisecond*51),
30+
metrics: statsLatencyAtQuantile(50, clock.Millisecond*51),
3131
expected: true,
3232
},
3333
{
3434
expression: "LatencyAtQuantileMS(50.0) < 50",
35-
metrics: statsLatencyAtQuantile(50, time.Millisecond*51),
35+
metrics: statsLatencyAtQuantile(50, clock.Millisecond*51),
3636
expected: false,
3737
},
3838
{

0 commit comments

Comments
 (0)