Skip to content

Commit a072fdb

Browse files
improve warns/errs
1 parent cbb9858 commit a072fdb

1 file changed

Lines changed: 42 additions & 14 deletions

File tree

internal/core/regional_list.go

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,38 +55,66 @@ func (c *CommandConfig) ListAllLocations(
5555
return c.Printer(columns).Prefix("items").Print(data)
5656
}
5757

58-
// Multi-location: query all concurrently
58+
// Build all configs before spawning goroutines to avoid racing
59+
// on client.Must() singleton (getters.go URL-change rebuild is not synchronized).
60+
type locConfig struct {
61+
location string
62+
cfg *shared.Configuration
63+
}
64+
configs := make([]locConfig, len(locations))
65+
for i, loc := range locations {
66+
normalizedLoc := strings.ReplaceAll(loc, "/", "-")
67+
url := fmt.Sprintf(templateURL, normalizedLoc)
68+
configs[i] = locConfig{location: loc, cfg: client.NewRegionalConfig(url)}
69+
}
70+
71+
// Query all locations concurrently
5972
results := make([]locResult, len(locations))
6073
var wg sync.WaitGroup
6174

62-
for i, loc := range locations {
75+
for i, lc := range configs {
6376
wg.Add(1)
64-
go func(i int, loc string) {
77+
go func(i int, lc locConfig) {
6578
defer wg.Done()
66-
67-
normalizedLoc := strings.ReplaceAll(loc, "/", "-")
68-
url := fmt.Sprintf(templateURL, normalizedLoc)
69-
cfg := client.NewRegionalConfig(url)
70-
71-
data, err := fetchFn(cfg)
72-
results[i] = locResult{location: loc, data: data, err: err}
73-
}(i, loc)
79+
data, err := fetchFn(lc.cfg)
80+
results[i] = locResult{location: lc.location, data: data, err: err}
81+
}(i, lc)
7482
}
7583
wg.Wait()
7684

77-
// Check if all failed
85+
// Collect errors, deduplicate identical messages
7886
var lastErr error
7987
anySuccess := false
88+
errCounts := map[string][]string{} // error message → list of locations
8089
for _, r := range results {
8190
if r.err != nil {
8291
lastErr = r.err
83-
fmt.Fprintf(c.Command.Command.ErrOrStderr(), "WARN: failed to list from %s: %v\n", r.location, r.err)
92+
msg := r.err.Error()
93+
errCounts[msg] = append(errCounts[msg], r.location)
8494
} else {
8595
anySuccess = true
8696
}
8797
}
98+
8899
if !anySuccess {
89-
return fmt.Errorf("failed to list from any location: %w", lastErr)
100+
// All failed — return single error, no warnings
101+
if len(errCounts) == 1 {
102+
return fmt.Errorf("failed to list from all locations: %w", lastErr)
103+
}
104+
// Multiple distinct errors — join them
105+
var parts []string
106+
for msg, locs := range errCounts {
107+
parts = append(parts, fmt.Sprintf("%s: %s", strings.Join(locs, ", "), msg))
108+
}
109+
return fmt.Errorf("failed to list from all locations:\n %s", strings.Join(parts, "\n "))
110+
}
111+
112+
// Partial failure — warn only for failed locations
113+
if len(errCounts) > 0 {
114+
stderr := c.Command.Command.ErrOrStderr()
115+
for msg, locs := range errCounts {
116+
fmt.Fprintf(stderr, "WARN: failed to list from %s: %s\n", strings.Join(locs, ", "), msg)
117+
}
90118
}
91119

92120
// Determine output format

0 commit comments

Comments
 (0)