mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
feat: make process output blocking-capable (#23312)
Replace the 200ms polling loop in chatd's execute and
process_output tools with server-side blocking via sync.Cond
on HeadTailBuffer.
The agent's GET /{id}/output endpoint accepts ?wait=true to
block until the process exits or a 5-minute server cap expires.
The process_output tool blocks by default for 10s (overridable
via wait_timeout), and falls back to a non-blocking snapshot on
timeout. The execute tool's foreground path makes a single
blocking call instead of polling.
Related #23316
This commit is contained in:
committed by
GitHub
parent
c8e58575e0
commit
41e15ae440
@@ -70,7 +70,7 @@ type AgentConn interface {
|
||||
ListeningPorts(ctx context.Context) (codersdk.WorkspaceAgentListeningPortsResponse, error)
|
||||
Netcheck(ctx context.Context) (healthsdk.AgentNetcheckReport, error)
|
||||
Ping(ctx context.Context) (time.Duration, bool, *ipnstate.PingResult, error)
|
||||
ProcessOutput(ctx context.Context, id string) (ProcessOutputResponse, error)
|
||||
ProcessOutput(ctx context.Context, id string, opts *ProcessOutputOptions) (ProcessOutputResponse, error)
|
||||
PrometheusMetrics(ctx context.Context) ([]byte, error)
|
||||
ReconnectingPTY(ctx context.Context, id uuid.UUID, height uint16, width uint16, command string, initOpts ...AgentReconnectingPTYInitOption) (net.Conn, error)
|
||||
DeleteDevcontainer(ctx context.Context, devcontainerID string) error
|
||||
@@ -715,6 +715,14 @@ type ProcessOutputResponse struct {
|
||||
ExitCode *int `json:"exit_code,omitempty"`
|
||||
}
|
||||
|
||||
// ProcessOutputOptions configures blocking behavior for
|
||||
// process output retrieval.
|
||||
type ProcessOutputOptions struct {
|
||||
// Wait enables blocking mode. When true, the request
|
||||
// blocks until the process exits or the context expires.
|
||||
Wait bool
|
||||
}
|
||||
|
||||
// ProcessTruncation describes how process output was truncated.
|
||||
type ProcessTruncation struct {
|
||||
OriginalBytes int `json:"original_bytes"`
|
||||
@@ -946,10 +954,14 @@ func (c *agentConn) ListProcesses(ctx context.Context) (ListProcessesResponse, e
|
||||
}
|
||||
|
||||
// ProcessOutput returns the output of a tracked process on the agent.
|
||||
func (c *agentConn) ProcessOutput(ctx context.Context, id string) (ProcessOutputResponse, error) {
|
||||
func (c *agentConn) ProcessOutput(ctx context.Context, id string, opts *ProcessOutputOptions) (ProcessOutputResponse, error) {
|
||||
ctx, span := tracing.StartSpan(ctx)
|
||||
defer span.End()
|
||||
res, err := c.apiRequest(ctx, http.MethodGet, "/api/v0/processes/"+id+"/output", nil)
|
||||
path := "/api/v0/processes/" + id + "/output"
|
||||
if opts != nil && opts.Wait {
|
||||
path += "?wait=true"
|
||||
}
|
||||
res, err := c.apiRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return ProcessOutputResponse{}, xerrors.Errorf("do request: %w", err)
|
||||
}
|
||||
|
||||
@@ -308,18 +308,18 @@ func (mr *MockAgentConnMockRecorder) Ping(ctx any) *gomock.Call {
|
||||
}
|
||||
|
||||
// ProcessOutput mocks base method.
|
||||
func (m *MockAgentConn) ProcessOutput(ctx context.Context, id string) (workspacesdk.ProcessOutputResponse, error) {
|
||||
func (m *MockAgentConn) ProcessOutput(ctx context.Context, id string, opts *workspacesdk.ProcessOutputOptions) (workspacesdk.ProcessOutputResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ProcessOutput", ctx, id)
|
||||
ret := m.ctrl.Call(m, "ProcessOutput", ctx, id, opts)
|
||||
ret0, _ := ret[0].(workspacesdk.ProcessOutputResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ProcessOutput indicates an expected call of ProcessOutput.
|
||||
func (mr *MockAgentConnMockRecorder) ProcessOutput(ctx, id any) *gomock.Call {
|
||||
func (mr *MockAgentConnMockRecorder) ProcessOutput(ctx, id, opts any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessOutput", reflect.TypeOf((*MockAgentConn)(nil).ProcessOutput), ctx, id)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessOutput", reflect.TypeOf((*MockAgentConn)(nil).ProcessOutput), ctx, id, opts)
|
||||
}
|
||||
|
||||
// PrometheusMetrics mocks base method.
|
||||
|
||||
Reference in New Issue
Block a user