@@ -30,6 +30,7 @@ import (
30
30
"github.com/coder/coder/coderd/util/ptr"
31
31
"github.com/coder/coder/codersdk"
32
32
"github.com/coder/coder/cryptorand"
33
+ "github.com/coder/retry"
33
34
)
34
35
35
36
var (
@@ -110,32 +111,49 @@ func (r *RootCmd) ssh() *clibase.Cmd {
110
111
// will usually not propagate.
111
112
//
112
113
// See: https://github.com/coder/coder/issues/6180
113
- wsWatch , err := client .WatchWorkspace (ctx , workspace .ID )
114
- if err != nil {
115
- return err
116
- }
117
114
watchAndClose := func (closer func () error ) {
118
115
// Ensure session is ended on both context cancellation
119
116
// and workspace stop.
120
117
defer func () {
121
118
_ = closer ()
122
119
}()
123
120
121
+ startWatchLoop:
124
122
for {
125
- select {
126
- case <- ctx .Done ():
127
- return
128
- case w , ok := <- wsWatch :
129
- if ! ok {
123
+ // (Re)connect to the coder server and watch workspace events.
124
+ var wsWatch <- chan codersdk.Workspace
125
+ for r := retry .New (time .Second , 15 * time .Second ); r .Wait (ctx ); {
126
+ wsWatch , err = client .WatchWorkspace (ctx , workspace .ID )
127
+ if err == nil {
128
+ break
129
+ }
130
+ if ctx .Err () != nil {
130
131
return
131
132
}
133
+ }
132
134
133
- // Note, we only react to the stopped state here because we
134
- // want to give the agent a chance to gracefully shut down
135
- // during "stopping".
136
- if w .LatestBuild .Status == codersdk .WorkspaceStatusStopped {
137
- _ , _ = fmt .Fprintf (inv .Stderr , "Workspace %q has stopped. Closing connection.\r \n " , workspace .Name )
135
+ for {
136
+ select {
137
+ case <- ctx .Done ():
138
138
return
139
+ case w , ok := <- wsWatch :
140
+ if ! ok {
141
+ continue startWatchLoop
142
+ }
143
+
144
+ // Transitioning to stop or delete could mean that
145
+ // the agent will still gracefully stop. If a new
146
+ // build is starting, there's no reason to wait for
147
+ // the agent, it should be long gone.
148
+ if workspace .LatestBuild .ID != w .LatestBuild .ID && w .LatestBuild .Transition == codersdk .WorkspaceTransitionStart {
149
+ return
150
+ }
151
+ // Note, we only react to the stopped state here because we
152
+ // want to give the agent a chance to gracefully shut down
153
+ // during "stopping".
154
+ if w .LatestBuild .Status == codersdk .WorkspaceStatusStopped {
155
+ return
156
+ }
139
157
}
140
158
}
141
159
}
0 commit comments