Chore: use package function to replace parallel function (#6052)

This commit is contained in:
Somefive
2023-05-31 14:01:30 +08:00
committed by GitHub
parent 1c0f2c4c7d
commit 04cd510ddc
4 changed files with 10 additions and 244 deletions
+7 -7
View File
@@ -25,6 +25,7 @@ import (
"sync"
"github.com/gosuri/uitable/util/wordwrap"
velaslices "github.com/kubevela/pkg/util/slices"
"github.com/xlab/treeprint"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
@@ -38,7 +39,6 @@ import (
"github.com/oam-dev/kubevela/pkg/multicluster"
"github.com/oam-dev/kubevela/pkg/utils"
velaerrors "github.com/oam-dev/kubevela/pkg/utils/errors"
"github.com/oam-dev/kubevela/pkg/utils/parallel"
)
// PrivilegeInfo describes one privilege in Kubernetes. Either one ClusterRole or
@@ -82,15 +82,15 @@ type RoleBindingRef authObjRef
// ListPrivileges retrieve privilege information in specified clusters
func ListPrivileges(ctx context.Context, cli client.Client, clusters []string, identity *Identity) (map[string][]PrivilegeInfo, error) {
var m sync.Map
errs := parallel.Run(func(cluster string) error {
errs := velaslices.ParMap(clusters, func(cluster string) error {
info, err := listPrivilegesInCluster(ctx, cli, cluster, identity)
if err != nil {
return err
}
m.Store(cluster, info)
return nil
}, clusters, parallel.DefaultParallelism)
if err := velaerrors.AggregateErrors(errs.([]error)); err != nil {
})
if err := velaerrors.AggregateErrors(errs); err != nil {
return nil, err
}
privilegesMap := make(map[string][]PrivilegeInfo)
@@ -147,7 +147,7 @@ func listPrivilegesInCluster(ctx context.Context, cli client.Client, cluster str
infos = append(infos, PrivilegeInfo{RoleRef: roleRef, RoleBindingRefs: roleBindingRefs})
}
var m sync.Map
errs := parallel.Run(func(info PrivilegeInfo) error {
errs := velaslices.ParMap(infos, func(info PrivilegeInfo) error {
key := types.NamespacedName{Namespace: info.RoleRef.Namespace, Name: info.RoleRef.Name}
var rules []rbacv1.PolicyRule
if info.RoleRef.Kind == "Role" {
@@ -165,8 +165,8 @@ func listPrivilegesInCluster(ctx context.Context, cli client.Client, cluster str
}
m.Store(authObjRef(info.RoleRef).FullName(), rules)
return nil
}, infos, parallel.DefaultParallelism)
if err := velaerrors.AggregateErrors(errs.([]error)); err != nil {
})
if err := velaerrors.AggregateErrors(errs); err != nil {
return nil, err
}
for i, info := range infos {
+3 -4
View File
@@ -33,7 +33,6 @@ import (
"github.com/oam-dev/kubevela/pkg/resourcetracker"
"github.com/oam-dev/kubevela/pkg/utils/apply"
velaerrors "github.com/oam-dev/kubevela/pkg/utils/errors"
"github.com/oam-dev/kubevela/pkg/utils/parallel"
)
// MaxDispatchConcurrent is the max dispatch concurrent number
@@ -145,7 +144,7 @@ func (h *resourceKeeper) record(ctx context.Context, manifests []*unstructured.U
}
func (h *resourceKeeper) dispatch(ctx context.Context, manifests []*unstructured.Unstructured, applyOpts []apply.ApplyOption) error {
errs := parallel.Run(func(manifest *unstructured.Unstructured) error {
errs := velaslices.ParMap(manifests, func(manifest *unstructured.Unstructured) error {
applyCtx := multicluster.ContextWithClusterName(ctx, oam.GetCluster(manifest))
applyCtx = auth.ContextWithUserInfo(applyCtx, h.app)
ao := applyOpts
@@ -166,6 +165,6 @@ func (h *resourceKeeper) dispatch(ctx context.Context, manifests []*unstructured
return errors.Wrapf(err, "failed to apply once policy for application %s,%s", h.app.Name, err.Error())
}
return h.applicator.Apply(applyCtx, manifest, ao...)
}, manifests, MaxDispatchConcurrent)
return velaerrors.AggregateErrors(errs.([]error))
}, velaslices.Parallelism(MaxDispatchConcurrent))
return velaerrors.AggregateErrors(errs)
}
-132
View File
@@ -1,132 +0,0 @@
/*
Copyright 2021 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package parallel
import (
"reflect"
)
const (
// DefaultParallelism default parallelism
DefaultParallelism int = 5
)
// ParInput input for parallel execution
type ParInput interface{}
// ParOutput output for parallel execution
type ParOutput interface{}
type orderedParOutput struct {
ParOutput
index int
}
// RunBatch parallel execute handler function on parInputs, with maximum concurrency as parallelism
func RunBatch(handler func(ParInput) ParOutput, parInputs []ParInput, parallelism int) []ParOutput {
outs := make(chan orderedParOutput)
pool := make(chan struct{}, parallelism)
for _idx, _input := range parInputs {
go func(idx int, input ParInput) {
pool <- struct{}{}
output := handler(input)
outs <- orderedParOutput{ParOutput: output, index: idx}
<-pool
}(_idx, _input)
}
outputs := make([]ParOutput, len(parInputs))
for range parInputs {
out := <-outs
outputs[out.index] = out.ParOutput
}
close(outs)
close(pool)
return outputs
}
// Run execute handler on parInputs, with automatic type conversion and maximum concurrency as parallelism
// Examples:
// > out := Run(func(x int) int { return x*x }, []int{1,2,3,4,5}, 5)
// < out: []int{1,4,19,16,25}
// > out := Run(func(x int, y string) (string, bool) { return y, x%2==0 }, [][]interface{}{{1,"n"},{2,"y"}}, 2)
// < out: [][]interface{{"n",false},{"y",true}}
func Run(handler interface{}, parInputs interface{}, parallelism int) interface{} {
parInputsVal := reflect.ValueOf(parInputs)
elemLen := parInputsVal.Len()
_parInputVal := reflect.MakeSlice(reflect.TypeOf([]ParInput{}), elemLen, elemLen)
for i := 0; i < elemLen; i++ {
v := parInputsVal.Index(i)
if v.IsValid() {
_parInputVal.Index(i).Set(v)
}
}
handleFunc := reflect.ValueOf(handler)
handleFuncTyp := reflect.TypeOf(handler)
nParams, nReturns := handleFuncTyp.NumIn(), handleFuncTyp.NumOut()
parOutputTyp := reflect.TypeOf([]ParOutput{}).Elem()
_handler := reflect.MakeFunc(reflect.TypeOf(func(ParInput) ParOutput { return nil }), func(args []reflect.Value) (results []reflect.Value) {
in := make([]reflect.Value, nParams)
_inputVal := args[0].Elem()
if nParams > 1 {
for i := 0; i < nParams; i++ {
in[i] = _inputVal.Index(i).Elem()
}
} else if nParams == 1 {
in[0] = _inputVal
}
for i := 0; i < nParams; i++ {
if !in[i].IsValid() {
in[i] = reflect.New(handleFuncTyp.In(i)).Elem()
}
}
out := handleFunc.Call(in)
_outputVal := reflect.New(parOutputTyp).Elem()
if nReturns > 1 {
ret := reflect.MakeSlice(reflect.TypeOf([]interface{}{}), nReturns, nReturns)
for i := 0; i < nReturns; i++ {
if out[i].IsValid() {
ret.Index(i).Set(out[i])
}
}
_outputVal.Set(ret)
} else if nReturns == 1 {
if out[0].IsValid() {
_outputVal.Set(out[0])
}
}
return []reflect.Value{_outputVal}
})
outs := RunBatch(_handler.Interface().(func(ParInput) ParOutput), _parInputVal.Interface().([]ParInput), parallelism)
if nReturns == 0 {
return nil
}
var outputs reflect.Value
if nReturns == 1 {
outputs = reflect.MakeSlice(reflect.SliceOf(handleFuncTyp.Out(0)), elemLen, elemLen)
} else {
outputs = reflect.MakeSlice(reflect.TypeOf([]interface{}{}), elemLen, elemLen)
}
for i := 0; i < elemLen; i++ {
v := reflect.ValueOf(outs[i])
if v.IsValid() {
outputs.Index(i).Set(v)
}
}
return outputs.Interface()
}
-101
View File
@@ -1,101 +0,0 @@
/*
Copyright 2021 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package parallel
import (
"math"
"math/rand"
"testing"
"time"
"github.com/stretchr/testify/require"
"k8s.io/utils/pointer"
)
func TestParExecNto1(t *testing.T) {
var inputs [][]interface{}
size := 100
parallelism := 20
for i := 0; i < size; i++ {
if i%2 == 0 {
inputs = append(inputs, []interface{}{i, i + 1, math.Sqrt(float64(i)), nil})
} else {
inputs = append(inputs, []interface{}{i, i + 1, math.Sqrt(float64(i)), pointer.Int(i)})
}
}
outs := Run(func(a int, b int, c float64, d *int) *float64 {
time.Sleep(time.Duration(rand.Intn(200)+25) * time.Millisecond)
if d == nil {
return nil
}
return pointer.Float64(float64(a*b) + c + float64(*d))
}, inputs, parallelism)
outputs, ok := outs.([]*float64)
r := require.New(t)
r.True(ok)
r.Equal(size, len(outputs))
for i, j := range outputs {
if i%2 == 0 {
r.Nil(j)
} else {
r.NotNil(j)
r.Equal(float64(i*(i+1))+math.Sqrt(float64(i))+float64(i), *j)
}
}
}
func TestParExec0toN(t *testing.T) {
var inputs [][]interface{}
size := 100
parallelism := 20
for i := 0; i < size; i++ {
inputs = append(inputs, nil)
}
outs := Run(func() (bool, string) {
time.Sleep(time.Duration(rand.Intn(200)+25) * time.Millisecond)
return false, "ok"
}, inputs, parallelism)
outputs, ok := outs.([]interface{})
r := require.New(t)
r.True(ok)
r.Equal(size, len(outputs))
for _, _j := range outputs {
j, ok := _j.([]interface{})
r.True(ok)
r.Equal(2, len(j))
j0, ok := j[0].(bool)
r.True(ok)
r.False(j0)
j1, ok := j[1].(string)
r.True(ok)
r.Equal("ok", j1)
}
}
func TestParExec1to0(t *testing.T) {
var inputs []struct{ key int }
size := 100
parallelism := 20
for i := 0; i < size; i++ {
inputs = append(inputs, struct{ key int }{key: i})
}
outs := Run(func(obj struct{ key int }) {
time.Sleep(time.Duration(rand.Intn(50)+size-obj.key) * time.Millisecond)
}, inputs, parallelism)
r := require.New(t)
r.Nil(outs)
}