diff --git a/pkg/handlers/delete_project.go b/pkg/handlers/delete_project.go index 549900c7..c2d2d7d5 100644 --- a/pkg/handlers/delete_project.go +++ b/pkg/handlers/delete_project.go @@ -19,16 +19,14 @@ func (h DeleteProjectHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) return } - result := <-h.Manager.DeleteProject(r.Context(), projectID) - - if result.IsFailure() { + if err := h.Manager.DeleteProject(r.Context(), projectID); err != nil { var projectNotFoundError *project.ProjectNotFoundError - if errors.As(result.Error, &projectNotFoundError) { + if errors.As(err, &projectNotFoundError) { http.Error(w, projectNotFoundError.Error(), http.StatusNotFound) return } - http.Error(w, fmt.Sprintf("Failed to delete project: %s", result.Error), http.StatusInternalServerError) + http.Error(w, fmt.Sprintf("Failed to delete project: %s", err), http.StatusInternalServerError) return } diff --git a/pkg/handlers/delete_project_test.go b/pkg/handlers/delete_project_test.go index 2c090588..e37262dd 100644 --- a/pkg/handlers/delete_project_test.go +++ b/pkg/handlers/delete_project_test.go @@ -10,7 +10,6 @@ import ( "github.com/hide-org/hide/pkg/handlers" "github.com/hide-org/hide/pkg/project" "github.com/hide-org/hide/pkg/project/mocks" - "github.com/hide-org/hide/pkg/result" "github.com/stretchr/testify/assert" ) @@ -18,17 +17,15 @@ func TestDeleteProjectHandler_ServeHTTP(t *testing.T) { tests := []struct { name string target string - mockDeleteProjectFunc func(ctx context.Context, projectId string) <-chan result.Empty + mockDeleteProjectFunc func(ctx context.Context, projectId string) error wantStatusCode int wantBody string }{ { name: "successful deletion", target: "/projects/123", - mockDeleteProjectFunc: func(ctx context.Context, projectId string) <-chan result.Empty { - ch := make(chan result.Empty, 1) - ch <- result.EmptySuccess() - return ch + mockDeleteProjectFunc: func(ctx context.Context, projectId string) error { + return nil }, wantStatusCode: http.StatusNoContent, wantBody: "", @@ -36,10 +33,8 @@ func TestDeleteProjectHandler_ServeHTTP(t *testing.T) { { name: "project not found", target: "/projects/123", - mockDeleteProjectFunc: func(ctx context.Context, projectId string) <-chan result.Empty { - ch := make(chan result.Empty, 1) - ch <- result.EmptyFailure(project.NewProjectNotFoundError(projectId)) - return ch + mockDeleteProjectFunc: func(ctx context.Context, projectId string) error { + return project.NewProjectNotFoundError(projectId) }, wantStatusCode: http.StatusNotFound, wantBody: "project 123 not found\n", @@ -47,10 +42,8 @@ func TestDeleteProjectHandler_ServeHTTP(t *testing.T) { { name: "internal server error", target: "/projects/123", - mockDeleteProjectFunc: func(ctx context.Context, projectId string) <-chan result.Empty { - ch := make(chan result.Empty, 1) - ch <- result.EmptyFailure(errors.New("internal error")) - return ch + mockDeleteProjectFunc: func(ctx context.Context, projectId string) error { + return errors.New("internal error") }, wantStatusCode: http.StatusInternalServerError, wantBody: "Failed to delete project: internal error\n", diff --git a/pkg/project/manager.go b/pkg/project/manager.go index ba8f07ae..354779f3 100644 --- a/pkg/project/manager.go +++ b/pkg/project/manager.go @@ -49,7 +49,7 @@ type Manager interface { CreateProject(ctx context.Context, request CreateProjectRequest) <-chan result.Result[model.Project] CreateTask(ctx context.Context, projectId model.ProjectId, command string) (TaskResult, error) DeleteFile(ctx context.Context, projectId, path string) error - DeleteProject(ctx context.Context, projectId model.ProjectId) <-chan result.Empty + DeleteProject(ctx context.Context, projectId model.ProjectId) error GetProject(ctx context.Context, projectId model.ProjectId) (model.Project, error) GetProjects(ctx context.Context) ([]*model.Project, error) ListFiles(ctx context.Context, projectId string, opts ...files.ListFileOption) ([]*model.File, error) @@ -193,37 +193,33 @@ func (pm ManagerImpl) GetProjects(ctx context.Context) ([]*model.Project, error) return projects, nil } -func (pm ManagerImpl) DeleteProject(ctx context.Context, projectId string) <-chan result.Empty { - c := make(chan result.Empty) - - go func() { - log.Debug().Msgf("Deleting project %s", projectId) +func (pm ManagerImpl) DeleteProject(ctx context.Context, projectId string) error { + log.Debug().Msgf("Deleting project %s", projectId) - project, err := pm.GetProject(ctx, projectId) - if err != nil { - log.Error().Err(err).Msgf("Failed to get project with id %s", projectId) - c <- result.EmptyFailure(fmt.Errorf("Failed to get project with id %s: %w", projectId, err)) - return - } + project, err := pm.GetProject(ctx, projectId) + if err != nil { + log.Error().Err(err).Msgf("Failed to get project with id %s", projectId) + return fmt.Errorf("Failed to get project with id %s: %w", projectId, err) + } - if err := pm.devContainerRunner.Stop(ctx, project.ContainerId); err != nil { - log.Error().Err(err).Msgf("Failed to stop container %s", project.ContainerId) - c <- result.EmptyFailure(fmt.Errorf("Failed to stop container: %w", err)) - return - } + if err := pm.devContainerRunner.Stop(ctx, project.ContainerId); err != nil { + log.Error().Err(err).Msgf("Failed to stop container %s", project.ContainerId) + return fmt.Errorf("Failed to stop container: %w", err) + } - if err := pm.store.DeleteProject(projectId); err != nil { - log.Error().Err(err).Msgf("Failed to delete project %s", projectId) - c <- result.EmptyFailure(fmt.Errorf("Failed to delete project: %w", err)) - return - } + if err := pm.lspService.CleanupProject(ctx, projectId); err != nil { + log.Error().Err(err).Str("projectId", projectId).Msg("Failed to stop LSP server(s)") + return fmt.Errorf("Failed to stop LSP server(s): %w", err) + } - log.Debug().Msgf("Deleted project %s", projectId) + if err := pm.store.DeleteProject(projectId); err != nil { + log.Error().Err(err).Msgf("Failed to delete project %s", projectId) + return fmt.Errorf("Failed to delete project: %w", err) + } - c <- result.EmptySuccess() - }() + log.Debug().Msgf("Deleted project %s", projectId) - return c + return nil } func (pm ManagerImpl) ResolveTaskAlias(ctx context.Context, projectId string, alias string) (devcontainer.Task, error) { @@ -282,22 +278,10 @@ func (pm ManagerImpl) Cleanup(ctx context.Context) error { wg.Add(1) go func(p *model.Project) { defer wg.Done() - log.Debug().Msgf("Cleaning up project %s", p.Id) - - if err := pm.devContainerRunner.Stop(ctx, p.ContainerId); err != nil { - errChan <- fmt.Errorf("Failed to stop container for project %s: %w", p.Id, err) - return - } - - if err := pm.lspService.CleanupProject(ctx, p.Id); err != nil { - errChan <- fmt.Errorf("Failed to cleanup LSP for project %s: %w", p.Id, err) - return - } - - if err := pm.store.DeleteProject(p.Id); err != nil { - errChan <- fmt.Errorf("Failed to delete project %s: %w", p.Id, err) - return + if err := pm.DeleteProject(ctx, p.Id); err != nil { + errChan <- err } + return }(project) } diff --git a/pkg/project/mocks/mock_manager.go b/pkg/project/mocks/mock_manager.go index f3e0df0d..323adad9 100644 --- a/pkg/project/mocks/mock_manager.go +++ b/pkg/project/mocks/mock_manager.go @@ -19,7 +19,7 @@ type MockProjectManager struct { CreateProjectFunc func(ctx context.Context, request project.CreateProjectRequest) <-chan result.Result[model.Project] CreateTaskFunc func(ctx context.Context, projectId string, command string) (project.TaskResult, error) DeleteFileFunc func(ctx context.Context, projectId, path string) error - DeleteProjectFunc func(ctx context.Context, projectId string) <-chan result.Empty + DeleteProjectFunc func(ctx context.Context, projectId string) error GetProjectFunc func(ctx context.Context, projectId string) (model.Project, error) GetProjectsFunc func(ctx context.Context) ([]*model.Project, error) ListFilesFunc func(ctx context.Context, projectId string, opts ...files.ListFileOption) ([]*model.File, error) @@ -42,7 +42,7 @@ func (m *MockProjectManager) GetProjects(ctx context.Context) ([]*model.Project, return m.GetProjectsFunc(ctx) } -func (m *MockProjectManager) DeleteProject(ctx context.Context, projectId string) <-chan result.Empty { +func (m *MockProjectManager) DeleteProject(ctx context.Context, projectId string) error { return m.DeleteProjectFunc(ctx, projectId) }