Skip to content

Commit

Permalink
cleanup lint & test
Browse files Browse the repository at this point in the history
  • Loading branch information
dc0d committed Jun 1, 2021
1 parent a2f50ec commit a4d8923
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 72 deletions.
26 changes: 21 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ name: Test
on: [push, pull_request]

jobs:
test:
lint:
runs-on: ubuntu-latest
continue-on-error: false
timeout-minutes: 5

steps:
- name: Install Go
Expand All @@ -16,10 +17,25 @@ jobs:
- name: Checkout Code
uses: actions/checkout@v2

- name: Test
run: go test -count=1 -timeout 60s ./...

- name: Lint
uses: golangci/golangci-lint-action@v2
with:
version: v1.29
version: v1.40.1

test:
runs-on: ubuntu-latest
continue-on-error: false
timeout-minutes: 5
needs: lint

steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '^1.15'

- name: Checkout Code
uses: actions/checkout@v2

- name: Test
run: go test -count=1 -timeout 60s ./...
6 changes: 3 additions & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ linters-settings:
lines: 100
statements: 50
gci:
local-prefixes: github.com/golangci/golangci-lint
local-prefixes: github.com/dc0d/spool
goconst:
min-len: 2
min-occurrences: 2
Expand All @@ -34,7 +34,7 @@ linters-settings:
gocyclo:
min-complexity: 15
goimports:
local-prefixes: github.com/golangci/golangci-lint
local-prefixes: github.com/dc0d/spool
golint:
min-confidence: 0
gomnd:
Expand Down Expand Up @@ -83,7 +83,6 @@ linters:
- gocyclo
- gofmt
- goimports
- golint
- gomnd
- goprintffuncname
- gosec
Expand Down Expand Up @@ -121,6 +120,7 @@ linters:
# - testpackage
# - revive
# - wsl
# - golint

issues:
# Excluding configuration per-path, per-linter, per-text and per-source
Expand Down
18 changes: 11 additions & 7 deletions worker-pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ func (pool Workerpool) Blocking(callback func()) {
<-done
}

// Nonblocking sends the job to the worker, as long as the mailbox is not full.
// SemiBlocking sends the job to the worker in a non-blocking manner, as long as the mailbox is not full.
// After that, it becomes blocking until there is an empty space in the mailbox.
// If the workerpool is stopped, Nonblocking will panic.
func (pool Workerpool) Nonblocking(callback func()) {
// If the workerpool is stopped, SemiBlocking will panic.
func (pool Workerpool) SemiBlocking(callback func()) {
pool <- callback
}

Expand All @@ -69,8 +69,12 @@ func (pool Workerpool) start(options growthOptions) {
}

func (pool Workerpool) worker(options growthOptions) {
workerStarted(pool)
defer workerStopped(pool)
if workerStarted != nil {
workerStarted(pool)
}
if workerStopped != nil {
defer workerStopped(pool)
}

var (
absoluteTimeout = options.absoluteTimeout
Expand Down Expand Up @@ -125,8 +129,8 @@ func execCallback(callback func()) {
}

var (
workerStarted = func(pool Workerpool) {}
workerStopped = func(pool Workerpool) {}
workerStarted func(pool Workerpool)
workerStopped func(pool Workerpool)
)

// growth options
Expand Down
113 changes: 56 additions & 57 deletions worker-pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func Test_Workerpool_Nonblocking_should_just_put_job_in_the_mailbox(t *testing.T

wg.Add(n)
for i := 0; i < n; i++ {
pool.Nonblocking(func() {
pool.SemiBlocking(func() {
defer wg.Done()
atomic.AddInt64(&counter, 1)
})
Expand Down Expand Up @@ -98,40 +98,46 @@ func Test_Workerpool_should_not_stop_because_of_panic(t *testing.T) {

func Test_Workerpool_Grow_should_spin_up_at_least_one_new_worker(t *testing.T) {
increased := 1
expectedNumberOfWorkers := increased /* the one extra worker */ + 1 /* the default worker */
pool := Init(9)
defer pool.Stop()

negativeOrZero := 0
pool.Grow(negativeOrZero)
time.Sleep(time.Millisecond * 50)

assert.Equal(t, expectedNumberOfWorkers, getNumberOfWorkers(pool))
expectedNumberOfWorkers := increased /* the one extra worker */ + 1 /* the default worker */
assert.Eventuallyf(t, func() bool {
return expectedNumberOfWorkers == getNumberOfWorkers(pool)
}, time.Millisecond*500, time.Millisecond*50,
"expectedNumberOfWorkers: %v, actual: %v", expectedNumberOfWorkers, getNumberOfWorkers(pool))
}

func Test_Workerpool_Grow_should_spin_up_multiple_new_workers(t *testing.T) {
increased := 10
expectedNumberOfWorkers := increased + 1
pool := Init(9)
defer pool.Stop()

pool.Grow(increased)
time.Sleep(time.Millisecond * 50)

assert.Equal(t, expectedNumberOfWorkers, getNumberOfWorkers(pool))
expectedNumberOfWorkers := increased + 1
assert.Eventuallyf(t, func() bool {
return expectedNumberOfWorkers == getNumberOfWorkers(pool)
}, time.Millisecond*500, time.Millisecond*50,
"expectedNumberOfWorkers: %v, actual: %v", expectedNumberOfWorkers, getNumberOfWorkers(pool))
}

func Test_Workerpool_Grow_should_stop_extra_workers_with_absolute_timeout(t *testing.T) {
increased := 10
expectedNumberOfWorkers := 1
absoluteTimeout := time.Millisecond * 10
pool := Init(9)
defer pool.Stop()

pool.Grow(increased, WithAbsoluteTimeout(absoluteTimeout))
time.Sleep(time.Millisecond * 50)

assert.Equal(t, expectedNumberOfWorkers, getNumberOfWorkers(pool))
expectedNumberOfWorkers := 1
assert.Eventuallyf(t, func() bool {
return expectedNumberOfWorkers == getNumberOfWorkers(pool)
}, time.Millisecond*500, time.Millisecond*50,
"expectedNumberOfWorkers: %v, actual: %v", expectedNumberOfWorkers, getNumberOfWorkers(pool))
}

func Test_Workerpool_Grow_should_stop_extra_workers_with_idle_timeout_when_there_are_no_more_jobs(t *testing.T) {
Expand All @@ -145,20 +151,18 @@ func Test_Workerpool_Grow_should_stop_extra_workers_with_idle_timeout_when_there
wg := &sync.WaitGroup{}
wg.Add(n)
for i := 0; i < n; i++ {
go pool.Nonblocking(func() {
go pool.SemiBlocking(func() {
defer wg.Done()
<-start
})
}

pool.Grow(increased, WithIdleTimeout(idleTimeout))
expectedNumberOfWorkers := 1 + increased
for i := 0; i < 3; i++ {
if expectedNumberOfWorkers > getNumberOfWorkers(pool) {
time.Sleep(time.Millisecond * 50)
}
}
assert.Equal(t, expectedNumberOfWorkers, getNumberOfWorkers(pool))
assert.Eventuallyf(t, func() bool {
return expectedNumberOfWorkers == getNumberOfWorkers(pool)
}, time.Millisecond*500, time.Millisecond*50,
"expectedNumberOfWorkers: %v, actual: %v", expectedNumberOfWorkers, getNumberOfWorkers(pool))

go func() {
for i := 0; i < n; i++ {
Expand All @@ -168,12 +172,10 @@ func Test_Workerpool_Grow_should_stop_extra_workers_with_idle_timeout_when_there
wg.Wait()

expectedNumberOfWorkers = 1
for i := 0; i < 3; i++ {
if expectedNumberOfWorkers < getNumberOfWorkers(pool) {
time.Sleep(time.Millisecond * 50)
}
}
assert.Equal(t, expectedNumberOfWorkers, getNumberOfWorkers(pool))
assert.Eventuallyf(t, func() bool {
return expectedNumberOfWorkers == getNumberOfWorkers(pool)
}, time.Millisecond*500, time.Millisecond*50,
"expectedNumberOfWorkers: %v, actual: %v", expectedNumberOfWorkers, getNumberOfWorkers(pool))
}

func Test_Workerpool_Grow_should_stop_extra_workers_with_explicit_stop_signal(t *testing.T) {
Expand All @@ -185,44 +187,45 @@ func Test_Workerpool_Grow_should_stop_extra_workers_with_explicit_stop_signal(t
pool.Grow(increased, WithStopSignal(stopSignal))

expectedNumberOfWorkers := 1 + increased
for i := 0; i < 3; i++ {
if expectedNumberOfWorkers > getNumberOfWorkers(pool) {
time.Sleep(time.Millisecond * 50)
}
}
assert.Equal(t, expectedNumberOfWorkers, getNumberOfWorkers(pool))
assert.Eventuallyf(t, func() bool {
return expectedNumberOfWorkers == getNumberOfWorkers(pool)
}, time.Millisecond*500, time.Millisecond*50,
"expectedNumberOfWorkers: %v, actual: %v", expectedNumberOfWorkers, getNumberOfWorkers(pool))

close(stopSignal)
expectedNumberOfWorkers = 1
for i := 0; i < 3; i++ {
if expectedNumberOfWorkers < getNumberOfWorkers(pool) {
time.Sleep(time.Millisecond * 50)
}
}
assert.Equal(t, expectedNumberOfWorkers, getNumberOfWorkers(pool))
assert.Eventuallyf(t, func() bool {
return expectedNumberOfWorkers == getNumberOfWorkers(pool)
}, time.Millisecond*500, time.Millisecond*50,
"expectedNumberOfWorkers: %v, actual: %v", expectedNumberOfWorkers, getNumberOfWorkers(pool))
}

func Test_Workerpool_Grow_should_respawn_after_a_certain_number_of_requests(t *testing.T) {
pool := Init(9, WithRespawnAfter(10))
defer pool.Stop()

time.Sleep(time.Millisecond * 50)
assert.Equal(t, 1, getNumberOfStarts(pool)) // one start
expectedNumberOfStarts := 1 // one initial start
assert.Eventually(t, func() bool {
return expectedNumberOfStarts == getNumberOfStarts(pool)
}, time.Millisecond*500, time.Millisecond*50)

for i := 0; i < 11; i++ {
pool.Blocking(func() {})
}

time.Sleep(time.Millisecond * 50)
assert.Equal(t, 2, getNumberOfStarts(pool))
expectedNumberOfStarts = 2
assert.Eventually(t, func() bool {
return expectedNumberOfStarts == getNumberOfStarts(pool)
}, time.Millisecond*500, time.Millisecond*50)
}

func Test_Workerpool_Grow_should_respawn_after_a_certain_timespan_if_reapawnAfter_is_provided(t *testing.T) {
pool := Init(9, WithRespawnAfter(1000), WithIdleTimeout(time.Millisecond*50))
defer pool.Stop()

time.Sleep(time.Millisecond * 190)
assert.Equal(t, 4, getNumberOfStarts(pool))
expectedNumberOfStarts := 4
assert.Equal(t, expectedNumberOfStarts, getNumberOfStarts(pool))
}

//
Expand All @@ -232,7 +235,7 @@ func Test_Workerpool_Stop_should_close_the_pool(t *testing.T) {
pool.Stop()

assert.Panics(t, func() {
pool.Nonblocking(func() {})
pool.SemiBlocking(func() {})
})
}

Expand All @@ -243,26 +246,22 @@ func Test_Workerpool_Stop_should_stop_the_workers(t *testing.T) {
pool.Grow(increased)

expectedNumberOfWorkers := 1 + increased
for i := 0; i < 3; i++ {
if expectedNumberOfWorkers > getNumberOfWorkers(pool) {
time.Sleep(time.Millisecond * 50)
}
}
assert.Equal(t, expectedNumberOfWorkers, getNumberOfWorkers(pool))
assert.Eventuallyf(t, func() bool {
return expectedNumberOfWorkers == getNumberOfWorkers(pool)
}, time.Millisecond*500, time.Millisecond*50,
"expectedNumberOfWorkers: %v, actual: %v", expectedNumberOfWorkers, getNumberOfWorkers(pool))

pool.Stop()

assert.Panics(t, func() {
pool.Nonblocking(func() {})
pool.SemiBlocking(func() {})
})

expectedNumberOfWorkers = 0
for i := 0; i < 3; i++ {
if expectedNumberOfWorkers < getNumberOfWorkers(pool) {
time.Sleep(time.Millisecond * 50)
}
}
assert.Equal(t, expectedNumberOfWorkers, getNumberOfWorkers(pool))
assert.Eventuallyf(t, func() bool {
return expectedNumberOfWorkers == getNumberOfWorkers(pool)
}, time.Millisecond*500, time.Millisecond*50,
"expectedNumberOfWorkers: %v, actual: %v", expectedNumberOfWorkers, getNumberOfWorkers(pool))
}

//
Expand Down Expand Up @@ -346,7 +345,7 @@ func ExampleWorkerpool_Blocking() {
// 19
}

func ExampleWorkerpool_Nonblocking() {
func ExampleWorkerpool_SemiBlocking() {
pool := Init(1)
defer pool.Stop()

Expand All @@ -357,7 +356,7 @@ func ExampleWorkerpool_Nonblocking() {
atomic.AddInt64(&state, 19)
}

pool.Nonblocking(job)
pool.SemiBlocking(job)
<-jobDone

fmt.Println(state)
Expand All @@ -377,7 +376,7 @@ func ExampleWorkerpool_Grow() {
wg := &sync.WaitGroup{}
wg.Add(n)
for i := 0; i < n; i++ {
pool.Nonblocking(func() { defer wg.Done(); atomic.AddInt64(&state, 1) })
pool.SemiBlocking(func() { defer wg.Done(); atomic.AddInt64(&state, 1) })
}
wg.Wait()

Expand Down

0 comments on commit a4d8923

Please sign in to comment.