Skip to content

Commit

Permalink
pkg/project: stop lsp when deleting project (#128)
Browse files Browse the repository at this point in the history
* pkg/project: stop lsp when deleting project

* pkg/project: refactor DeleteProject
  • Loading branch information
artmoskvin authored Oct 6, 2024
1 parent 6f9fda6 commit 9d57ec0
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 62 deletions.
8 changes: 3 additions & 5 deletions pkg/handlers/delete_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
21 changes: 7 additions & 14 deletions pkg/handlers/delete_project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,47 +10,40 @@ 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"
)

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: "",
},
{
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",
},
{
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",
Expand Down
66 changes: 25 additions & 41 deletions pkg/project/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/project/mocks/mock_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
}

Expand Down

0 comments on commit 9d57ec0

Please sign in to comment.