-
Notifications
You must be signed in to change notification settings - Fork 881
feat: send native system notification on scheduled workspace shutdown #1414
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This commit adds a fairly generic notification package and uses it to notify users connected over SSH of pending workspace shutdowns.
Codecov Report
@@ Coverage Diff @@
## main #1414 +/- ##
==========================================
+ Coverage 67.13% 67.22% +0.08%
==========================================
Files 287 288 +1
Lines 19307 19424 +117
Branches 241 244 +3
==========================================
+ Hits 12962 13057 +95
- Misses 5007 5025 +18
- Partials 1338 1342 +4
Continue to review full report at Codecov.
|
Sounds like we need to add some templates for test desktops on v2 dogfood |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per my other comment, if the notification triggers on every open coder-cli instance, then this may overwhelm the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the sheer amount of comments 😅. I like how you managed to keep the condition logic simple!
t.Run(testCase.Name, func(t *testing.T) { | ||
ch := make(chan time.Time) | ||
numConditions := atomic.NewInt64(0) | ||
numCalls := atomic.NewInt64(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool use of atomic
, I need to remember this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one more question but overall very nice!
type Notifier struct { | ||
lock sync.Mutex | ||
condition Condition | ||
notifiedAt map[time.Duration]bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to move this into pollOnce
? My thought is that this map never reset, and a notification can only be shown once per countdown
entry (for the lifetime of the Notifier
). Not sure if that's a problem or not though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could move into Poll
, but not into pollOnce
.
If we did that, we could probably also remove the sync.Mutex
.
I like the idea of the same Notifier
instance keeping track of what it's already notified between successive calls to Poll()
though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok that makes sense. I guess it's mostly a question of how the package is to be used and what the user (might) expect to happen. I imagine this will not be a problem for ssh
since when the workspace stops, so does the command, so the notifier doesn't outlive its purpose.
// Attempt to poll workspace autostop. We write a per-workspace lockfile to | ||
// avoid spamming the user with notifications in case of multiple instances | ||
// of the CLI running simultaneously. | ||
func tryPollWorkspaceAutostop(ctx context.Context, client *codersdk.Client, workspace codersdk.Workspace) (stop func()) { | ||
lock := flock.New(filepath.Join(os.TempDir(), "coder-autostop-notify-"+workspace.ID.String())) | ||
condition := notifyCondition(ctx, client, workspace.ID, lock) | ||
return notify.Notify(condition, autostopPollInterval, autostopNotifyCountdown...) | ||
} | ||
|
||
// Notify the user if the workspace is due to shutdown. | ||
func notifyCondition(ctx context.Context, client *codersdk.Client, workspaceID uuid.UUID, lock *flock.Flock) notify.Condition { | ||
return func(now time.Time) (deadline time.Time, callback func()) { | ||
// Keep trying to regain the lock. | ||
locked, err := lock.TryLockContext(ctx, autostopPollInterval) | ||
if err != nil || !locked { | ||
return time.Time{}, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it'd be best to place as much of this as possible in the notify
package. eg. for coder port-forward
we'd probably want to do the exact same type of thing.
I could imagine for the frontend too, we would send a notification via WebSocket or something!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That could be a good idea when we have a better idea of what different use-cases crop up.
I fear I've already over-engineered this enough as it is!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't review the code, but if only one notification is sent across all coder-clis, I'm good with this.
…#1414) * feat: send native system notification on scheduled workspace shutdown This commit adds a fairly generic notification package and uses it to notify users connected over SSH of pending workspace shutdowns. Only one notification will be sent at most 5 minutes prior to the scheduled shutdown, and only one CLI instance will send notifications if multiple instances are running.
This commit adds a fairly generic notification package and uses it
to notify users connected over SSH of pending workspace shutdowns.
It uses
github.com/gen2brain/beeep
under the hood for actually doing the platform-specific heavy lifting.I've tested it out on MacOS and Windows and it seems to work fine there; I don't have a Linux desktop around with dbus and all of that associated stuff setup to test it there though.
The
autobuild/notify
package might be a bit of a step too far, but it lets me easily test the notification timing logic without worrying about anything else -- which is arguably the most important part.Subtasks
Additions
gofrs/flock
)notifier.Notify
for folks who don't like making their own timers.Fixes #861