Skip to content

Commit 6a94b32

Browse files
committed
Handle client closed request situations
1 parent 9d2bd6e commit 6a94b32

3 files changed

Lines changed: 68 additions & 9 deletions

File tree

tests/helper/stdout.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package helper
22

33
import (
4+
"fmt"
45
"io"
56
"os"
67
)
@@ -17,6 +18,8 @@ func CaptureStdout(f func()) string {
1718

1819
f()
1920

21+
fmt.Println() // to flush data
22+
2023
w.Close()
2124
b, _ := io.ReadAll(r)
2225

tests/worker/start_task_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package worker
22

33
import (
4+
"context"
45
"dirigeant/task"
56
"dirigeant/tests/helper"
67
"dirigeant/worker"
@@ -9,6 +10,7 @@ import (
910
"net/http/httptest"
1011
"sync"
1112
"testing"
13+
"time"
1214

1315
"github.com/google/uuid"
1416
"github.com/stretchr/testify/assert"
@@ -105,3 +107,41 @@ func TestStartTask__AllButOneRequestsShouldFailIfCreatingTheSameTaskSimultaneous
105107
assert.Equal(t, 1, len(api.Worker.Tasks), "Tasks map should contain 1 task")
106108
assert.NotNil(t, api.Worker.Tasks[testTask.ID], "Persisted task ID should match the one from request")
107109
}
110+
111+
func TestStartTask__ShouldHandleClientClosedRequest(t *testing.T) {
112+
api := &worker.Api{
113+
Worker: &worker.Worker{
114+
Tasks: make(map[uuid.UUID]*task.Task),
115+
},
116+
}
117+
testTask := helper.PingTask("ping-task", "127.0.0.1")
118+
ctx, cancel := context.WithCancel(context.TODO())
119+
120+
// 1 - Create a task
121+
var wg sync.WaitGroup
122+
wg.Add(1)
123+
go func() {
124+
defer wg.Done()
125+
126+
createRequest := helper.NewTaskPostRequest(testTask).WithContext(ctx)
127+
createResponseRecorder := httptest.NewRecorder()
128+
129+
stdout := helper.CaptureStdout(func() {
130+
api.HandleCreateTask(createResponseRecorder, createRequest)
131+
})
132+
133+
assert.Equal(t, 499, createResponseRecorder.Code, "Response status code should be 499 Client Closed Request")
134+
assert.Equal(t, "Error when executing the task: client closed request", createResponseRecorder.Body.String(), "Response body should contain error message")
135+
assert.NotEmpty(t, stdout, "Task logs shouldn't be empty")
136+
assert.Empty(t, api.Worker.Tasks, "Tasks map should be empty")
137+
}()
138+
139+
time.Sleep(1 * time.Second)
140+
141+
assert.Equal(t, 1, len(api.Worker.Tasks), "Tasks map should contain 1 task")
142+
143+
// 2 - Cancel a request
144+
cancel()
145+
146+
wg.Wait()
147+
}

worker/api.go

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,34 @@ func (a *Api) HandleCreateTask(w http.ResponseWriter, r *http.Request) {
6969
return
7070
}
7171

72-
if err := a.Worker.StartTask(t); err != nil {
73-
if errors.Is(err, task.ErrAlreadyExists) {
74-
w.WriteHeader(http.StatusConflict)
75-
} else {
76-
w.WriteHeader(http.StatusInternalServerError)
72+
errCh := make(chan error)
73+
defer close(errCh)
74+
go func() {
75+
errCh <- a.Worker.StartTask(t)
76+
}()
77+
78+
select {
79+
case <-r.Context().Done():
80+
a.Worker.StopTask(t.ID)
81+
82+
<-errCh
83+
84+
w.WriteHeader(499) // client closed request
85+
fmt.Fprint(w, "Error when executing the task: client closed request")
86+
case err := <-errCh:
87+
if err != nil {
88+
if errors.Is(err, task.ErrAlreadyExists) {
89+
w.WriteHeader(http.StatusConflict)
90+
} else {
91+
w.WriteHeader(http.StatusInternalServerError)
92+
}
93+
94+
fmt.Fprintf(w, "Error when executing the task: %v", err)
95+
return
7796
}
7897

79-
fmt.Fprintf(w, "Error when executing the task: %v", err)
80-
return
98+
w.WriteHeader(http.StatusCreated)
8199
}
82-
83-
w.WriteHeader(http.StatusCreated)
84100
}
85101

86102
func (a *Api) HandleDeleteTask(w http.ResponseWriter, r *http.Request) {

0 commit comments

Comments
 (0)