Skip to content

Commit 40cd57c

Browse files
committed
fix unit test and address comment on AcquireChan return
1 parent c5f2d53 commit 40cd57c

File tree

6 files changed

+40
-22
lines changed

6 files changed

+40
-22
lines changed

internal/internal_poller_autoscaler.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ func (p *pollerAutoScaler) Start() {
135135
p.permit.SetQuota(int(proposedResource))
136136
}
137137
p.pollerUsageEstimator.Reset()
138+
139+
// hooks
140+
for i := range p.onAutoScale {
141+
p.onAutoScale[i]()
142+
}
138143
}
139144
}
140145
}()

internal/internal_poller_autoscaler_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ func Test_pollerAutoscaler(t *testing.T) {
193193
go func() {
194194
defer wg.Done()
195195
for pollResult := range pollChan {
196-
pollerScaler.permit.Acquire(context.Background())
196+
err := pollerScaler.permit.Acquire(context.Background())
197+
assert.NoError(t, err)
197198
pollerScaler.CollectUsage(pollResult)
198199
pollerScaler.permit.Release()
199200
}
@@ -202,7 +203,7 @@ func Test_pollerAutoscaler(t *testing.T) {
202203

203204
assert.Eventually(t, func() bool {
204205
return autoscalerEpoch.Load() == uint64(tt.args.autoScalerEpoch)
205-
}, tt.args.cooldownTime+20*time.Millisecond, 10*time.Millisecond)
206+
}, tt.args.cooldownTime+100*time.Millisecond, 10*time.Millisecond)
206207
pollerScaler.Stop()
207208
res := pollerScaler.permit.Quota() - pollerScaler.permit.Count()
208209
assert.Equal(t, tt.want, int(res))

internal/internal_worker_base.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,14 +248,13 @@ func (bw *baseWorker) runPoller() {
248248
bw.metricsScope.Counter(metrics.PollerStartCounter).Inc(1)
249249

250250
for {
251-
// permitChannel can be blocking without passing context because shutdownCh is used
252-
permitChannel := bw.concurrency.PollerPermit.AcquireChan(context.Background())
251+
permitChannel, channelDone := bw.concurrency.TaskPermit.AcquireChan(bw.limiterContext)
253252
select {
254253
case <-bw.shutdownCh:
255-
permitChannel.Close()
254+
channelDone()
256255
return
257-
case <-permitChannel.C(): // don't poll unless there is a task permit
258-
permitChannel.Close()
256+
case <-permitChannel: // don't poll unless there is a task permit
257+
channelDone()
259258
// TODO move to a centralized place inside the worker
260259
// emit metrics on concurrent task permit quota and current task permit count
261260
// NOTE task permit doesn't mean there is a task running, it still needs to poll until it gets a task to process

internal/worker/concurrency.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,9 @@ type ConcurrencyLimit struct {
3333
// Permit is an adaptive permit issuer to control concurrency
3434
type Permit interface {
3535
Acquire(context.Context) error
36-
AcquireChan(context.Context) PermitChannel
36+
AcquireChan(context.Context) (channel <-chan struct{}, done func())
3737
Count() int
3838
Quota() int
3939
Release()
4040
SetQuota(int)
4141
}
42-
43-
// PermitChannel is a channel that can be used to wait for a permit to be available
44-
// Remember to call Close() to avoid goroutine leak
45-
type PermitChannel interface {
46-
C() <-chan struct{}
47-
Close()
48-
}

internal/worker/resizable_permit.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (p *resizablePermit) Count() int {
7070
// After usage:
7171
// 1. avoid goroutine leak by calling permitChannel.Close()
7272
// 2. release permit by calling permit.Release()
73-
func (p *resizablePermit) AcquireChan(ctx context.Context) PermitChannel {
73+
func (p *resizablePermit) AcquireChan(ctx context.Context) (<-chan struct{}, func()) {
7474
ctx, cancel := context.WithCancel(ctx)
7575
pc := &permitChannel{
7676
p: p,
@@ -79,8 +79,10 @@ func (p *resizablePermit) AcquireChan(ctx context.Context) PermitChannel {
7979
cancel: cancel,
8080
wg: &sync.WaitGroup{},
8181
}
82-
pc.start()
83-
return pc
82+
pc.Start()
83+
return pc.C(), func() {
84+
pc.Close()
85+
}
8486
}
8587

8688
type permitChannel struct {
@@ -95,7 +97,7 @@ func (ch *permitChannel) C() <-chan struct{} {
9597
return ch.c
9698
}
9799

98-
func (ch *permitChannel) start() {
100+
func (ch *permitChannel) Start() {
99101
ch.wg.Add(1)
100102
go func() {
101103
defer ch.wg.Done()

internal/worker/resizable_permit_test.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030

3131
"github.com/stretchr/testify/assert"
3232
"go.uber.org/atomic"
33+
"go.uber.org/goleak"
3334
)
3435

3536
func TestPermit_Simulation(t *testing.T) {
@@ -86,6 +87,7 @@ func TestPermit_Simulation(t *testing.T) {
8687

8788
for _, tt := range tests {
8889
t.Run(tt.name, func(t *testing.T) {
90+
defer goleak.VerifyNone(t)
8991
wg := &sync.WaitGroup{}
9092
permit := NewResizablePermit(tt.capacity[0])
9193
wg.Add(1)
@@ -117,15 +119,15 @@ func TestPermit_Simulation(t *testing.T) {
117119
wg.Add(1)
118120
go func() {
119121
defer wg.Done()
120-
permitChan := permit.AcquireChan(ctx)
122+
permitChan, done := permit.AcquireChan(ctx)
121123
select {
122-
case <-permitChan.C():
124+
case <-permitChan:
123125
time.Sleep(time.Duration(100+rand.Intn(50)) * time.Millisecond)
124126
permit.Release()
125127
case <-ctx.Done():
126128
failures.Inc()
127129
}
128-
permitChan.Close()
130+
done()
129131
}()
130132
}
131133

@@ -142,3 +144,19 @@ func TestPermit_Simulation(t *testing.T) {
142144
})
143145
}
144146
}
147+
148+
func Test_Permit_AcquireChan(t *testing.T) {
149+
permit := NewResizablePermit(2)
150+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
151+
defer cancel()
152+
permitChan, done := permit.AcquireChan(ctx)
153+
select {
154+
case <-permitChan:
155+
assert.Equal(t, 2, permit.Quota())
156+
assert.Equal(t, 1, permit.Count())
157+
case <-ctx.Done():
158+
t.Error("unexpected timeout")
159+
}
160+
done()
161+
permit.Release()
162+
}

0 commit comments

Comments
 (0)