Skip to content

Commit

Permalink
feat: delete resources in batches of 10
Browse files Browse the repository at this point in the history
  • Loading branch information
jooola committed Jun 19, 2024
1 parent a8a61ca commit aa01744
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 32 deletions.
70 changes: 38 additions & 32 deletions internal/cmd/base/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"strings"
"sync"

"github.com/spf13/cobra"

Expand Down Expand Up @@ -53,48 +52,55 @@ func (dc *DeleteCmd) CobraCommand(s state.State) *cobra.Command {

// Run executes a delete command.
func (dc *DeleteCmd) Run(s state.State, cmd *cobra.Command, args []string) error {
errs := make([]error, 0, len(args))
deleted := make([]string, 0, len(args))

wg := sync.WaitGroup{}
wg.Add(len(args))
actions, errs :=
make([]*hcloud.Action, len(args)),
make([]error, len(args))
for _, batch := range util.Batches(args, 10) {
results := make([]util.ResourceState, len(batch))
actions := make([]*hcloud.Action, 0, len(batch))

for i, idOrName := range batch {
results[i] = util.ResourceState{IDOrName: idOrName}

for i, idOrName := range args {
i, idOrName := i, idOrName
go func() {
defer wg.Done()
resource, _, err := dc.Fetch(s, cmd, idOrName)
if err != nil {
errs[i] = err
return
results[i].Error = err
continue
}
if util.IsNil(resource) {
errs[i] = fmt.Errorf("%s not found: %s", dc.ResourceNameSingular, idOrName)
return
results[i].Error = fmt.Errorf("%s not found: %s", dc.ResourceNameSingular, idOrName)
continue
}
actions[i], errs[i] = dc.Delete(s, cmd, resource)
}()
}

wg.Wait()
filtered := util.FilterNil(actions)
var err error
if len(filtered) > 0 {
err = s.WaitForActions(cmd, s, filtered...)
}
action, err := dc.Delete(s, cmd, resource)
if err != nil {
results[i].Error = err
continue
}
if action != nil {
actions = append(actions, action)
}
}

if len(actions) > 0 {
// TODO: We do not check when an action fail for a specific resource
if err := s.WaitForActions(cmd, s, actions...); err != nil {
errs = append(errs, err)
}
}

var actuallyDeleted []string
for i, idOrName := range args {
if errs[i] == nil {
actuallyDeleted = append(actuallyDeleted, idOrName)
for _, result := range results {
if result.Error == nil {
deleted = append(deleted, result.IDOrName)
}
}
}

if len(actuallyDeleted) == 1 {
cmd.Printf("%s %s deleted\n", dc.ResourceNameSingular, actuallyDeleted[0])
} else if len(actuallyDeleted) > 1 {
cmd.Printf("%s %s deleted\n", dc.ResourceNamePlural, strings.Join(actuallyDeleted, ", "))
if len(deleted) == 1 {
cmd.Printf("%s %s deleted\n", dc.ResourceNameSingular, deleted[0])
} else if len(deleted) > 1 {
cmd.Printf("%s %s deleted\n", dc.ResourceNamePlural, strings.Join(deleted, ", "))
}
return errors.Join(append(errs, err)...)

return errors.Join(errs...)
}
6 changes: 6 additions & 0 deletions internal/cmd/util/resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package util

type ResourceState struct {
IDOrName string
Error error
}
8 changes: 8 additions & 0 deletions internal/cmd/util/slices.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package util

func Batches[T any](all []T, size int) (batches [][]T) {
for size < len(all) {
all, batches = all[size:], append(batches, all[:size])
}
return append(batches, all)
}
17 changes: 17 additions & 0 deletions internal/cmd/util/slices_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package util

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestBatches(t *testing.T) {
all := []int{1, 2, 3, 4, 5}
batches := Batches(all, 2)

assert.Len(t, batches, 3)
assert.Equal(t, []int{1, 2}, batches[0])
assert.Equal(t, []int{3, 4}, batches[1])
assert.Equal(t, []int{5}, batches[2])
}

0 comments on commit aa01744

Please sign in to comment.