From 2b0e4de6152e67bd08d6d459876bdc6ea3831ce5 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 9 Mar 2026 16:33:05 +0000 Subject: [PATCH] kubens: use context to cancel slow-query warning timer after API returns Replace done channel + defer with context.WithCancel so the warning goroutine is cancelled immediately when queryNamespaces returns, not when Run returns (which could be minutes later while user browses fzf). Also thread the context into queryNamespaces so the k8s List call respects it. https://claude.ai/code/session_01XJXHq8WG22iqX8KaDb9RZz --- cmd/kubens/fzf.go | 9 +++++---- cmd/kubens/list.go | 12 ++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/cmd/kubens/fzf.go b/cmd/kubens/fzf.go index af51bad..aafedd8 100644 --- a/cmd/kubens/fzf.go +++ b/cmd/kubens/fzf.go @@ -16,6 +16,7 @@ package main import ( "bytes" + "context" "errors" "fmt" "io" @@ -54,17 +55,17 @@ func (op InteractiveSwitchOp) Run(_, stderr io.Writer) error { return fmt.Errorf("cannot read current namespace: %w", err) } - done := make(chan struct{}) - defer close(done) + ctx, cancel := context.WithCancel(context.Background()) go func() { select { case <-time.After(3 * time.Second): printer.Warning(stderr, `listing namespaces is taking long, switch to a namespace directly with "kubens -f "`) - case <-done: + case <-ctx.Done(): } }() - ns, err := queryNamespaces(kc) + ns, err := queryNamespaces(ctx, kc) + cancel() if err != nil { return fmt.Errorf("could not list namespaces (is the cluster accessible?): %w", err) } diff --git a/cmd/kubens/list.go b/cmd/kubens/list.go index 6ed9528..036cbc1 100644 --- a/cmd/kubens/list.go +++ b/cmd/kubens/list.go @@ -53,17 +53,17 @@ func (op ListOp) Run(stdout, stderr io.Writer) error { return fmt.Errorf("cannot read current namespace: %w", err) } - done := make(chan struct{}) - defer close(done) + ctx, cancel := context.WithCancel(context.Background()) go func() { select { case <-time.After(3 * time.Second): printer.Warning(stderr, `listing namespaces is taking long, switch to a namespace directly with "kubens -f "`) - case <-done: + case <-ctx.Done(): } }() - ns, err := queryNamespaces(kc) + ns, err := queryNamespaces(ctx, kc) + cancel() if err != nil { return fmt.Errorf("could not list namespaces (is the cluster accessible?): %w", err) } @@ -78,7 +78,7 @@ func (op ListOp) Run(stdout, stderr io.Writer) error { return nil } -func queryNamespaces(kc *kubeconfig.Kubeconfig) ([]string, error) { +func queryNamespaces(ctx context.Context, kc *kubeconfig.Kubeconfig) ([]string, error) { if os.Getenv("_MOCK_NAMESPACES") != "" { return []string{"ns1", "ns2"}, nil } @@ -92,7 +92,7 @@ func queryNamespaces(kc *kubeconfig.Kubeconfig) ([]string, error) { var next string for { list, err := clientset.CoreV1().Namespaces().List( - context.Background(), + ctx, metav1.ListOptions{ Limit: 500, Continue: next,