Skip to content

feat: Add web terminal with reconnecting TTYs #1186

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

Merged
merged 8 commits into from
Apr 29, 2022
Merged

feat: Add web terminal with reconnecting TTYs #1186

merged 8 commits into from
Apr 29, 2022

Conversation

kylecarbs
Copy link
Member

@kylecarbs kylecarbs commented Apr 26, 2022

This adds a web terminal that can reconnect to resume sessions!
No more disconnects, and no more bad buffering!

It uses a circular buffer under the hood to constantly buffer ~64KB
of terminal scrollback data.

Todo:

  • Add proper error states to the frontend.
  • Add test for the frontend!
  • Allow agents in "connecting" state to "Wait for connection...", just like the CLI. This doesn't seem necessary for merge. Customers will get an error that the workspace is offline anyways, which is a pretty obvious indicator.

image

There isn't currently a direct link from the dashboard, but you can try it out by:

  1. make bin && go run -tags embed ./cmd/coder server --dev
  2. Creating a template and workspace.
  3. Manually navigating to https://localhost:3000/<username>/<workspace>/terminal.
reconnecting-terminal-2022-04-29_09.06.33.mp4

@kylecarbs kylecarbs requested a review from code-asher April 26, 2022 20:25
@kylecarbs kylecarbs self-assigned this Apr 26, 2022
@codecov
Copy link

codecov bot commented Apr 26, 2022

Codecov Report

Merging #1186 (19c7b54) into main (021e4cd) will increase coverage by 0.14%.
The diff coverage is 69.20%.

@@            Coverage Diff             @@
##             main    #1186      +/-   ##
==========================================
+ Coverage   65.65%   65.80%   +0.14%     
==========================================
  Files         269      272       +3     
  Lines       17366    17872     +506     
  Branches      164      192      +28     
==========================================
+ Hits        11402    11760     +358     
- Misses       4772     4882     +110     
- Partials     1192     1230      +38     
Flag Coverage Δ
unittest-go-macos-latest 53.19% <64.34%> (+0.19%) ⬆️
unittest-go-postgres- 64.80% <64.34%> (+0.01%) ⬆️
unittest-go-ubuntu-latest 55.54% <63.50%> (+0.15%) ⬆️
unittest-go-windows-2022 52.78% <62.74%> (+0.26%) ⬆️
unittest-js 69.96% <80.51%> (+1.08%) ⬆️
Impacted Files Coverage Δ
site/src/AppRouter.tsx 0.00% <0.00%> (ø)
...ges/OrganizationPage/TemplatePage/TemplatePage.tsx 0.00% <ø> (ø)
codersdk/workspaceagents.go 51.52% <56.00%> (+0.41%) ⬆️
coderd/workspaceagents.go 56.77% <57.62%> (-1.38%) ⬇️
agent/conn.go 64.70% <62.50%> (-0.68%) ⬇️
agent/agent.go 66.87% <68.31%> (+0.56%) ⬆️
site/src/xServices/terminal/terminalXService.ts 68.42% <68.42%> (ø)
site/src/pages/TerminalPage/TerminalPage.tsx 87.50% <87.50%> (ø)
site/src/api/index.ts 69.49% <90.00%> (+4.18%) ⬆️
cli/agent.go 80.37% <100.00%> (+0.37%) ⬆️
... and 15 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 021e4cd...19c7b54. Read the comment docs.

@kylecarbs kylecarbs force-pushed the webterm branch 3 times, most recently from 47e0e98 to 6e1ac65 Compare April 27, 2022 00:11
This adds a web terminal that can reconnect to resume sessions!
No more disconnects, and no more bad bufferring!
"/api": {
target: "http://localhost:3000",
ws: true,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️ site/ changes LGTM

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's much fancier now! ✨

@kylecarbs kylecarbs force-pushed the webterm branch 3 times, most recently from cf9d2a3 to 8cc14c1 Compare April 28, 2022 14:33
@deansheather
Copy link
Member

Have you considered instead of capturing scroll back just reconnecting the tty to the new websocket and forcing the shell or ncurses app to refresh by sending a resize signal? Would be way simpler, and we can show the reconnection similar to how iterm or vscode does it

@kylecarbs
Copy link
Member Author

This actually is how VS Code does it!

@kylecarbs
Copy link
Member Author

@deansheather do you feel like this is complex right now? We do just store a reconnection token, much like VS Code.

@kylecarbs kylecarbs marked this pull request as ready for review April 29, 2022 03:57
@kylecarbs kylecarbs requested review from presleyp and a team as code owners April 29, 2022 03:57
@deansheather
Copy link
Member

@kylecarbs my suggestion is to not use a scroll back buffer at all, but when they reconnect the client would keep the existing history it has locally and just write a "Restored terminal session" message to the terminal, then force a screen refresh for interactive apps (like the shell and vim etc.) using sigwinch. We would not need to worry about scrollback buffers which I think are weird and complex anyways

@kylecarbs
Copy link
Member Author

How would that work if data occurred during disconnect? Or if they refresh the window?

The current case handles both seamlessly, and could even allow terminal sharing just with a link.

@deansheather
Copy link
Member

@kylecarbs my suggestion is how vscode does it I think. Obviously having a scrollback is nicer, but I think it adds to much complexity and is prone to weird terminal bugs rather than a simpler and more robust solution.

Terminal sharing is still possible but when new clients connect they won't have scrollback which I think is fine.

@kylecarbs
Copy link
Member Author

VS Code has a buffer like the current implementation, but maybe they also do what you mention.

What bugs do you foresee? Have you tried it out?

@deansheather
Copy link
Member

We can add scrollback later if customers request it, but for most cases users just don't want to do lose their shell history or running processes or vim session etc and the output (as long as we do the refresh thing) isn't a huge issue IMO

@kylecarbs kylecarbs force-pushed the webterm branch 2 times, most recently from 0fd3e02 to b1f3b0e Compare April 29, 2022 18:41
@kylecarbs kylecarbs force-pushed the webterm branch 2 times, most recently from daf4ece to 8212287 Compare April 29, 2022 18:50
Copy link
Member

@code-asher code-asher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Niiiiice!!

One thing I thought would be nice is an automatic reconnection or a longer timeout because I will have a disconnect and not notice for a while but by then it is too late to reconnect (no need to do that in this PR though IMO).

Do you get disconnected a lot or is it just me? That disconnect overlay keeps coming up for me (one to two minutes). I doubt it is something in this PR, just curious if this is normal. only happens when using the provided tunneled URL; might be something to look at eventually though

return render(
<Routes>
<Route path="/:username/:workspace/terminal" element={<TerminalPage renderer="dom" />} />
</Routes>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh, curious why you put Routes in here, it might help me with some pain points I've had

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It said it was required for me to use <Route /> :(

Copy link
Contributor

@presleyp presleyp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting up with my slow trickle of comments throughout the day! Awesome stuff.

@kylecarbs
Copy link
Member Author

@presleyp I appreciate the thorough review!

@kylecarbs kylecarbs force-pushed the webterm branch 4 times, most recently from bd6dc51 to 7d9c1b8 Compare April 29, 2022 20:15
@code-asher code-asher self-requested a review April 29, 2022 21:39
@kylecarbs
Copy link
Member Author

I'm going to merge, but @deansheather please feel free to follow up if my message doesn't resolve your concerns! It appears to be a solid web-terminal as-is, but if we can make it even better I'm of course happy to do so! 😄🪄

@kylecarbs kylecarbs merged commit 81577f1 into main Apr 29, 2022
@kylecarbs kylecarbs deleted the webterm branch April 29, 2022 22:30
@misskniss misskniss added api Area: HTTP API V2 BETA labels May 16, 2022
@misskniss misskniss added this to the V2 Beta milestone May 16, 2022
kylecarbs added a commit that referenced this pull request Jun 10, 2022
* feat: Add web terminal with reconnecting TTYs

This adds a web terminal that can reconnect to resume sessions!
No more disconnects, and no more bad bufferring!

* Add xstate service

* Add the webpage for accessing a web terminal

* Add terminal page tests

* Use Ticker instead of Timer

* Active Windows mode on Windows
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api Area: HTTP API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants