Skip to content

Commit 3e0f876

Browse files
committed
Improved logging on close timeout
1 parent eded2a5 commit 3e0f876

File tree

5 files changed

+22
-25
lines changed

5 files changed

+22
-25
lines changed

kafka.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ Interfaces.
1515
type KafkaConsumer interface {
1616
Subscribe(topic string, rebalanceCb kafka.RebalanceCb) error
1717
ReadMessage(timeout time.Duration) (*kafka.Message, error)
18-
Events() chan kafka.Event
1918
Close() error
2019
}
2120

kafka_mock_test.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,16 @@ import (
1010
type consMockFuncs struct {
1111
Subscribe func(m *consMock, topic string, rebalanceCb kafka.RebalanceCb) error
1212
ReadMessage func(m *consMock, timeout time.Duration) (*kafka.Message, error)
13-
Events func(m *consMock) chan kafka.Event
1413
Close func(m *consMock) error
1514
}
1615

1716
type consMockCounts struct {
1817
Subscribe,
1918
ReadMessage,
20-
Events,
2119
Close concurrent.AtomicCounter
2220
}
2321

2422
type consMock struct {
25-
events chan kafka.Event
2623
rebalanceCallback kafka.RebalanceCb
2724
rebalanceEvents chan kafka.Event
2825
messages chan *kafka.Message
@@ -50,20 +47,12 @@ func (m *consMock) ReadMessage(timeout time.Duration) (*kafka.Message, error) {
5047
return m.f.ReadMessage(m, timeout)
5148
}
5249

53-
func (m *consMock) Events() chan kafka.Event {
54-
defer m.c.Events.Inc()
55-
return m.f.Events(m)
56-
}
57-
5850
func (m *consMock) Close() error {
5951
defer m.c.Close.Inc()
6052
return m.f.Close(m)
6153
}
6254

6355
func (m *consMock) fillDefaults() {
64-
if m.events == nil {
65-
m.events = make(chan kafka.Event)
66-
}
6756
if m.rebalanceEvents == nil {
6857
m.rebalanceEvents = make(chan kafka.Event)
6958
}
@@ -85,17 +74,11 @@ func (m *consMock) fillDefaults() {
8574
}
8675
}
8776
}
88-
if m.f.Events == nil {
89-
m.f.Events = func(m *consMock) chan kafka.Event {
90-
return m.events
91-
}
92-
}
9377
if m.f.Close == nil {
9478
m.f.Close = func(m *consMock) error {
9579
return nil
9680
}
9781
}
98-
m.c.Events = concurrent.NewAtomicCounter()
9982
m.c.Subscribe = concurrent.NewAtomicCounter()
10083
m.c.ReadMessage = concurrent.NewAtomicCounter()
10184
m.c.Close = concurrent.NewAtomicCounter()

neli.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,10 +372,10 @@ func (n *neli) Close() error {
372372
// the Events channel. So we delegate this to a separate goroutine — better an orphaned goroutine than a
373373
// frozen harvester. (The rest of the battery will still unwind normally.)
374374
const closeTimeout = 10 * time.Second
375-
_, _ = performTimed(void(n.producer.Close), closeTimeout)
375+
_, _ = performTimed(n.logger().W(), "producer close", void(n.producer.Close), closeTimeout)
376376

377377
// Similarly to the above, Consumer.Close() may also hang, and we need to cope with this until #463 is resolved.
378-
_, err := performTimed(n.consumer.Close, closeTimeout)
378+
_, err := performTimed(n.logger().W(), "consumer close", n.consumer.Close, closeTimeout)
379379
return err
380380
}
381381

timed.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"time"
66

77
"github.com/obsidiandynamics/libstdgo/concurrent"
8+
"github.com/obsidiandynamics/libstdgo/scribe"
89
)
910

1011
var errPerformWithNoError = errors.New("")
@@ -16,10 +17,10 @@ func void(f func()) func() error {
1617
}
1718
}
1819

19-
func performTimed(f func() error, timeout time.Duration) (bool, error) {
20+
func performTimed(logger scribe.Logger, opName string, op func() error, timeout time.Duration) (bool, error) {
2021
errorRef := concurrent.NewAtomicReference()
2122
go func() {
22-
err := f()
23+
err := op()
2324
if err != nil {
2425
errorRef.Set(err)
2526
} else {
@@ -29,6 +30,7 @@ func performTimed(f func() error, timeout time.Duration) (bool, error) {
2930

3031
res := errorRef.Await(concurrent.RefNot(concurrent.RefNil()), timeout)
3132
if res == nil {
33+
logger("Operation '%s' failed to complete within %v", opName, timeout)
3234
return false, nil
3335
}
3436
if err := res.(error); err != errPerformWithNoError {

timed_test.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,46 @@ import (
66
"time"
77

88
"github.com/obsidiandynamics/libstdgo/check"
9+
"github.com/obsidiandynamics/libstdgo/scribe"
910
"github.com/stretchr/testify/require"
1011
)
1112

1213
func TestPerformTimed_noError(t *testing.T) {
13-
done, err := performTimed(void(func() {}), 10*time.Second)
14+
m := scribe.NewMock()
15+
scr := scribe.New(m.Factories())
16+
done, err := performTimed(scr.W(), "some-op", void(func() {}), 10*time.Second)
1417
require.True(t, done)
1518
require.Nil(t, err)
19+
m.Entries().Assert(t, scribe.Count(0))
1620
}
1721

1822
func TestPerformTimed_withError(t *testing.T) {
19-
done, err := performTimed(func() error {
23+
m := scribe.NewMock()
24+
scr := scribe.New(m.Factories())
25+
done, err := performTimed(scr.W(), "some-op", func() error {
2026
return check.ErrSimulated
2127
}, 10*time.Second)
2228
require.True(t, done)
2329
require.Equal(t, check.ErrSimulated, err)
30+
m.Entries().Assert(t, scribe.Count(0))
2431
}
2532

2633
func TestPerformTimed_withTimeout(t *testing.T) {
34+
m := scribe.NewMock()
35+
scr := scribe.New(m.Factories())
2736
wg := sync.WaitGroup{}
2837
wg.Add(1)
2938

30-
done, err := performTimed(func() error {
39+
done, err := performTimed(scr.W(), "some-op", func() error {
3140
wg.Wait()
3241
return nil
3342
}, 1*time.Millisecond)
3443
require.False(t, done)
3544
require.Nil(t, err)
45+
m.Entries().
46+
Having(scribe.LogLevel(scribe.Warn)).
47+
Having(scribe.MessageEqual("Operation 'some-op' failed to complete within 1ms")).
48+
Assert(t, scribe.Count(1))
3649

3750
wg.Done()
3851
}

0 commit comments

Comments
 (0)