-
Notifications
You must be signed in to change notification settings - Fork 16
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
Conversation
Looks like there is already a property that is the composite of the two fields we were checking.
// 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 | ||
} |
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.
@mafredri does this look right to you?
I use this computed state to determine whether to enable the connect button:
jetbrains-coder/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt
Lines 135 to 139 in 664c383
val ready = listOf( | |
WorkspaceAndAgentStatus.READY, WorkspaceAndAgentStatus.START_ERROR, | |
WorkspaceAndAgentStatus.START_TIMEOUT, WorkspaceAndAgentStatus.AGENT_STARTING_READY | |
).contains(selectedObject?.agentStatus) | |
setNextButtonEnabled(ready && selectedObject?.agentOS == OS.LINUX) |
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.
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.
* 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) { |
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.
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.
src/main/kotlin/com/coder/gateway/models/WorkspaceAndAgentStatus.kt
Outdated
Show resolved
Hide resolved
src/main/kotlin/com/coder/gateway/models/WorkspaceAndAgentStatus.kt
Outdated
Show resolved
Hide resolved
src/main/kotlin/com/coder/gateway/models/WorkspaceAndAgentStatus.kt
Outdated
Show resolved
Hide resolved
src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt
Outdated
Show resolved
Hide resolved
// 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 | ||
} |
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.
Yep, it looks mostly correct 👍. The start timeout behaves a bit different so needs some extra consideration but didn't spot any other issues.
src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt
Outdated
Show resolved
Hide resolved
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.
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.
Nice, LGTM!
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.