From 2da7ddc39971f41bfa761466b43511a61ef2ed32 Mon Sep 17 00:00:00 2001 From: Pete Davison Date: Sat, 14 Jan 2023 13:45:52 -0600 Subject: [PATCH] chore: optimize task filtering (#982) --- help.go | 9 +++++--- task.go | 71 ++++++++++++++++++++++++++------------------------------- 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/help.go b/help.go index 15a51fed..d0eca8f9 100644 --- a/help.go +++ b/help.go @@ -51,10 +51,10 @@ func (o ListOptions) Validate() error { // Filters returns the slice of FilterFunc which filters a list // of taskfile.Task according to the given ListOptions func (o ListOptions) Filters() []FilterFunc { - filters := []FilterFunc{FilterOutInternal()} + filters := []FilterFunc{FilterOutInternal} if o.ListOnlyTasksWithDescriptions { - filters = append(filters, FilterOutNoDesc()) + filters = append(filters, FilterOutNoDesc) } return filters @@ -65,7 +65,10 @@ func (o ListOptions) Filters() []FilterFunc { // The function returns a boolean indicating whether tasks were found // and an error if one was encountered while preparing the output. func (e *Executor) ListTasks(o ListOptions) (bool, error) { - tasks := e.GetTaskList(o.Filters()...) + tasks, err := e.GetTaskList(o.Filters()...) + if err != nil { + return false, err + } if o.FormatTaskListAsJSON { output, err := e.ToEditorOutput(tasks) if err != nil { diff --git a/task.go b/task.go index 4c774d4c..7a0d3ffd 100644 --- a/task.go +++ b/task.go @@ -400,23 +400,39 @@ func (e *Executor) GetTask(call taskfile.Call) (*taskfile.Task, error) { return matchingTask, nil } -type FilterFunc func(tasks []*taskfile.Task) []*taskfile.Task +type FilterFunc func(task *taskfile.Task) bool -func (e *Executor) GetTaskList(filters ...FilterFunc) []*taskfile.Task { +func (e *Executor) GetTaskList(filters ...FilterFunc) ([]*taskfile.Task, error) { tasks := make([]*taskfile.Task, 0, len(e.Taskfile.Tasks)) + // Create an error group to wait for each task to be compiled + var g errgroup.Group + // Fetch and compile the list of tasks - for _, task := range e.Taskfile.Tasks { - compiledTask, err := e.FastCompiledTask(taskfile.Call{Task: task.Task}) - if err == nil { - task = compiledTask - } - tasks = append(tasks, task) + for key := range e.Taskfile.Tasks { + task := e.Taskfile.Tasks[key] + g.Go(func() error { + + // Check if we should filter the task + for _, filter := range filters { + if filter(task) { + return nil + } + } + + // Compile the task + compiledTask, err := e.FastCompiledTask(taskfile.Call{Task: task.Task}) + if err == nil { + task = compiledTask + } + tasks = append(tasks, task) + return nil + }) } - // Filter the tasks - for _, filter := range filters { - tasks = filter(tasks) + // Wait for all the go routines to finish + if err := g.Wait(); err != nil { + return nil, err } // Sort the tasks. @@ -434,40 +450,17 @@ func (e *Executor) GetTaskList(filters ...FilterFunc) []*taskfile.Task { return false }) - return tasks -} - -// Filter is a generic task filtering function. It will remove each task in the -// slice where the result of the given function is true. -func Filter(f func(task *taskfile.Task) bool) FilterFunc { - return func(tasks []*taskfile.Task) []*taskfile.Task { - shift := 0 - for _, task := range tasks { - if !f(task) { - tasks[shift] = task - shift++ - } - } - // This loop stops any memory leaks - for j := shift; j < len(tasks); j++ { - tasks[j] = nil - } - return slices.Clip(tasks[:shift]) - } + return tasks, nil } // FilterOutNoDesc removes all tasks that do not contain a description. -func FilterOutNoDesc() FilterFunc { - return Filter(func(task *taskfile.Task) bool { - return task.Desc == "" - }) +func FilterOutNoDesc(task *taskfile.Task) bool { + return task.Desc == "" } // FilterOutInternal removes all tasks that are marked as internal. -func FilterOutInternal() FilterFunc { - return Filter(func(task *taskfile.Task) bool { - return task.Internal - }) +func FilterOutInternal(task *taskfile.Task) bool { + return task.Internal } func shouldRunOnCurrentPlatform(platforms []*taskfile.Platform) bool {