Use go 1.25 waitgroup Go method instead of Add/Wait (#3265)
* Use go 1.25 waitgroup Go method instead of Add/Wait Signed-off-by: Sanket Sudake <sanketsudake@gmail.com> * Disable java builder test for now Signed-off-by: Sanket Sudake <sanketsudake@gmail.com> --------- Signed-off-by: Sanket Sudake <sanketsudake@gmail.com>
This commit is contained in:
+10
-12
@@ -154,12 +154,11 @@ func (executor *Executor) serveCreateFuncServices(ctx context.Context) {
|
|||||||
// create a waitgroup for other requests for
|
// create a waitgroup for other requests for
|
||||||
// the same function to wait on
|
// the same function to wait on
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
wg.Add(1)
|
|
||||||
executor.fsCreateWg.Store(fnkeyUR, wg)
|
executor.fsCreateWg.Store(fnkeyUR, wg)
|
||||||
|
|
||||||
// launch a goroutine for each request, to parallelize
|
// launch a goroutine for each request, to parallelize
|
||||||
// the specialization of different functions
|
// the specialization of different functions
|
||||||
go func() {
|
wg.Go(func() {
|
||||||
// Control overall specialization time by setting function
|
// Control overall specialization time by setting function
|
||||||
// specialization time to context. The reason not to use
|
// specialization time to context. The reason not to use
|
||||||
// context from router requests is because a request maybe
|
// context from router requests is because a request maybe
|
||||||
@@ -188,8 +187,7 @@ func (executor *Executor) serveCreateFuncServices(ctx context.Context) {
|
|||||||
err: err,
|
err: err,
|
||||||
}
|
}
|
||||||
executor.fsCreateWg.Delete(fnkeyUR)
|
executor.fsCreateWg.Delete(fnkeyUR)
|
||||||
wg.Done()
|
})
|
||||||
}()
|
|
||||||
} else {
|
} else {
|
||||||
// There's an existing request for this function, wait for it to finish
|
// There's an existing request for this function, wait for it to finish
|
||||||
go func() {
|
go func() {
|
||||||
@@ -352,14 +350,14 @@ func StartExecutor(ctx context.Context, clientGen crd.ClientGeneratorInterface,
|
|||||||
|
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
for _, et := range executorTypes {
|
for _, et := range executorTypes {
|
||||||
wg.Add(1)
|
wg.Go(func() {
|
||||||
go func(et executortype.ExecutorType) {
|
func(et executortype.ExecutorType) {
|
||||||
defer wg.Done()
|
if adoptExistingResources {
|
||||||
if adoptExistingResources {
|
et.AdoptExistingResources(ctx)
|
||||||
et.AdoptExistingResources(ctx)
|
}
|
||||||
}
|
et.CleanupOldExecutorObjects(ctx)
|
||||||
et.CleanupOldExecutorObjects(ctx)
|
}(et)
|
||||||
}(et)
|
})
|
||||||
}
|
}
|
||||||
// set hard timeout for resource adoption
|
// set hard timeout for resource adoption
|
||||||
// TODO: use context to control the waiting time once kubernetes client supports it.
|
// TODO: use context to control the waiting time once kubernetes client supports it.
|
||||||
|
|||||||
@@ -302,17 +302,14 @@ func (caaf *Container) AdoptExistingResources(ctx context.Context) {
|
|||||||
for i := range fnList.Items {
|
for i := range fnList.Items {
|
||||||
fn := &fnList.Items[i]
|
fn := &fnList.Items[i]
|
||||||
if fn.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType == fv1.ExecutorTypeContainer {
|
if fn.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType == fv1.ExecutorTypeContainer {
|
||||||
wg.Add(1)
|
wg.Go(func() {
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
_, err = caaf.fnCreate(ctx, fn)
|
_, err = caaf.fnCreate(ctx, fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
caaf.logger.Warn("failed to adopt resources for function", zap.Error(err))
|
caaf.logger.Warn("failed to adopt resources for function", zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
caaf.logger.Info("adopt resources for function", zap.String("function", fn.ObjectMeta.Name))
|
caaf.logger.Info("adopt resources for function", zap.String("function", fn.ObjectMeta.Name))
|
||||||
}()
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -322,17 +322,14 @@ func (deploy *NewDeploy) AdoptExistingResources(ctx context.Context) {
|
|||||||
for i := range fnList.Items {
|
for i := range fnList.Items {
|
||||||
fn := &fnList.Items[i]
|
fn := &fnList.Items[i]
|
||||||
if fn.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType == fv1.ExecutorTypeNewdeploy {
|
if fn.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType == fv1.ExecutorTypeNewdeploy {
|
||||||
wg.Add(1)
|
wg.Go(func() {
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
_, err = deploy.fnCreate(ctx, fn)
|
_, err = deploy.fnCreate(ctx, fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
deploy.logger.Warn("failed to adopt resources for function", zap.Error(err))
|
deploy.logger.Warn("failed to adopt resources for function", zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
deploy.logger.Info("adopt resources for function", zap.String("function", fn.ObjectMeta.Name))
|
deploy.logger.Info("adopt resources for function", zap.String("function", fn.ObjectMeta.Name))
|
||||||
}()
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -368,9 +368,7 @@ func (gpm *GenericPoolManager) AdoptExistingResources(ctx context.Context) {
|
|||||||
env := envs.Items[i]
|
env := envs.Items[i]
|
||||||
|
|
||||||
if getEnvPoolSize(&env) > 0 {
|
if getEnvPoolSize(&env) > 0 {
|
||||||
wg.Add(1)
|
wg.Go(func() {
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
_, created, err := gpm.getPool(ctx, &env)
|
_, created, err := gpm.getPool(ctx, &env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gpm.logger.Error("adopt pool failed", zap.Error(err))
|
gpm.logger.Error("adopt pool failed", zap.Error(err))
|
||||||
@@ -378,7 +376,7 @@ func (gpm *GenericPoolManager) AdoptExistingResources(ctx context.Context) {
|
|||||||
if created {
|
if created {
|
||||||
gpm.logger.Info("created pool for the environment", zap.String("env", env.ObjectMeta.Name), zap.String("namespace", gpm.nsResolver.ResolveNamespace(gpm.nsResolver.FunctionNamespace)))
|
gpm.logger.Info("created pool for the environment", zap.String("env", env.ObjectMeta.Name), zap.String("namespace", gpm.nsResolver.ResolveNamespace(gpm.nsResolver.FunctionNamespace)))
|
||||||
}
|
}
|
||||||
}()
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// create environment map for later use
|
// create environment map for later use
|
||||||
@@ -407,10 +405,7 @@ func (gpm *GenericPoolManager) AdoptExistingResources(ctx context.Context) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Add(1)
|
wg.Go(func() {
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
// avoid too many requests arrive Kubernetes API server at the same time.
|
// avoid too many requests arrive Kubernetes API server at the same time.
|
||||||
time.Sleep(time.Duration(rand.Intn(30)) * time.Millisecond)
|
time.Sleep(time.Duration(rand.Intn(30)) * time.Millisecond)
|
||||||
|
|
||||||
@@ -482,7 +477,7 @@ func (gpm *GenericPoolManager) AdoptExistingResources(ctx context.Context) {
|
|||||||
|
|
||||||
gpm.logger.Info("adopt function pod",
|
gpm.logger.Info("adopt function pod",
|
||||||
zap.String("pod", pod.Name), zap.Any("labels", pod.Labels), zap.Any("annotations", pod.Annotations))
|
zap.String("pod", pod.Name), zap.Any("labels", pod.Labels), zap.Any("annotations", pod.Annotations))
|
||||||
}()
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -224,32 +224,33 @@ func TestPoolCacheRequests(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for i := 1; i <= tt.requests; i++ {
|
for i := 1; i <= tt.requests; i++ {
|
||||||
reqno := i
|
reqno := i
|
||||||
wg.Add(1)
|
wg.Go(func() {
|
||||||
go func(reqno int) {
|
func(reqno int) {
|
||||||
defer wg.Done()
|
svc, err := p.GetSvcValue(context.Background(), key, tt.rpp, tt.concurrency)
|
||||||
svc, err := p.GetSvcValue(context.Background(), key, tt.rpp, tt.concurrency)
|
if err != nil {
|
||||||
if err != nil {
|
code, _ := ferror.GetHTTPError(err)
|
||||||
code, _ := ferror.GetHTTPError(err)
|
if code == http.StatusNotFound {
|
||||||
if code == http.StatusNotFound {
|
atomic.AddUint64(&svcCounter, 1)
|
||||||
atomic.AddUint64(&svcCounter, 1)
|
address := fmt.Sprintf("svc-%d", atomic.LoadUint64(&svcCounter))
|
||||||
address := fmt.Sprintf("svc-%d", atomic.LoadUint64(&svcCounter))
|
p.SetSvcValue(context.Background(), key, address, &FuncSvc{
|
||||||
p.SetSvcValue(context.Background(), key, address, &FuncSvc{
|
Name: address,
|
||||||
Name: address,
|
}, resource.MustParse("45m"), tt.rpp, tt.retainPods)
|
||||||
}, resource.MustParse("45m"), tt.rpp, tt.retainPods)
|
} else {
|
||||||
|
t.Log(reqno, "=>", err)
|
||||||
|
atomic.AddUint64(&failedRequests, 1)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
t.Log(reqno, "=>", err)
|
if svc == nil {
|
||||||
atomic.AddUint64(&failedRequests, 1)
|
t.Log(reqno, "=>", "svc is nil")
|
||||||
|
atomic.AddUint64(&failedRequests, 1)
|
||||||
|
}
|
||||||
|
// } else {
|
||||||
|
// t.Log(reqno, "=>", svc.Name)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
} else {
|
}(reqno)
|
||||||
if svc == nil {
|
})
|
||||||
t.Log(reqno, "=>", "svc is nil")
|
|
||||||
atomic.AddUint64(&failedRequests, 1)
|
|
||||||
}
|
|
||||||
// } else {
|
|
||||||
// t.Log(reqno, "=>", svc.Name)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}(reqno)
|
|
||||||
if reqno%simultaneous == 0 {
|
if reqno%simultaneous == 0 {
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
@@ -261,12 +262,12 @@ func TestPoolCacheRequests(t *testing.T) {
|
|||||||
|
|
||||||
for i := 0; i < tt.concurrency; i++ {
|
for i := 0; i < tt.concurrency; i++ {
|
||||||
for j := 0; j < tt.rpp; j++ {
|
for j := 0; j < tt.rpp; j++ {
|
||||||
wg.Add(1)
|
|
||||||
svcno := i
|
svcno := i
|
||||||
go func(svcno int) {
|
wg.Go(func() {
|
||||||
defer wg.Done()
|
func(svcno int) {
|
||||||
p.MarkAvailable(key, fmt.Sprintf("svc-%d", svcno+1))
|
p.MarkAvailable(key, fmt.Sprintf("svc-%d", svcno+1))
|
||||||
}(svcno)
|
}(svcno)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|||||||
@@ -48,16 +48,14 @@ func TestQueuePushWithConcurrentRequest(t *testing.T) {
|
|||||||
q := NewQueue()
|
q := NewQueue()
|
||||||
noOfRequests := 20
|
noOfRequests := 20
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(noOfRequests)
|
|
||||||
for i := 0; i < noOfRequests; i++ {
|
for i := 0; i < noOfRequests; i++ {
|
||||||
go func() {
|
wg.Go(func() {
|
||||||
defer wg.Done()
|
|
||||||
item := &svcWait{
|
item := &svcWait{
|
||||||
svcChannel: make(chan *FuncSvc),
|
svcChannel: make(chan *FuncSvc),
|
||||||
ctx: nil,
|
ctx: nil,
|
||||||
}
|
}
|
||||||
q.Push(item)
|
q.Push(item)
|
||||||
}()
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|||||||
@@ -128,11 +128,11 @@ func (opts *DumpSubCommand) do(input cli.Input) error {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wg.Add(1)
|
wg.Go(func() {
|
||||||
go func(res resources.Resource, dir string) {
|
func(res resources.Resource, dir string) {
|
||||||
defer wg.Done()
|
res.Dump(input.Context(), dir)
|
||||||
res.Dump(input.Context(), dir)
|
}(res, dir)
|
||||||
}(res, dir)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|||||||
@@ -207,49 +207,48 @@ func (res KubernetesPodLogDumper) Dump(ctx context.Context, dumpDir string) {
|
|||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
|
|
||||||
for _, p := range l.Items {
|
for _, p := range l.Items {
|
||||||
wg.Add(1)
|
wg.Go(func() {
|
||||||
|
func(pod corev1.Pod) {
|
||||||
|
// dump logs from each containers
|
||||||
|
for _, container := range append(pod.Spec.Containers, pod.Spec.InitContainers...) {
|
||||||
|
req := res.client.CoreV1().Pods(pod.Namespace).
|
||||||
|
GetLogs(pod.Name, &corev1.PodLogOptions{Container: container.Name})
|
||||||
|
|
||||||
go func(pod corev1.Pod) {
|
stream, err := req.Stream(ctx)
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
// dump logs from each containers
|
|
||||||
for _, container := range append(pod.Spec.Containers, pod.Spec.InitContainers...) {
|
|
||||||
req := res.client.CoreV1().Pods(pod.Namespace).
|
|
||||||
GetLogs(pod.Name, &corev1.PodLogOptions{Container: container.Name})
|
|
||||||
|
|
||||||
stream, err := req.Stream(ctx)
|
|
||||||
if err != nil {
|
|
||||||
console.Error(fmt.Sprintf("Error streaming logs for pod %v: %v", pod.Name, err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
reader := bufio.NewReader(stream)
|
|
||||||
var buffer bytes.Buffer
|
|
||||||
|
|
||||||
for {
|
|
||||||
line, _, err := reader.ReadLine()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
console.Error(fmt.Sprintf("Error streaming logs for pod %v: %v", pod.Name, err))
|
||||||
stream.Close()
|
return
|
||||||
break
|
}
|
||||||
|
|
||||||
|
reader := bufio.NewReader(stream)
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
|
||||||
|
for {
|
||||||
|
line, _, err := reader.ReadLine()
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
stream.Close()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
console.Error(fmt.Sprintf("Error reading logs from buffer: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = buffer.WriteString(string(line) + "\n")
|
||||||
|
if err != nil {
|
||||||
|
console.Error(fmt.Sprintf("Error writing bytes to buffer: %v", err))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
console.Error(fmt.Sprintf("Error reading logs from buffer: %v", err))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = buffer.WriteString(string(line) + "\n")
|
f := getPodFileName(dumpDir, pod.ObjectMeta, container.Name)
|
||||||
if err != nil {
|
writeToFile(f, buffer.String())
|
||||||
console.Error(fmt.Sprintf("Error writing bytes to buffer: %v", err))
|
|
||||||
return
|
stream.Close()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}(p)
|
||||||
|
})
|
||||||
|
|
||||||
f := getPodFileName(dumpDir, pod.ObjectMeta, container.Name)
|
|
||||||
writeToFile(f, buffer.String())
|
|
||||||
|
|
||||||
stream.Close()
|
|
||||||
}
|
|
||||||
}(p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|||||||
@@ -36,11 +36,9 @@ func New() Interface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (g *GroupManager) Add(ctx context.Context, f func(context.Context)) {
|
func (g *GroupManager) Add(ctx context.Context, f func(context.Context)) {
|
||||||
g.wg.Add(1)
|
g.wg.Go(func() {
|
||||||
go func() {
|
|
||||||
defer g.wg.Done()
|
|
||||||
f(ctx)
|
f(ctx)
|
||||||
}()
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GroupManager) AddInformers(ctx context.Context, informers map[string]k8sCache.SharedIndexInformer) {
|
func (g *GroupManager) AddInformers(ctx context.Context, informers map[string]k8sCache.SharedIndexInformer) {
|
||||||
|
|||||||
@@ -23,9 +23,7 @@ func chunkedHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
ctx, cancel := context.WithCancel(r.Context())
|
ctx, cancel := context.WithCancel(r.Context())
|
||||||
ticker := time.NewTicker(time.Second) // We may set it to 10 secs
|
ticker := time.NewTicker(time.Second) // We may set it to 10 secs
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(1)
|
wg.Go(func() {
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
@@ -37,7 +35,7 @@ func chunkedHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
})
|
||||||
|
|
||||||
// Emulate some work
|
// Emulate some work
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
#test:disabled
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
source $(dirname $0)/../../utils.sh
|
source $(dirname $0)/../../utils.sh
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user