Improve Continuous integration and fix concurrency bugs (#66)
- improvements to the continuous GH actions - fix edge case concurrency bugs with Process.start() and state transitions discovered setting up CI.
This commit is contained in:
13
.github/workflows/go-ci.yml
vendored
13
.github/workflows/go-ci.yml
vendored
@@ -1,10 +1,11 @@
|
|||||||
# This workflow will build a golang project
|
# This workflow will build a golang project
|
||||||
|
|
||||||
name: Go
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ "main" ]
|
branches: [ "main" ]
|
||||||
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ "main" ]
|
branches: [ "main" ]
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
build:
|
run-tests:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -23,5 +24,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
go-version: '1.23'
|
go-version: '1.23'
|
||||||
|
|
||||||
- name: Test
|
# necessary for testing proxy/Process swapping
|
||||||
run: make test-all
|
- name: Create simple-responder
|
||||||
|
run: make simple-responder
|
||||||
|
|
||||||
|
- name: Test all
|
||||||
|
run: make test-all
|
||||||
@@ -133,9 +133,24 @@ func (p *Process) start() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There is the possibility of a hard to replicate race condition where
|
||||||
|
// curState *WAS* StateStopped but by the time we get to the p.stateMutex.Lock()
|
||||||
|
// below, it's value has changed!
|
||||||
|
|
||||||
p.stateMutex.Lock()
|
p.stateMutex.Lock()
|
||||||
defer p.stateMutex.Unlock()
|
defer p.stateMutex.Unlock()
|
||||||
|
|
||||||
|
// with the exclusive lock, check if p.state is StateStopped, which is the only valid state
|
||||||
|
// to transition from to StateReady
|
||||||
|
|
||||||
|
if p.state != StateStopped {
|
||||||
|
if p.state == StateReady {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("start() can not proceed expected StateReady but process is in %v", p.state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := p.setState(StateStarting); err != nil {
|
if err := p.setState(StateStarting); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,6 +169,8 @@ func TestProcess_LowTTLValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// issue #19
|
// issue #19
|
||||||
|
// This test makes sure using Process.Stop() does not affect pending HTTP
|
||||||
|
// requests. All HTTP requests in this test should complete successfully.
|
||||||
func TestProcess_HTTPRequestsHaveTimeToFinish(t *testing.T) {
|
func TestProcess_HTTPRequestsHaveTimeToFinish(t *testing.T) {
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip("skipping slow test")
|
t.Skip("skipping slow test")
|
||||||
@@ -192,8 +194,9 @@ func TestProcess_HTTPRequestsHaveTimeToFinish(t *testing.T) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(key string) {
|
go func(key string) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
// send a request that should take 5 * 200ms (1 second) to complete
|
// send a request where simple-responder is will wait 300ms before responding
|
||||||
req := httptest.NewRequest("GET", fmt.Sprintf("/slow-respond?echo=%s&delay=200ms", key), nil)
|
// this will simulate an in-progress request.
|
||||||
|
req := httptest.NewRequest("GET", fmt.Sprintf("/slow-respond?echo=%s&delay=300ms", key), nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
process.ProxyRequest(w, req)
|
process.ProxyRequest(w, req)
|
||||||
@@ -209,9 +212,9 @@ func TestProcess_HTTPRequestsHaveTimeToFinish(t *testing.T) {
|
|||||||
}(key)
|
}(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop the requests in the middle
|
// Stop the process while requests are still being processed
|
||||||
go func() {
|
go func() {
|
||||||
<-time.After(500 * time.Millisecond)
|
<-time.After(150 * time.Millisecond)
|
||||||
process.Stop()
|
process.Stop()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user