Skip to content

Commit

Permalink
Start making each check run in parallel
Browse files Browse the repository at this point in the history
  • Loading branch information
mcasperson committed Oct 8, 2024
1 parent 6ee85ed commit b31ad57
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 25 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.22.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hayageek/threadsafe v1.0.1 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
Expand All @@ -161,6 +163,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hayageek/threadsafe v1.0.1 h1:QTMJrninAaGQE7+CYdJWPzTlnhcBPwhxD5GDdvIf5oU=
github.com/hayageek/threadsafe v1.0.1/go.mod h1:Uhu/endHEMkw2SsIk1I4xYTGTnWvuGhWOBPIFWO+mPk=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kinbiko/jsonassert v1.1.1 h1:DB12divY+YB+cVpHULLuKePSi6+ui4M/shHSzJISkSE=
github.com/kinbiko/jsonassert v1.1.1/go.mod h1:NO4lzrogohtIdNUNzx8sdzB55M4R4Q1bsrWVdqQ7C+A=
Expand Down
75 changes: 50 additions & 25 deletions internal/checks/organization/octopus_unused_projects_check.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package organization

import (
"context"
"errors"
"fmt"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/tasks"
"github.com/OctopusSolutionsEngineering/OctopusRecommendationEngine/internal/checks"
"github.com/OctopusSolutionsEngineering/OctopusRecommendationEngine/internal/client_wrapper"
"github.com/OctopusSolutionsEngineering/OctopusRecommendationEngine/internal/config"
"github.com/OctopusSolutionsEngineering/OctopusRecommendationEngine/internal/executor"
"github.com/hayageek/threadsafe"
"go.uber.org/zap"
"golang.org/x/sync/errgroup"
"strings"
"time"
)
Expand Down Expand Up @@ -52,44 +56,65 @@ func (o OctopusUnusedProjectsCheck) Execute() (checks.OctopusCheckResult, error)
return o.errorHandler.HandleError(o.Id(), checks.Organization, err)
}

unusedProjects := []string{}
g, _ := errgroup.WithContext(context.Background())
g.SetLimit(executor.CheckParallelTasks)

unusedProjects := threadsafe.NewSlice[string]()
goroutineErrors := threadsafe.NewSlice[error]()

for i, project := range projects {
zap.L().Debug(o.Id() + " " + fmt.Sprintf("%.2f", float32(i+1)/float32(len(projects))*100) + "% complete")
i := i

// Ignore disabled projects
if project.IsDisabled {
continue
}
g.Go(func() error {
zap.L().Debug(o.Id() + " " + fmt.Sprintf("%.2f", float32(i+1)/float32(len(projects))*100) + "% complete")

projectHasTask := false
// Ignore disabled projects
if project.IsDisabled {
return nil
}

tasks, err := o.client.Tasks.Get(tasks.TasksQuery{
Project: project.ID,
Skip: 0,
Take: 100,
})
projectHasTask := false

if err != nil {
return o.errorHandler.HandleError(o.Id(), checks.Organization, err)
}
tasks, err := o.client.Tasks.Get(tasks.TasksQuery{
Project: project.ID,
Skip: 0,
Take: 100,
})

for _, task := range tasks.Items {
if task.StartTime != nil && task.StartTime.After(time.Now().Add(-time.Hour*24*time.Duration(o.config.MaxDaysSinceLastTask))) {
projectHasTask = true
break
if err != nil {
goroutineErrors.Append(err)
return nil
}
}

if !projectHasTask {
unusedProjects = append(unusedProjects, project.Name)
}
for _, task := range tasks.Items {
if task.StartTime != nil && task.StartTime.After(time.Now().Add(-time.Hour*24*time.Duration(o.config.MaxDaysSinceLastTask))) {
projectHasTask = true
break
}
}

if !projectHasTask {
unusedProjects.Append(project.Name)
}

return nil
})
}

if err := g.Wait(); err != nil {
return nil, err
}

// Treat the first error as the root cause
if goroutineErrors.Length() > 0 {
return o.errorHandler.HandleError(o.Id(), checks.Organization, goroutineErrors.Values()[0])
}

daysString := fmt.Sprintf("%d", o.config.MaxDaysSinceLastTask)

if len(unusedProjects) > 0 {
if unusedProjects.Length() > 0 {
return checks.NewOctopusCheckResultImpl(
"The following projects have not had any tasks in "+daysString+" days:\n"+strings.Join(unusedProjects, "\n"),
"The following projects have not had any tasks in "+daysString+" days:\n"+strings.Join(unusedProjects.Values(), "\n"),
o.Id(),
"",
checks.Warning,
Expand Down
1 change: 1 addition & 0 deletions internal/executor/octopus_check_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
)

const ParallelTasks = 15
const CheckParallelTasks = 2

// OctopusCheckExecutor is responsible for running each lint check and returning the results. It deals with things
// like retries and error handling.
Expand Down

0 comments on commit b31ad57

Please sign in to comment.