@@ -2,7 +2,6 @@ package cli
2
2
3
3
import (
4
4
"context"
5
- "errors"
6
5
"fmt"
7
6
"io"
8
7
"os"
@@ -11,6 +10,7 @@ import (
11
10
"time"
12
11
13
12
"github.com/gen2brain/beeep"
13
+ "github.com/gofrs/flock"
14
14
"github.com/google/uuid"
15
15
"github.com/mattn/go-isatty"
16
16
"github.com/spf13/cobra"
@@ -197,35 +197,20 @@ func ssh() *cobra.Command {
197
197
// avoid spamming the user with notifications in case of multiple instances
198
198
// of the CLI running simultaneously.
199
199
func tryPollWorkspaceAutostop (ctx context.Context , client * codersdk.Client , workspace codersdk.Workspace ) (stop func ()) {
200
- lockPath := filepath .Join (os .TempDir (), "coder-autostop-notify-" + workspace .ID .String ())
201
- lockStat , err := os .Stat (lockPath )
202
- if err == nil {
203
- // Lock file already exists for this workspace. How old is it?
204
- lockAge := time .Now ().Sub (lockStat .ModTime ())
205
- if lockAge < 3 * autostopPollInterval {
206
- // Lock file exists and is still "fresh". Do nothing.
207
- return func () {}
208
- }
209
- }
210
- if ! errors .Is (err , os .ErrNotExist ) {
211
- // No permission to write to temp? Not much we can do.
212
- return func () {}
213
- }
214
- lockFile , err := os .Create (lockPath )
215
- if err != nil {
216
- // Someone got there already?
217
- return func () {}
218
- }
219
-
220
- condition := notifyCondition (ctx , client , workspace .ID , lockFile )
200
+ lock := flock .New (filepath .Join (os .TempDir (), "coder-autostop-notify-" + workspace .ID .String ()))
201
+ condition := notifyCondition (ctx , client , workspace .ID , lock )
221
202
return notify .Notify (condition , autostopPollInterval , autostopNotifyCountdown ... )
222
203
}
223
204
224
205
// Notify the user if the workspace is due to shutdown.
225
- func notifyCondition (ctx context.Context , client * codersdk.Client , workspaceID uuid.UUID , lockFile * os. File ) notify.Condition {
206
+ func notifyCondition (ctx context.Context , client * codersdk.Client , workspaceID uuid.UUID , lock * flock. Flock ) notify.Condition {
226
207
return func (now time.Time ) (deadline time.Time , callback func ()) {
227
- // update lockFile (best effort)
228
- _ = os .Chtimes (lockFile .Name (), now , now )
208
+ // Keep trying to regain the lock.
209
+ locked , err := lock .TryLockContext (ctx , autostopPollInterval )
210
+ if err != nil || ! locked {
211
+ return time.Time {}, nil
212
+ }
213
+
229
214
ws , err := client .Workspace (ctx , workspaceID )
230
215
if err != nil {
231
216
return time.Time {}, nil
0 commit comments