Skip to content

Commit 2c3e031

Browse files
authored
feat: Return job ids when workflows are created (closes: #1155) (#1156)
1 parent 8bad484 commit 2c3e031

6 files changed

Lines changed: 135 additions & 26 deletions

File tree

‎apps/workspace-engine/oapi/openapi.json‎

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3241,6 +3241,52 @@
32413241
],
32423242
"type": "object"
32433243
},
3244+
"WorkflowRunJob": {
3245+
"properties": {
3246+
"jobAgentId": {
3247+
"description": "Job agent the job was dispatched to",
3248+
"type": "string"
3249+
},
3250+
"jobId": {
3251+
"description": "Job id; poll its status via GET /v1/workspaces/{workspaceId}/jobs/{jobId}",
3252+
"type": "string"
3253+
}
3254+
},
3255+
"required": [
3256+
"jobId",
3257+
"jobAgentId"
3258+
],
3259+
"type": "object"
3260+
},
3261+
"WorkflowRunResult": {
3262+
"properties": {
3263+
"id": {
3264+
"description": "Workflow run id",
3265+
"type": "string"
3266+
},
3267+
"inputs": {
3268+
"additionalProperties": true,
3269+
"type": "object"
3270+
},
3271+
"jobs": {
3272+
"description": "Jobs created and dispatched for this run",
3273+
"items": {
3274+
"$ref": "#/components/schemas/WorkflowRunJob"
3275+
},
3276+
"type": "array"
3277+
},
3278+
"workflowId": {
3279+
"type": "string"
3280+
}
3281+
},
3282+
"required": [
3283+
"id",
3284+
"workflowId",
3285+
"inputs",
3286+
"jobs"
3287+
],
3288+
"type": "object"
3289+
},
32443290
"WorkflowStringInput": {
32453291
"properties": {
32463292
"default": {
@@ -4037,7 +4083,7 @@
40374083
"content": {
40384084
"application/json": {
40394085
"schema": {
4040-
"$ref": "#/components/schemas/WorkflowRun"
4086+
"$ref": "#/components/schemas/WorkflowRunResult"
40414087
}
40424088
}
40434089
},

‎apps/workspace-engine/oapi/spec/paths/workflows.jsonnet‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ local openapi = import '../lib/openapi.libsonnet';
2828
},
2929
},
3030
},
31-
responses: openapi.okResponse(openapi.schemaRef('WorkflowRun'))
31+
responses: openapi.okResponse(openapi.schemaRef('WorkflowRunResult'))
3232
+ openapi.notFoundResponse()
3333
+ openapi.badRequestResponse(),
3434
},

‎apps/workspace-engine/oapi/spec/schemas/workflows.jsonnet‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,33 @@ local openapi = import '../lib/openapi.libsonnet';
5555
},
5656
},
5757

58+
WorkflowRunJob: {
59+
type: 'object',
60+
required: ['jobId', 'jobAgentId'],
61+
properties: {
62+
jobId: { type: 'string', description: 'Job id; poll its status via GET /v1/workspaces/{workspaceId}/jobs/{jobId}' },
63+
jobAgentId: { type: 'string', description: 'Job agent the job was dispatched to' },
64+
},
65+
},
66+
67+
WorkflowRunResult: {
68+
type: 'object',
69+
required: ['id', 'workflowId', 'inputs', 'jobs'],
70+
properties: {
71+
id: { type: 'string', description: 'Workflow run id' },
72+
workflowId: { type: 'string' },
73+
inputs: {
74+
type: 'object',
75+
additionalProperties: true,
76+
},
77+
jobs: {
78+
type: 'array',
79+
description: 'Jobs created and dispatched for this run',
80+
items: openapi.schemaRef('WorkflowRunJob'),
81+
},
82+
},
83+
},
84+
5885
WorkflowStringInput: {
5986
type: 'object',
6087
required: ['key', 'type'],

‎apps/workspace-engine/pkg/oapi/oapi.gen.go‎

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

‎apps/workspace-engine/svc/http/server/openapi/workflows/setters.go‎

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type Setter interface {
2020
workspaceID string,
2121
workflow *oapi.Workflow,
2222
inputs map[string]any,
23-
) error
23+
) (*oapi.WorkflowRunResult, error)
2424
}
2525

2626
var _ Setter = &PostgresSetter{}
@@ -48,17 +48,17 @@ func (s *PostgresSetter) CreateWorkflowRun(
4848
workspaceID string,
4949
workflow *oapi.Workflow,
5050
inputs map[string]any,
51-
) error {
51+
) (*oapi.WorkflowRunResult, error) {
5252
dispatchContext := s.buildDispatchContext(workflow, inputs)
5353

5454
workflowIDUUID, err := uuid.Parse(workflow.Id)
5555
if err != nil {
56-
return fmt.Errorf("parse workflow id: %w", err)
56+
return nil, fmt.Errorf("parse workflow id: %w", err)
5757
}
5858

5959
tx, err := db.GetPool(ctx).Begin(ctx)
6060
if err != nil {
61-
return fmt.Errorf("begin transaction: %w", err)
61+
return nil, fmt.Errorf("begin transaction: %w", err)
6262
}
6363
defer func() { _ = tx.Rollback(ctx) }()
6464

@@ -69,30 +69,42 @@ func (s *PostgresSetter) CreateWorkflowRun(
6969
Inputs: inputs,
7070
})
7171
if err != nil {
72-
return fmt.Errorf("insert workflow run: %w", err)
72+
return nil, fmt.Errorf("insert workflow run: %w", err)
7373
}
7474

75+
jobs := make([]oapi.WorkflowRunJob, 0, len(workflow.Jobs))
7576
for _, jobAgent := range workflow.Jobs {
7677
isMatchingSelector, err := selector.Match(ctx, jobAgent.Selector, *dispatchContext)
7778
if err != nil {
78-
return fmt.Errorf("match selector: %w", err)
79+
return nil, fmt.Errorf("match selector: %w", err)
7980
}
8081
if !isMatchingSelector {
8182
continue
8283
}
83-
if err := s.dispatchJobForAgent(
84+
job, err := s.dispatchJobForAgent(
8485
ctx,
8586
queries,
8687
jobAgent,
8788
workflowRun.ID,
8889
dispatchContext,
8990
workspaceID,
90-
); err != nil {
91-
return err
91+
)
92+
if err != nil {
93+
return nil, err
9294
}
95+
jobs = append(jobs, job)
9396
}
9497

95-
return tx.Commit(ctx)
98+
if err := tx.Commit(ctx); err != nil {
99+
return nil, fmt.Errorf("commit transaction: %w", err)
100+
}
101+
102+
return &oapi.WorkflowRunResult{
103+
Id: workflowRun.ID.String(),
104+
WorkflowId: workflow.Id,
105+
Inputs: inputs,
106+
Jobs: jobs,
107+
}, nil
96108
}
97109

98110
// mergeWorkflowJobAgentConfig builds the JobAgentConfig that ends up on a
@@ -136,34 +148,34 @@ func (s *PostgresSetter) dispatchJobForAgent(
136148
workflowRunID uuid.UUID,
137149
dispatchContext *oapi.DispatchContext,
138150
workspaceID string,
139-
) error {
151+
) (oapi.WorkflowRunJob, error) {
140152
jobAgentIDUUID, err := uuid.Parse(jobAgent.Ref)
141153
if err != nil {
142-
return fmt.Errorf("parse job agent id: %w", err)
154+
return oapi.WorkflowRunJob{}, fmt.Errorf("parse job agent id: %w", err)
143155
}
144156
workspaceIDUUID, err := uuid.Parse(workspaceID)
145157
if err != nil {
146-
return fmt.Errorf("parse workspace id: %w", err)
158+
return oapi.WorkflowRunJob{}, fmt.Errorf("parse workspace id: %w", err)
147159
}
148160
runner, err := queries.GetJobAgentByID(ctx, jobAgentIDUUID)
149161
if err != nil {
150-
return fmt.Errorf("get job agent: %w", err)
162+
return oapi.WorkflowRunJob{}, fmt.Errorf("get job agent: %w", err)
151163
}
152164
if runner.WorkspaceID != workspaceIDUUID {
153-
return fmt.Errorf(
165+
return oapi.WorkflowRunJob{}, fmt.Errorf(
154166
"job agent %s does not belong to workspace %s",
155167
jobAgentIDUUID, workspaceIDUUID,
156168
)
157169
}
158170
mergedConfig := mergeWorkflowJobAgentConfig(runner.Config, jobAgent.Config)
159171
jobAgentConfig, err := json.Marshal(mergedConfig)
160172
if err != nil {
161-
return fmt.Errorf("marshal job agent config: %w", err)
173+
return oapi.WorkflowRunJob{}, fmt.Errorf("marshal job agent config: %w", err)
162174
}
163175
jobDispatchContext := buildJobDispatchContext(dispatchContext, runner, mergedConfig)
164176
dispatchContextJSON, err := json.Marshal(jobDispatchContext)
165177
if err != nil {
166-
return fmt.Errorf("marshal dispatch context: %w", err)
178+
return oapi.WorkflowRunJob{}, fmt.Errorf("marshal dispatch context: %w", err)
167179
}
168180

169181
now := pgtype.Timestamptz{Time: time.Now().UTC(), Valid: true}
@@ -178,14 +190,14 @@ func (s *PostgresSetter) dispatchJobForAgent(
178190
CreatedAt: now,
179191
UpdatedAt: now,
180192
}); err != nil {
181-
return fmt.Errorf("insert job: %w", err)
193+
return oapi.WorkflowRunJob{}, fmt.Errorf("insert job: %w", err)
182194
}
183195

184196
if _, err := queries.InsertWorkflowJob(ctx, db.InsertWorkflowJobParams{
185197
WorkflowRunID: workflowRunID,
186198
JobID: jobID,
187199
}); err != nil {
188-
return fmt.Errorf("insert workflow job: %w", err)
200+
return oapi.WorkflowRunJob{}, fmt.Errorf("insert workflow job: %w", err)
189201
}
190202

191203
if err := s.queue.Enqueue(ctx, reconcile.EnqueueParams{
@@ -194,8 +206,11 @@ func (s *PostgresSetter) dispatchJobForAgent(
194206
ScopeType: "job",
195207
ScopeID: jobID.String(),
196208
}); err != nil {
197-
return fmt.Errorf("enqueue job dispatch: %w", err)
209+
return oapi.WorkflowRunJob{}, fmt.Errorf("enqueue job dispatch: %w", err)
198210
}
199211

200-
return nil
212+
return oapi.WorkflowRunJob{
213+
JobId: jobID.String(),
214+
JobAgentId: jobAgentIDUUID.String(),
215+
}, nil
201216
}

‎apps/workspace-engine/svc/http/server/openapi/workflows/workflows.go‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,16 @@ func (w *Workflows) CreateWorkflowRun(
9494
return
9595
}
9696

97-
if err := w.setter.CreateWorkflowRun(
97+
result, err := w.setter.CreateWorkflowRun(
9898
c.Request.Context(),
9999
workspaceId,
100100
workflow,
101101
inputs,
102-
); err != nil {
102+
)
103+
if err != nil {
103104
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
104105
return
105106
}
106107

107-
c.JSON(http.StatusOK, gin.H{"message": "Workflow run created"})
108+
c.JSON(http.StatusOK, result)
108109
}

0 commit comments

Comments
 (0)