Skip to content

Check the agent's status #232

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 10 commits into from
Apr 26, 2023
Merged

Check the agent's status #232

merged 10 commits into from
Apr 26, 2023

Conversation

code-asher
Copy link
Member

@code-asher code-asher commented Apr 25, 2023

Some more information in the individual commits.

Interestingly this may also improve the perception of how long it takes to select an editor because the time waiting for the agent will be spent on the initial connect screen rather than the select editor screen.

Looks like there is already a property that is the composite of the two
fields we were checking.
Comment on lines 49 to 92
// We want to check that the workspace is `running`, the agent is
// `connected`, and the agent lifecycle state is `ready` to ensure the best
// possible scenario for attempting a connection.
//
// We can also choose to allow `start_timeout` and `start_error` for the
// agent state; this means the startup script did not successfully complete
// but the agent will accept SSH connections.
//
// Lastly we can also allow connections when the agent lifecycle state is
// `starting` if `login_before_ready` is true on the workspace response.
//
// Note that latest_build.status is derived from latest_build.job.status and
// latest_build.job.transition so there is no need to check those.
companion object {
fun from(workspace: Workspace, agent: WorkspaceAgent? = null) = when (workspace.latestBuild.status) {
WorkspaceStatus.PENDING -> QUEUED
WorkspaceStatus.STARTING -> STARTING
WorkspaceStatus.RUNNING -> when (agent?.status) {
WorkspaceAgentStatus.CONNECTED -> when (agent.lifecycleState) {
WorkspaceAgentLifecycleState.CREATED -> CREATED
WorkspaceAgentLifecycleState.STARTING -> if (agent.loginBeforeReady == true) AGENT_STARTING_READY else AGENT_STARTING
WorkspaceAgentLifecycleState.START_TIMEOUT -> START_TIMEOUT
WorkspaceAgentLifecycleState.START_ERROR -> START_ERROR
WorkspaceAgentLifecycleState.READY -> READY
WorkspaceAgentLifecycleState.SHUTTING_DOWN -> SHUTTING_DOWN
WorkspaceAgentLifecycleState.SHUTDOWN_TIMEOUT -> SHUTDOWN_TIMEOUT
WorkspaceAgentLifecycleState.SHUTDOWN_ERROR -> SHUTDOWN_ERROR
WorkspaceAgentLifecycleState.OFF -> OFF
}

WorkspaceAgentStatus.DISCONNECTED -> DISCONNECTED
WorkspaceAgentStatus.TIMEOUT -> TIMEOUT
WorkspaceAgentStatus.CONNECTING -> CONNECTING
else -> RUNNING
}

WorkspaceStatus.STOPPING -> STOPPING
WorkspaceStatus.STOPPED -> STOPPED
WorkspaceStatus.FAILED -> FAILED
WorkspaceStatus.CANCELING -> CANCELING
WorkspaceStatus.CANCELED -> CANCELED
WorkspaceStatus.DELETING -> DELETING
WorkspaceStatus.DELETED -> DELETED
}
Copy link
Member Author

@code-asher code-asher Apr 25, 2023

Choose a reason for hiding this comment

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

@mafredri does this look right to you?

I use this computed state to determine whether to enable the connect button:

val ready = listOf(
WorkspaceAndAgentStatus.READY, WorkspaceAndAgentStatus.START_ERROR,
WorkspaceAndAgentStatus.START_TIMEOUT, WorkspaceAndAgentStatus.AGENT_STARTING_READY
).contains(selectedObject?.agentStatus)
setNextButtonEnabled(ready && selectedObject?.agentOS == OS.LINUX)

Copy link
Member

Choose a reason for hiding this comment

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

Yep, it looks mostly correct 👍. The start timeout behaves a bit different so needs some extra consideration but didn't spot any other issues.

We can just check if the list is empty then add the workspace-only
"agent" model rather than duplicate the block.
Previously we only checked the workspace, now we also check the agent.
Should help ensure we only connect when the connection will succeed.
@code-asher code-asher marked this pull request as ready for review April 25, 2023 22:33
@code-asher code-asher requested review from johnstcn and mafredri April 25, 2023 22:33
* WorkspaceAndAgentStatus represents the combined status of a single agent and
* its workspace (or just the workspace if there are no agents).
*/
enum class WorkspaceAndAgentStatus(val label: String, val description: String) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Something feels a bit off to me about this, like maybe we should just have the workspace status and agent status and check both whenever we need to rather than have this computed state but my thoughts about it are a bit fuzzy and we already had it architectured like this so I left it for now.

Comment on lines 49 to 92
// We want to check that the workspace is `running`, the agent is
// `connected`, and the agent lifecycle state is `ready` to ensure the best
// possible scenario for attempting a connection.
//
// We can also choose to allow `start_timeout` and `start_error` for the
// agent state; this means the startup script did not successfully complete
// but the agent will accept SSH connections.
//
// Lastly we can also allow connections when the agent lifecycle state is
// `starting` if `login_before_ready` is true on the workspace response.
//
// Note that latest_build.status is derived from latest_build.job.status and
// latest_build.job.transition so there is no need to check those.
companion object {
fun from(workspace: Workspace, agent: WorkspaceAgent? = null) = when (workspace.latestBuild.status) {
WorkspaceStatus.PENDING -> QUEUED
WorkspaceStatus.STARTING -> STARTING
WorkspaceStatus.RUNNING -> when (agent?.status) {
WorkspaceAgentStatus.CONNECTED -> when (agent.lifecycleState) {
WorkspaceAgentLifecycleState.CREATED -> CREATED
WorkspaceAgentLifecycleState.STARTING -> if (agent.loginBeforeReady == true) AGENT_STARTING_READY else AGENT_STARTING
WorkspaceAgentLifecycleState.START_TIMEOUT -> START_TIMEOUT
WorkspaceAgentLifecycleState.START_ERROR -> START_ERROR
WorkspaceAgentLifecycleState.READY -> READY
WorkspaceAgentLifecycleState.SHUTTING_DOWN -> SHUTTING_DOWN
WorkspaceAgentLifecycleState.SHUTDOWN_TIMEOUT -> SHUTDOWN_TIMEOUT
WorkspaceAgentLifecycleState.SHUTDOWN_ERROR -> SHUTDOWN_ERROR
WorkspaceAgentLifecycleState.OFF -> OFF
}

WorkspaceAgentStatus.DISCONNECTED -> DISCONNECTED
WorkspaceAgentStatus.TIMEOUT -> TIMEOUT
WorkspaceAgentStatus.CONNECTING -> CONNECTING
else -> RUNNING
}

WorkspaceStatus.STOPPING -> STOPPING
WorkspaceStatus.STOPPED -> STOPPED
WorkspaceStatus.FAILED -> FAILED
WorkspaceStatus.CANCELING -> CANCELING
WorkspaceStatus.CANCELED -> CANCELED
WorkspaceStatus.DELETING -> DELETING
WorkspaceStatus.DELETED -> DELETED
}
Copy link
Member

Choose a reason for hiding this comment

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

Yep, it looks mostly correct 👍. The start timeout behaves a bit different so needs some extra consideration but didn't spot any other issues.

These mean the script is still running and is taking longer than
expected.

Also we can connect with login_before_ready when in the start_timeout
state.
I think it still has a chance to connect so this wording makes that
clearer.
@code-asher code-asher requested a review from mafredri April 26, 2023 18:07
Copy link
Member

@mafredri mafredri left a comment

Choose a reason for hiding this comment

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

Nice, LGTM!

@code-asher code-asher merged commit d2a3649 into main Apr 26, 2023
@code-asher code-asher deleted the ready-state branch April 26, 2023 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants