Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Aug 30, 2024. It is now read-only.
/coder-v1-cliPublic archive

Commit6c2e59b

Browse files
committed
Add new clog.ErrGroup
1 parent6f8b9b8 commit6c2e59b

File tree

3 files changed

+72
-28
lines changed

3 files changed

+72
-28
lines changed

‎internal/clog/doc.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// package clog provides rich error types and logging helpers for coder-cli.
2+
//
3+
// clog encourages returning error types rather than
4+
// logging them and failing with os.Exit as they happen.
5+
// Error, Fatal, and Warn allow downstream functions to return errors with rich formatting information
6+
// while preserving the original, single-line error chain.
7+
package clog

‎internal/clog/errgroup.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package clog
2+
3+
import (
4+
"fmt"
5+
"sync/atomic"
6+
7+
"golang.org/x/sync/errgroup"
8+
"golang.org/x/xerrors"
9+
)
10+
11+
// ErrGroup wraps the /x/sync/errgroup.(Group) and adds clog logging and rich error propagation.
12+
//
13+
// Take for example, a case in which we are concurrently stopping a slice of environments.
14+
// In this case, we want to log errors as they happen, not pass them through the callstack as errors.
15+
// When the operations complete, we want to log how many, if any, failed. The caller is still expected
16+
// to handle success and info logging.
17+
typeErrGroupinterface {
18+
Go(ffunc()error)
19+
Wait()error
20+
}
21+
22+
typegroupstruct {
23+
egroup errgroup.Group
24+
failuresint32
25+
}
26+
27+
// LoggedErrGroup gives an error group with error logging and error propagation handled automatically.
28+
funcLoggedErrGroup()ErrGroup {
29+
return&group{
30+
egroup: errgroup.Group{},
31+
failures:0,
32+
}
33+
}
34+
35+
func (g*group)Go(ffunc()error) {
36+
g.egroup.Go(func()error {
37+
iferr:=f();err!=nil {
38+
atomic.AddInt32(&g.failures,1)
39+
Log(err)
40+
41+
// this error does not matter because we discard it in Wait.
42+
returnxerrors.New("")
43+
}
44+
returnnil
45+
})
46+
}
47+
48+
func (g*group)Wait()error {
49+
_=g.egroup.Wait()// ignore this error because we are already tracking failures manually
50+
ifg.failures==0 {
51+
returnnil
52+
}
53+
failureWord:="failure"
54+
ifg.failures>1 {
55+
failureWord+="s"
56+
}
57+
returnFatal(fmt.Sprintf("%d %s emitted",g.failures,failureWord))
58+
}

‎internal/cmd/envs.go

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@ import (
44
"encoding/json"
55
"fmt"
66
"os"
7-
"sync/atomic"
87

98
"cdr.dev/coder-cli/coder-sdk"
109
"cdr.dev/coder-cli/internal/clog"
1110
"cdr.dev/coder-cli/internal/x/xtabwriter"
1211
"github.com/manifoldco/promptui"
1312
"github.com/spf13/cobra"
14-
"golang.org/x/sync/errgroup"
1513
"golang.org/x/xerrors"
1614
)
1715

@@ -113,36 +111,27 @@ coder envs --user charlie@coder.com ls -o json \
113111
returnxerrors.Errorf("new client: %w",err)
114112
}
115113

116-
varegroup errgroup.Group
117-
varfailsint32
114+
egroup:=clog.LoggedErrGroup()
118115
for_,envName:=rangeargs {
119116
envName:=envName
120117
egroup.Go(func()error {
121118
env,err:=findEnv(cmd.Context(),client,envName,*user)
122119
iferr!=nil {
123-
atomic.AddInt32(&fails,1)
124-
clog.Log(err)
125-
returnxerrors.Errorf("find env by name: %w",err)
120+
returnerr
126121
}
127122

128123
iferr=client.StopEnvironment(cmd.Context(),env.ID);err!=nil {
129-
atomic.AddInt32(&fails,1)
130-
err=clog.Fatal(fmt.Sprintf("stop environment %q",env.Name),
124+
returnclog.Error(fmt.Sprintf("stop environment %q",env.Name),
131125
clog.Causef(err.Error()),clog.BlankLine,
132126
clog.Hintf("current environment status is %q",env.LatestStat.ContainerStatus),
133127
)
134-
clog.Log(err)
135-
returnerr
136128
}
137129
clog.LogSuccess(fmt.Sprintf("successfully stopped environment %q",envName))
138130
returnnil
139131
})
140132
}
141133

142-
iferr=egroup.Wait();err!=nil {
143-
returnclog.Fatal(fmt.Sprintf("%d failure(s) emitted",fails))
144-
}
145-
returnnil
134+
returnegroup.Wait()
146135
},
147136
}
148137
}
@@ -353,35 +342,25 @@ func rmEnvsCommand(user *string) *cobra.Command {
353342
}
354343
}
355344

356-
varegroup errgroup.Group
357-
varfailuresint32
345+
egroup:=clog.LoggedErrGroup()
358346
for_,envName:=rangeargs {
359347
envName:=envName
360348
egroup.Go(func()error {
361349
env,err:=findEnv(ctx,client,envName,*user)
362350
iferr!=nil {
363-
atomic.AddInt32(&failures,1)
364-
clog.Log(err)
365351
returnerr
366352
}
367353
iferr=client.DeleteEnvironment(cmd.Context(),env.ID);err!=nil {
368-
atomic.AddInt32(&failures,1)
369-
err=clog.Error(
354+
returnclog.Error(
370355
fmt.Sprintf(`failed to delete environment "%s"`,env.Name),
371356
clog.Causef(err.Error()),
372357
)
373-
clog.Log(err)
374-
returnerr
375358
}
376359
clog.LogSuccess(fmt.Sprintf("deleted environment %q",env.Name))
377360
returnnil
378361
})
379362
}
380-
381-
iferr=egroup.Wait();err!=nil {
382-
returnxerrors.Errorf("%d failure(s) emitted",failures)
383-
}
384-
returnnil
363+
returnegroup.Wait()
385364
},
386365
}
387366
cmd.Flags().BoolVarP(&force,"force","f",false,"force remove the specified environments without prompting first")

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp