Skip to content

Commit 1714863

Browse files
committed
Handle client closed request situations
1 parent d4a391e commit 1714863

2 files changed

Lines changed: 64 additions & 9 deletions

File tree

tests/worker/start_task_test.go

Lines changed: 42 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,43 @@ 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+
api.HandleCreateTask(createResponseRecorder, createRequest)
130+
131+
assert.Equal(t, 499, createResponseRecorder.Code, "Response status code should be 499 Client Closed Request")
132+
assert.Equal(t, "Error when executing the task: client closed request", createResponseRecorder.Body.String(), "Response body should contain error message")
133+
assert.Empty(t, api.Worker.Tasks, "Tasks map should be empty")
134+
}()
135+
136+
time.Sleep(1 * time.Second)
137+
138+
assert.Equal(t, 1, len(api.Worker.Tasks), "Tasks map should contain 1 task")
139+
140+
// 2 - Cancel a request
141+
stdout := helper.CaptureStdout(func() {
142+
cancel()
143+
time.Sleep(2 * time.Second)
144+
})
145+
146+
assert.NotEmpty(t, stdout, "Task logs shouldn't be empty")
147+
148+
wg.Wait()
149+
}

worker/api.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,31 @@ 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+
go func() {
74+
errCh <- a.Worker.StartTask(t)
75+
}()
76+
77+
select {
78+
case <-r.Context().Done():
79+
a.Worker.StopTask(t.ID)
80+
81+
w.WriteHeader(499) // client closed request
82+
fmt.Fprint(w, "Error when executing the task: client closed request")
83+
case err := <-errCh:
84+
if err != nil {
85+
if errors.Is(err, task.ErrAlreadyExists) {
86+
w.WriteHeader(http.StatusConflict)
87+
} else {
88+
w.WriteHeader(http.StatusInternalServerError)
89+
}
90+
91+
fmt.Fprintf(w, "Error when executing the task: %v", err)
92+
return
7793
}
7894

79-
fmt.Fprintf(w, "Error when executing the task: %v", err)
80-
return
95+
w.WriteHeader(http.StatusCreated)
8196
}
82-
83-
w.WriteHeader(http.StatusCreated)
8497
}
8598

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

0 commit comments

Comments
 (0)