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:
Benson Wong
2025-03-11 10:39:14 -07:00
committed by GitHub
parent eeb72297f7
commit 9b2ed244e2
3 changed files with 31 additions and 8 deletions

View File

@@ -1,10 +1,11 @@
# This workflow will build a golang project
name: Go
name: CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
@@ -13,7 +14,7 @@ on:
jobs:
build:
run-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -23,5 +24,9 @@ jobs:
with:
go-version: '1.23'
- name: Test
run: make test-all
# necessary for testing proxy/Process swapping
- name: Create simple-responder
run: make simple-responder
- name: Test all
run: make test-all

View File

@@ -133,9 +133,24 @@ func (p *Process) start() error {
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()
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 {
return err
}

View File

@@ -169,6 +169,8 @@ func TestProcess_LowTTLValue(t *testing.T) {
}
// 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) {
if testing.Short() {
t.Skip("skipping slow test")
@@ -192,8 +194,9 @@ func TestProcess_HTTPRequestsHaveTimeToFinish(t *testing.T) {
wg.Add(1)
go func(key string) {
defer wg.Done()
// send a request that should take 5 * 200ms (1 second) to complete
req := httptest.NewRequest("GET", fmt.Sprintf("/slow-respond?echo=%s&delay=200ms", key), nil)
// send a request where simple-responder is will wait 300ms before responding
// this will simulate an in-progress request.
req := httptest.NewRequest("GET", fmt.Sprintf("/slow-respond?echo=%s&delay=300ms", key), nil)
w := httptest.NewRecorder()
process.ProxyRequest(w, req)
@@ -209,9 +212,9 @@ func TestProcess_HTTPRequestsHaveTimeToFinish(t *testing.T) {
}(key)
}
// stop the requests in the middle
// Stop the process while requests are still being processed
go func() {
<-time.After(500 * time.Millisecond)
<-time.After(150 * time.Millisecond)
process.Stop()
}()