Repository: MrShanks/Taska
Pull request #36: add context to connection
Author: login: BarbalberoKills
Created: 2025-03-19T18:20:18Z | Merged: 2025-03-21T20:28:56Z

For the moment I've added a proper context in the connection to see if it is the right way.
I'm not sure which may be the best way to return the error. Any suggestions are more than welcome.


Diff:
diff --git a/taskcli/cmd/common.go b/taskcli/cmd/common.go
index d5aca9a..19e4517 100644
--- a/taskcli/cmd/common.go
+++ b/taskcli/cmd/common.go
@@ -120,17 +120,17 @@ func fetch(taskcli *Taskcli, ctx context.Context, endpoint string, result any, t
 func makeRequest(taskcli *Taskcli, ctx context.Context, data map[string]string) (*http.Response, error) {
 	body, err := json.Marshal(data)
 	if err != nil {
-		return nil, fmt.Errorf("Couldn't marshal data into the request body: %v", err)
+		return nil, fmt.Errorf("couldn't marshal data into the request body: %v", err)
 	}
 
 	request, err := http.NewRequestWithContext(ctx, "POST", taskcli.ServerURL.String(), bytes.NewBuffer(body))
 	if err != nil {
-		return nil, fmt.Errorf("Couldn't create request: %v", err)
+		return nil, fmt.Errorf("couldn't create request: %v", err)
 	}
 
 	response, err := taskcli.HttpClient.Do(request)
 	if err != nil {
-		return nil, fmt.Errorf("Couldn't get a response from the server: %v", err)
+		return nil, fmt.Errorf("couldn't get a response from the server: %v", err)
 	}
 
 	return response, nil
diff --git a/taskcli/cmd/del.go b/taskcli/cmd/del.go
index a647bc7..b70ba0e 100644
--- a/taskcli/cmd/del.go
+++ b/taskcli/cmd/del.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"log"
 	"net/http"
+	"time"
 
 	"github.com/MrShanks/Taska/utils"
 	"github.com/spf13/cobra"
@@ -16,7 +17,9 @@ var delCmd = &cobra.Command{
 	Long:  "Delete a task by passing its id",
 
 	Run: func(cmd *cobra.Command, args []string) {
-		ctx := context.Background()
+		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+		defer cancel()
+
 		apiClient := NewApiClient()
 
 		token := utils.ReadToken()
diff --git a/taskcli/cmd/get.go b/taskcli/cmd/get.go
index f711cdc..a3789f9 100644
--- a/taskcli/cmd/get.go
+++ b/taskcli/cmd/get.go
@@ -5,6 +5,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"os"
+	"time"
 
 	"github.com/MrShanks/Taska/common/task"
 	"github.com/MrShanks/Taska/utils"
@@ -18,7 +19,9 @@ var getCmd = &cobra.Command{
 	Long:  "Get or dump on a file all active tasks stored on the server",
 
 	Run: func(cmd *cobra.Command, args []string) {
-		ctx := context.Background()
+		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+		defer cancel()
+
 		apiClient := NewApiClient()
 
 		format, err := cmd.Flags().GetString("export")
diff --git a/taskcli/cmd/getone.go b/taskcli/cmd/getone.go
index 08eaff7..c563189 100644
--- a/taskcli/cmd/getone.go
+++ b/taskcli/cmd/getone.go
@@ -4,12 +4,14 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
-	"github.com/MrShanks/Taska/common/task"
-	"github.com/MrShanks/Taska/utils"
-	"github.com/spf13/cobra"
 	"io"
 	"log"
 	"net/http"
+	"time"
+
+	"github.com/MrShanks/Taska/common/task"
+	"github.com/MrShanks/Taska/utils"
+	"github.com/spf13/cobra"
 )
 
 var getOneCmd = &cobra.Command{
@@ -20,8 +22,10 @@ var getOneCmd = &cobra.Command{
 
 	ValidArgsFunction: getCompletion,
 	Run: func(cmd *cobra.Command, args []string) {
+		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+		defer cancel()
+
 		apiClient := NewApiClient()
-		ctx := context.Background()
 
 		token := utils.ReadToken()
 
@@ -34,8 +38,10 @@ var getOneCmd = &cobra.Command{
 }
 
 func getCompletion(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
+	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+	defer cancel()
+
 	apiClient := NewApiClient()
-	ctx := context.Background()
 
 	token := utils.ReadToken()
 
diff --git a/taskcli/cmd/import.go b/taskcli/cmd/import.go
index 0753e5d..0340536 100644
--- a/taskcli/cmd/import.go
+++ b/taskcli/cmd/import.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"os"
 	"path/filepath"
+	"time"
 
 	"github.com/MrShanks/Taska/utils"
 	"github.com/spf13/cobra"
@@ -23,7 +24,9 @@ var importCmd = &cobra.Command{
 }
 
 func runImportCmd(cmd *cobra.Command, args []string) {
-	ctx := context.Background()
+	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+	defer cancel()
+
 	apiClient := NewApiClient()
 
 	token := utils.ReadToken()
diff --git a/taskcli/cmd/login.go b/taskcli/cmd/login.go
index 781ae6a..80c4067 100644
--- a/taskcli/cmd/login.go
+++ b/taskcli/cmd/login.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"io"
 	"net/http"
+	"time"
 
 	"github.com/MrShanks/Taska/utils"
 	"github.com/spf13/cobra"
@@ -18,8 +19,10 @@ var loginCmd = &cobra.Command{
 	Long:  "Login with email and password to get a token to auhtenticate future requests",
 
 	Run: func(cmd *cobra.Command, args []string) {
+		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+		defer cancel()
+
 		apiClient := NewApiClient()
-		ctx := context.Background()
 
 		email, err := cmd.Flags().GetString("email")
 		if err != nil {
@@ -58,7 +61,7 @@ func Login(taskcli *Taskcli, ctx context.Context, endpoint, email, password stri
 
 	srvMsg, err := io.ReadAll(response.Body)
 	if err != nil {
-		return fmt.Errorf("Couldn't read response body: %v", err)
+		return fmt.Errorf("couldn't read response body: %v", err)
 	}
 
 	fmt.Printf("%v\n", string(srvMsg))
diff --git a/taskcli/cmd/mod.go b/taskcli/cmd/mod.go
index 8c96357..66ca097 100644
--- a/taskcli/cmd/mod.go
+++ b/taskcli/cmd/mod.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"io"
 	"net/http"
+	"time"
 
 	"github.com/MrShanks/Taska/utils"
 	"github.com/spf13/cobra"
@@ -17,7 +18,9 @@ var modCmd = &cobra.Command{
 	Long:  "Modify a task by passing its id",
 
 	Run: func(cmd *cobra.Command, args []string) {
-		ctx := context.Background()
+		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+		defer cancel()
+
 		apiClient := NewApiClient()
 
 		token := utils.ReadToken()
diff --git a/taskcli/cmd/new.go b/taskcli/cmd/new.go
index 86e2c80..2b22fbc 100644
--- a/taskcli/cmd/new.go
+++ b/taskcli/cmd/new.go
@@ -7,6 +7,7 @@ import (
 	"fmt"
 	"io"
 	"net/http"
+	"time"
 
 	"github.com/spf13/cobra"
 
@@ -23,7 +24,9 @@ var newCmd = &cobra.Command{
 }
 
 func runNewCmd(cmd *cobra.Command, args []string) {
-	ctx := context.Background()
+	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+	defer cancel()
+
 	apiClient := NewApiClient()
 
 	title, desc, err := getFlags(cmd, 0)
diff --git a/taskcli/cmd/signup.go b/taskcli/cmd/signup.go
index 7757c71..fb7bfde 100644
--- a/taskcli/cmd/signup.go
+++ b/taskcli/cmd/signup.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"io"
 	"net/http"
+	"time"
 
 	"github.com/MrShanks/Taska/common/author"
 	"github.com/spf13/cobra"
@@ -16,8 +17,10 @@ var signupCmd = &cobra.Command{
 	Long:  "Signup a new auhtor to be able to login",
 
 	Run: func(cmd *cobra.Command, args []string) {
+		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+		defer cancel()
+
 		apiClient := NewApiClient()
-		ctx := context.Background()
 
 		firstname, err := cmd.Flags().GetString("firstname")
 		cobra.CheckErr(err)
diff --git a/taskmgr/server/server.go b/taskmgr/server/server.go
index 9783516..48bdf25 100644
--- a/taskmgr/server/server.go
+++ b/taskmgr/server/server.go
@@ -30,13 +30,11 @@ func NewServer(cfg *utils.Config, taskStore task.Store, authorStore author.Store
 	}
 }
 
-func ConnectDB(dbURL string) (*pgx.Conn, error) {
+func ConnectDB(ctx context.Context, dbURL string) (*pgx.Conn, error) {
 	password := os.Getenv("POSTGRES_PWD")
 	dburl := fmt.Sprintf(dbURL, password)
 
-	var err error
-
-	conn, err := pgx.Connect(context.Background(), dburl)
+	conn, err := pgx.Connect(ctx, dburl)
 	if err != nil {
 		return nil, err
 	}
@@ -48,11 +46,14 @@ func ConnectDB(dbURL string) (*pgx.Conn, error) {
 func Listen(cfg *utils.Config) error {
 	var err error
 
-	conn, err := ConnectDB(cfg.Spec.DB_URL)
+	ctxConnection, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
+
+	conn, err := ConnectDB(ctxConnection, cfg.Spec.DB_URL)
 	if err != nil {
 		return err
 	}
-	defer conn.Close(context.Background())
+	defer conn.Close(ctxConnection)
 
 	taskStore := storage.TaskStore{Conn: conn}
 	authorStore := storage.AuthorStore{Conn: conn}
diff --git a/taskmgr/storage/author_store_db.go b/taskmgr/storage/author_store_db.go
index ca8dee4..865193d 100644
--- a/taskmgr/storage/author_store_db.go
+++ b/taskmgr/storage/author_store_db.go
@@ -3,6 +3,7 @@ package storage
 import (
 	"context"
 	"fmt"
+	"time"
 
 	"github.com/MrShanks/Taska/common/author"
 	"github.com/jackc/pgx/v5"
@@ -17,7 +18,10 @@ func (db *AuthorStore) SignUp(newAuthor *author.Author) error {
 		"INSERT INTO author (firstname, lastname, email, password) values ('%s','%s','%s','%s');",
 		newAuthor.Firstname, newAuthor.Lastname, newAuthor.Email, newAuthor.Password)
 
-	_, err := db.Conn.Exec(context.Background(), query)
+	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
+
+	_, err := db.Conn.Exec(ctx, query)
 	if err != nil {
 		return fmt.Errorf("couldn't create author: %v", err)
 	}
@@ -30,7 +34,10 @@ func (db *AuthorStore) SignIn(email, password string) error {
 
 	a := author.Author{}
 
-	err := db.Conn.QueryRow(context.Background(), query).Scan(&a.ID, &a.Firstname, &a.Lastname, &a.Email, &a.Password)
+	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
+
+	err := db.Conn.QueryRow(ctx, query).Scan(&a.ID, &a.Firstname, &a.Lastname, &a.Email, &a.Password)
 	if err == pgx.ErrNoRows {
 		return fmt.Errorf("couln't find a email password match")
 	}
diff --git a/taskmgr/storage/task_store_db.go b/taskmgr/storage/task_store_db.go
index b8ede6a..03be12d 100644
--- a/taskmgr/storage/task_store_db.go
+++ b/taskmgr/storage/task_store_db.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"fmt"
 	"log"
+	"time"
 
 	"github.com/google/uuid"
 	"github.com/jackc/pgx/v5"
@@ -21,7 +22,10 @@ func (db *TaskStore) GetOne(id string) (*task.Task, error) {
 	t := task.Task{}
 	var author string
 
-	row := db.Conn.QueryRow(context.Background(), query).Scan(&t.ID, &t.Title, &t.Desc, &author)
+	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
+
+	row := db.Conn.QueryRow(ctx, query).Scan(&t.ID, &t.Title, &t.Desc, &author)
 	if row == pgx.ErrNoRows {
 		return nil, fmt.Errorf("task not found")
 	}
@@ -33,7 +37,10 @@ func (db *TaskStore) GetTasks() []*task.Task {
 	var fetchedTasks []*task.Task
 	query := "SELECT * FROM task"
 
-	rows, err := db.Conn.Query(context.Background(), query)
+	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
+
+	rows, err := db.Conn.Query(ctx, query)
 	if err != nil {
 		log.Printf("Error to query: %v", err)
 		return nil
@@ -59,28 +66,35 @@ func (db *TaskStore) New(task *task.Task) uuid.UUID {
 	query := "SELECT id FROM author WHERE email = 'marco@rossi.com';"
 	var authorID string
 
-	err := db.Conn.QueryRow(context.Background(), query).Scan(&authorID)
+	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
+
+	err := db.Conn.QueryRow(ctx, query).Scan(&authorID)
 	if err == pgx.ErrNoRows {
 		log.Printf("Couldn't find a match: %v", err)
 	}
 
+	ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
+
 	query = fmt.Sprintf("INSERT INTO task (title, description, author_id) VALUES ('%s', '%s', '%s');", task.Title, task.Desc, authorID)
-	_, err = db.Conn.Exec(context.Background(), query)
+	_, err = db.Conn.Exec(ctx, query)
 	if err != nil {
 		log.Printf("Could not insert new record into the database %v", err)
 		return uuid.Nil
 	}
 
-	var taskID uuid.UUID
+	ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
 
 	query = fmt.Sprintf("SELECT id FROM task WHERE title = '%s'", task.Title)
-
-	err = db.Conn.QueryRow(context.Background(), query).Scan(&taskID)
+  
+	err = db.Conn.QueryRow(ctx, query).Scan(&task.ID)
 	if err == pgx.ErrNoRows {
-		log.Printf("Couldn't find new task ID: %v", err)
+		log.Printf("Couldn't find a match: %v", err)
 	}
 
-	return taskID
+	return task.ID
 }
 
 func (db *TaskStore) Update(id, title, desc string) (*task.Task, error) {
@@ -91,7 +105,10 @@ func (db *TaskStore) Update(id, title, desc string) (*task.Task, error) {
 
 	query := fmt.Sprintf(`UPDATE task SET title = '%s', description = '%s' WHERE id = '%s';`, title, desc, id)
 
-	update, err := db.Conn.Exec(context.Background(), query)
+	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
+
+	update, err := db.Conn.Exec(ctx, query)
 	if err != nil {
 		return nil, fmt.Errorf("error updating task with ID %s with error %v", id, err)
 	}
@@ -104,7 +121,10 @@ func (db *TaskStore) Update(id, title, desc string) (*task.Task, error) {
 
 	var updatedTask task.Task
 
-	err = db.Conn.QueryRow(context.Background(), query).Scan(&updatedTask.ID, &updatedTask.Title, &updatedTask.Desc, &updatedTask.AuthorID)
+	ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
+
+	err = db.Conn.QueryRow(ctx, query).Scan(&updatedTask.ID, &updatedTask.Title, &updatedTask.Desc, &updatedTask.AuthorID)
 	if err != nil {
 		return nil, fmt.Errorf("error querying updated task: %v", err)
 	}
@@ -120,7 +140,10 @@ func (db *TaskStore) Delete(id string) error {
 
 	query := fmt.Sprintf("DELETE FROM task WHERE id = '%s';", id)
 
-	del, err := db.Conn.Exec(context.Background(), query)
+	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
+
+	del, err := db.Conn.Exec(ctx, query)
 	if err != nil {
 		return fmt.Errorf("error deleting task with ID %v with error %v", id, err)
 	}
@@ -137,7 +160,10 @@ func (db *TaskStore) BulkImport(tasks []*task.Task) {
 	for _, t := range tasks {
 		query := fmt.Sprintf("INSERT INTO task (title, description) VALUES ('%s', '%s');", t.Title, t.Desc)
 
-		_, err := db.Conn.Exec(context.Background(), query)
+		ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+		defer cancel()
+
+		_, err := db.Conn.Exec(ctx, query)
 		if err != nil {
 			log.Printf("%v", err)
 		}


Reviews:
user: login: MrShanks
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-20T17:23:55Z
user: login: MrShanks
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-20T17:25:57Z
user: login: MrShanks
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-20T19:54:06Z
user: login: MrShanks
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-21T16:24:00Z
user: login: MrShanks
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-21T16:24:39Z
user: login: MrShanks
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-21T16:24:58Z
user: login: MrShanks
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-21T16:25:09Z
user: login: MrShanks
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-21T16:25:17Z
user: login: MrShanks
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-21T16:25:43Z
user: login: MrShanks
body: I approve because there is nothing wrong with it but take a look at the comment I left.
state: APPROVED
author_association: OWNER
submitted_at: 2025-03-21T16:33:12Z

Review comments:
diff_hunk: @@ -34,14 +34,30 @@ func ConnectDB(dbURL string) (*pgx.Conn, error) {
 	password := os.Getenv("POSTGRES_PWD")
 	dburl := fmt.Sprintf(dbURL, password)
 
-	var err error
+	ctxConnection, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
 
-	conn, err := pgx.Connect(context.Background(), dburl)
-	if err != nil {
+	chConn := make(chan *pgx.Conn)
+	chErr := make(chan error)
+	go func() {
+		conn, err := pgx.Connect(ctxConnection, dburl)
+		if err != nil {
+			chErr <- err
+			return
+		}
+		chConn <- conn
+	}()
+
+	select {
+	case conn := <-chConn:
+		fmt.Printf("connection established\n")
+		return conn, nil
+	case err := <-chErr:
+		fmt.Printf("connection failed: ")
 		return nil, err
+	case <-ctxConnection.Done():
+		return nil, fmt.Errorf("timeout reached: %v", ctxConnection.Err())
path: taskmgr/server/server.go
user: login: MrShanks
body: why is all this needed?
created_at: 2025-03-20T17:23:48Z
author_association: OWNER
diff_hunk: @@ -34,14 +34,30 @@ func ConnectDB(dbURL string) (*pgx.Conn, error) {
 	password := os.Getenv("POSTGRES_PWD")
 	dburl := fmt.Sprintf(dbURL, password)
 
-	var err error
+	ctxConnection, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
 
-	conn, err := pgx.Connect(context.Background(), dburl)
-	if err != nil {
+	chConn := make(chan *pgx.Conn)
+	chErr := make(chan error)
+	go func() {
+		conn, err := pgx.Connect(ctxConnection, dburl)
+		if err != nil {
+			chErr <- err
+			return
+		}
+		chConn <- conn
+	}()
+
+	select {
+	case conn := <-chConn:
+		fmt.Printf("connection established\n")
+		return conn, nil
+	case err := <-chErr:
+		fmt.Printf("connection failed: ")
 		return nil, err
+	case <-ctxConnection.Done():
+		return nil, fmt.Errorf("timeout reached: %v", ctxConnection.Err())
path: taskmgr/server/server.go
user: login: MrShanks
body: from what I can see here, you are starting a go routine that starts a connection and when that connection is done yout fetch it from the channel and return. Do you expect multiple connection to be queue in that channel? or what is the idea behind this? I might be missing the reason you did such a thing
created_at: 2025-03-20T17:25:56Z
author_association: OWNER
diff_hunk: @@ -34,14 +34,30 @@ func ConnectDB(dbURL string) (*pgx.Conn, error) {
 	password := os.Getenv("POSTGRES_PWD")
 	dburl := fmt.Sprintf(dbURL, password)
 
-	var err error
+	ctxConnection, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+	defer cancel()
 
-	conn, err := pgx.Connect(context.Background(), dburl)
-	if err != nil {
+	chConn := make(chan *pgx.Conn)
+	chErr := make(chan error)
+	go func() {
+		conn, err := pgx.Connect(ctxConnection, dburl)
+		if err != nil {
+			chErr <- err
+			return
+		}
+		chConn <- conn
+	}()
+
+	select {
+	case conn := <-chConn:
+		fmt.Printf("connection established\n")
+		return conn, nil
+	case err := <-chErr:
+		fmt.Printf("connection failed: ")
 		return nil, err
+	case <-ctxConnection.Done():
+		return nil, fmt.Errorf("timeout reached: %v", ctxConnection.Err())
path: taskmgr/server/server.go
user: login: MrShanks
body: basically if this all section is there or you remove it, nothing changes, am I wrong?
created_at: 2025-03-20T19:54:06Z
author_association: OWNER
diff_hunk: @@ -57,7 +58,10 @@ func TestDelTask(t *testing.T) {
 				HttpClient: mockClient,
 			}
 
-			got := delTask(taskcli, context.Background(), "/delete", "notoken")
+			ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+			defer cancel()
+
+			got := delTask(taskcli, ctx, "/delete", "notoken")
path: taskcli/cmd/del_test.go
user: login: MrShanks
body: I'm not sure having a real context with timeout in the test actually make sense, here we are moking the server response we don't really utilize a real server, I think I would keep it simple and use just a place holder context.Background()
created_at: 2025-03-21T16:23:59Z
author_association: OWNER
diff_hunk: @@ -31,7 +32,10 @@ func TestNewTaskHandler(t *testing.T) {
 	// Act
 	handler := NewTaskHandler(&mockDatabase)
 
-	request, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, "/new", bytes.NewBuffer(body))
+	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+	defer cancel()
+
+	request, _ := http.NewRequestWithContext(ctx, http.MethodPost, "/new", bytes.NewBuffer(body))
path: taskmgr/server/handler_test.go
user: login: MrShanks
body: same here
created_at: 2025-03-21T16:24:39Z
author_association: OWNER
diff_hunk: @@ -63,7 +67,10 @@ func TestGetTasksHandler(t *testing.T) {
 		// Act
 		handler := GetAllTasksHandler(&IMD)
 
-		request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/tasks", nil)
+		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+		defer cancel()
+
+		request, err := http.NewRequestWithContext(ctx, http.MethodGet, "/tasks", nil)
path: taskmgr/server/handler_test.go
user: login: MrShanks
body: same here
created_at: 2025-03-21T16:24:58Z
author_association: OWNER
diff_hunk: @@ -101,7 +108,10 @@ func TestUpdateTaskHandler(t *testing.T) {
 		body := &bytes.Buffer{}
 		body.Write([]byte(`{"title":"new title","desc":"new description"}`))
 
-		request, err := http.NewRequestWithContext(context.Background(), http.MethodPut, fmt.Sprintf("/update/%s", task1.ID), body)
+		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+		defer cancel()
+
+		request, err := http.NewRequestWithContext(ctx, http.MethodPut, fmt.Sprintf("/update/%s", task1.ID), body)
path: taskmgr/server/handler_test.go
user: login: MrShanks
body: same here
created_at: 2025-03-21T16:25:08Z
author_association: OWNER
diff_hunk: @@ -133,7 +143,10 @@ func TestGeneralHandler(t *testing.T) {
 
 	for _, test := range tests {
 		t.Run(test.desc, func(t *testing.T) {
-			request, err := http.NewRequestWithContext(context.Background(), "GET", test.endpoint, nil)
+			ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+			defer cancel()
+
+			request, err := http.NewRequestWithContext(ctx, "GET", test.endpoint, nil)
path: taskmgr/server/handler_test.go
user: login: MrShanks
body: same here
created_at: 2025-03-21T16:25:17Z
author_association: OWNER
diff_hunk: @@ -40,7 +41,10 @@ func TestFetch(t *testing.T) {
 			ServerURL:  *serverURL,
 		}
 
-		got := FetchTasks(mockClient, context.Background(), "/tasks", "token")
+		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+		defer cancel()
+
+		got := FetchTasks(mockClient, ctx, "/tasks", "token")
path: taskcli/cmd/get_test.go
user: login: MrShanks
body: same here
created_at: 2025-03-21T16:25:43Z
author_association: OWNER

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-03-21T20:27:24Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=MrShanks_Taska&pullRequest=36) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=MrShanks_Taska&pullRequest=36&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=MrShanks_Taska&pullRequest=36&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=MrShanks_Taska&pullRequest=36&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=MrShanks_Taska&pullRequest=36&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=MrShanks_Taska&pullRequest=36&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=MrShanks_Taska&pullRequest=36)


author_association: NONE