Skip to content

Commit 66fbc02

Browse files
committed
refactor task status/state
1 parent 59c9c7e commit 66fbc02

File tree

3 files changed

+95
-120
lines changed

3 files changed

+95
-120
lines changed

coderd/aitasks.go

Lines changed: 54 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package coderd
22

33
import (
4+
"context"
45
"database/sql"
56
"errors"
67
"fmt"
@@ -190,49 +191,60 @@ func (api *API) tasksCreate(rw http.ResponseWriter, r *http.Request) {
190191
createWorkspace(ctx, aReq, apiKey.UserID, api, owner, createReq, rw, r)
191192
}
192193

193-
// tasksListResponse wraps a list of experimental tasks.
194-
//
195-
// Experimental: Response shape is experimental and may change.
196-
type tasksListResponse struct {
197-
Tasks []codersdk.Task `json:"tasks"`
198-
Count int `json:"count"`
199-
}
200-
201-
func mapTaskStatus(ws codersdk.Workspace) codersdk.TaskStatus {
202-
switch ws.LatestBuild.Status {
203-
case codersdk.WorkspaceStatusPending:
204-
return codersdk.TaskStatusPending
205-
206-
case codersdk.WorkspaceStatusStarting:
207-
return codersdk.TaskStatusStarting
194+
// tasksFromWorkspaces converts a slice of API workspaces into tasks, fetching
195+
// prompts and mapping status/state.
196+
func (api *API) tasksFromWorkspaces(ctx context.Context, apiWorkspaces []codersdk.Workspace) ([]codersdk.Task, error) {
197+
// Fetch prompts for each workspace build and map by build ID.
198+
buildIDs := make([]uuid.UUID, 0, len(apiWorkspaces))
199+
for _, ws := range apiWorkspaces {
200+
buildIDs = append(buildIDs, ws.LatestBuild.ID)
201+
}
202+
parameters, err := api.Database.GetWorkspaceBuildParametersByBuildIDs(ctx, buildIDs)
203+
if err != nil {
204+
return nil, err
205+
}
206+
promptsByBuildID := make(map[uuid.UUID]string, len(parameters))
207+
for _, p := range parameters {
208+
if p.Name == codersdk.AITaskPromptParameterName {
209+
promptsByBuildID[p.WorkspaceBuildID] = p.Value
210+
}
211+
}
208212

209-
case codersdk.WorkspaceStatusRunning:
213+
tasks := make([]codersdk.Task, 0, len(apiWorkspaces))
214+
for _, ws := range apiWorkspaces {
215+
var currentState *codersdk.TaskStateEntry
210216
if ws.LatestAppStatus != nil {
211-
switch ws.LatestAppStatus.State {
212-
case codersdk.WorkspaceAppStatusStateWorking:
213-
return codersdk.TaskStatusWorking
214-
case codersdk.WorkspaceAppStatusStateIdle:
215-
return codersdk.TaskStatusIdle
216-
case codersdk.WorkspaceAppStatusStateComplete:
217-
return codersdk.TaskStatusCompleted
218-
case codersdk.WorkspaceAppStatusStateFailure:
219-
return codersdk.TaskStatusFailed
217+
currentState = &codersdk.TaskStateEntry{
218+
Timestamp: ws.LatestAppStatus.CreatedAt,
219+
State: codersdk.TaskState(ws.LatestAppStatus.State),
220+
Message: ws.LatestAppStatus.Message,
221+
URI: ws.LatestAppStatus.URI,
220222
}
221223
}
222-
return codersdk.TaskStatusStarting
223-
224-
case codersdk.WorkspaceStatusStopping, codersdk.WorkspaceStatusStopped:
225-
return codersdk.TaskStatusStopping
226-
227-
case codersdk.WorkspaceStatusDeleting, codersdk.WorkspaceStatusDeleted:
228-
return codersdk.TaskStatusDeleting
224+
tasks = append(tasks, codersdk.Task{
225+
ID: ws.ID,
226+
OrganizationID: ws.OrganizationID,
227+
OwnerID: ws.OwnerID,
228+
Name: ws.Name,
229+
TemplateID: ws.TemplateID,
230+
WorkspaceID: uuid.NullUUID{Valid: true, UUID: ws.ID},
231+
CreatedAt: ws.CreatedAt,
232+
UpdatedAt: ws.UpdatedAt,
233+
Prompt: promptsByBuildID[ws.LatestBuild.ID],
234+
Status: ws.LatestBuild.Status,
235+
CurrentState: currentState,
236+
})
237+
}
229238

230-
case codersdk.WorkspaceStatusFailed, codersdk.WorkspaceStatusCanceling, codersdk.WorkspaceStatusCanceled:
231-
return codersdk.TaskStatusFailed
239+
return tasks, nil
240+
}
232241

233-
default:
234-
return codersdk.TaskStatusPending
235-
}
242+
// tasksListResponse wraps a list of experimental tasks.
243+
//
244+
// Experimental: Response shape is experimental and may change.
245+
type tasksListResponse struct {
246+
Tasks []codersdk.Task `json:"tasks"`
247+
Count int `json:"count"`
236248
}
237249

238250
// tasksList is an experimental endpoint to list AI tasks by mapping
@@ -323,41 +335,14 @@ func (api *API) tasksList(rw http.ResponseWriter, r *http.Request) {
323335
return
324336
}
325337

326-
// Fetch prompts for each workspace build and map by build ID.
327-
buildIDs := make([]uuid.UUID, 0, len(apiWorkspaces))
328-
for _, ws := range apiWorkspaces {
329-
buildIDs = append(buildIDs, ws.LatestBuild.ID)
330-
}
331-
parameters, err := api.Database.GetWorkspaceBuildParametersByBuildIDs(ctx, buildIDs)
338+
tasks, err := api.tasksFromWorkspaces(ctx, apiWorkspaces)
332339
if err != nil {
333340
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
334-
Message: "Internal error fetching task prompts.",
341+
Message: "Internal error fetching task prompts and states.",
335342
Detail: err.Error(),
336343
})
337344
return
338345
}
339-
promptsByBuildID := make(map[uuid.UUID]string, len(parameters))
340-
for _, p := range parameters {
341-
if p.Name == codersdk.AITaskPromptParameterName {
342-
promptsByBuildID[p.WorkspaceBuildID] = p.Value
343-
}
344-
}
345-
346-
tasks := make([]codersdk.Task, 0, len(apiWorkspaces))
347-
for _, ws := range apiWorkspaces {
348-
tasks = append(tasks, codersdk.Task{
349-
ID: ws.ID,
350-
OrganizationID: ws.OrganizationID,
351-
OwnerID: ws.OwnerID,
352-
Name: ws.Name,
353-
TemplateID: ws.TemplateID,
354-
WorkspaceID: uuid.NullUUID{Valid: true, UUID: ws.ID},
355-
Prompt: promptsByBuildID[ws.LatestBuild.ID],
356-
Status: mapTaskStatus(ws),
357-
CreatedAt: ws.CreatedAt,
358-
UpdatedAt: ws.UpdatedAt,
359-
})
360-
}
361346

362347
httpapi.Write(ctx, rw, http.StatusOK, tasksListResponse{
363348
Tasks: tasks,
@@ -432,35 +417,14 @@ func (api *API) taskGet(rw http.ResponseWriter, r *http.Request) {
432417
return
433418
}
434419

435-
// Fetch the AI prompt from the build parameters.
436-
params, err := api.Database.GetWorkspaceBuildParametersByBuildIDs(ctx, []uuid.UUID{ws.LatestBuild.ID})
420+
tasks, err := api.tasksFromWorkspaces(ctx, []codersdk.Workspace{ws})
437421
if err != nil {
438422
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
439-
Message: "Internal error fetching task prompt.",
423+
Message: "Internal error fetching task prompt and state.",
440424
Detail: err.Error(),
441425
})
442426
return
443427
}
444-
prompt := ""
445-
for _, p := range params {
446-
if p.Name == codersdk.AITaskPromptParameterName {
447-
prompt = p.Value
448-
break
449-
}
450-
}
451-
452-
resp := codersdk.Task{
453-
ID: ws.ID,
454-
OrganizationID: ws.OrganizationID,
455-
OwnerID: ws.OwnerID,
456-
Name: ws.Name,
457-
TemplateID: ws.TemplateID,
458-
WorkspaceID: uuid.NullUUID{Valid: true, UUID: ws.ID},
459-
Prompt: prompt,
460-
Status: mapTaskStatus(ws),
461-
CreatedAt: ws.CreatedAt,
462-
UpdatedAt: ws.UpdatedAt,
463-
}
464428

465-
httpapi.Write(ctx, rw, http.StatusOK, resp)
429+
httpapi.Write(ctx, rw, http.StatusOK, tasks[0])
466430
}

codersdk/aitasks.go

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -72,44 +72,51 @@ func (c *ExperimentalClient) CreateTask(ctx context.Context, user string, reques
7272
return workspace, nil
7373
}
7474

75-
// TaskStatus represents the high-level lifecycle of a task.
75+
// TaskState represents the high-level lifecycle of a task.
7676
//
7777
// Experimental: This type is experimental and may change in the future.
78-
type TaskStatus string
78+
type TaskState string
7979

8080
const (
81-
TaskStatusPending TaskStatus = "pending"
82-
TaskStatusStarting TaskStatus = "starting"
83-
TaskStatusStopping TaskStatus = "stopping"
84-
TaskStatusDeleting TaskStatus = "deleting"
85-
TaskStatusWorking TaskStatus = "working"
86-
TaskStatusIdle TaskStatus = "idle"
87-
TaskStatusCompleted TaskStatus = "completed"
88-
TaskStatusFailed TaskStatus = "failed"
81+
TaskStateWorking TaskState = "working"
82+
TaskStateIdle TaskState = "idle"
83+
TaskStateCompleted TaskState = "completed"
84+
TaskStateFailed TaskState = "failed"
8985
)
9086

91-
// TasksFilter filters the list of tasks.
87+
// Task represents a task.
9288
//
9389
// Experimental: This type is experimental and may change in the future.
94-
type TasksFilter struct {
95-
// Owner can be a username, UUID, or "me"
96-
Owner string `json:"owner,omitempty"`
90+
type Task struct {
91+
ID uuid.UUID `json:"id" format:"uuid"`
92+
OrganizationID uuid.UUID `json:"organization_id" format:"uuid"`
93+
OwnerID uuid.UUID `json:"owner_id" format:"uuid"`
94+
Name string `json:"name"`
95+
TemplateID uuid.UUID `json:"template_id" format:"uuid"`
96+
WorkspaceID uuid.NullUUID `json:"workspace_id" format:"uuid"`
97+
Prompt string `json:"prompt"`
98+
Status WorkspaceStatus `json:"status" enums:"pending,starting,running,stopping,stopped,failed,canceling,canceled,deleting,deleted"`
99+
CurrentState *TaskStateEntry `json:"current_state"`
100+
CreatedAt time.Time `json:"created_at" format:"date-time"`
101+
UpdatedAt time.Time `json:"updated_at" format:"date-time"`
97102
}
98103

99-
// Task represents a task.
104+
// TaskStateEntry represents a single entry in the task's state history.
100105
//
101106
// Experimental: This type is experimental and may change in the future.
102-
type Task struct {
103-
ID uuid.UUID `json:"id" format:"uuid"`
104-
OrganizationID uuid.UUID `json:"organization_id" format:"uuid"`
105-
OwnerID uuid.UUID `json:"owner_id" format:"uuid"`
106-
Name string `json:"name"`
107-
TemplateID uuid.UUID `json:"template_id" format:"uuid"`
108-
WorkspaceID uuid.NullUUID `json:"workspace_id" format:"uuid"`
109-
Prompt string `json:"prompt"`
110-
Status TaskStatus `json:"status" enum:"pending,starting,stopping,deleting,working,idle,completed,failed"`
111-
CreatedAt time.Time `json:"created_at" format:"date-time"`
112-
UpdatedAt time.Time `json:"updated_at" format:"date-time"`
107+
type TaskStateEntry struct {
108+
Timestamp time.Time `json:"timestamp" format:"date-time"`
109+
State TaskState `json:"state" enum:"working,idle,completed,failed"`
110+
Message string `json:"message"`
111+
URI string `json:"uri"`
112+
}
113+
114+
// TasksFilter filters the list of tasks.
115+
//
116+
// Experimental: This type is experimental and may change in the future.
117+
type TasksFilter struct {
118+
// Owner can be a username, UUID, or "me"
119+
Owner string `json:"owner,omitempty"`
113120
}
114121

115122
// Tasks lists all tasks belonging to the user or specified owner.

site/src/api/typesGenerated.ts

Lines changed: 8 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy