Skip to content

Commit 249e984

Browse files
authored
feat: add list of builds per template (#1408)
1 parent fb4a33e commit 249e984

18 files changed

Lines changed: 1558 additions & 197 deletions

packages/api/internal/api/api.gen.go

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

packages/api/internal/api/spec.gen.go

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

packages/api/internal/api/types.gen.go

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

packages/api/internal/handlers/sandboxes_list.go

Lines changed: 25 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,11 @@ import (
2727
)
2828

2929
const (
30-
maxSandboxListLimit int32 = 100
31-
defaultSandboxListLimit int32 = 100
30+
sandboxesDefaultLimit = int32(100)
31+
sandboxesMaxLimit = int32(100)
3232
)
3333

34-
func (a *APIStore) getPausedSandboxes(ctx context.Context, teamID uuid.UUID, runningSandboxesIDs []string, metadataFilter *map[string]string, limit int32, cursorTime time.Time, cursorID string) ([]utils.PaginatedSandbox, error) {
35-
// Apply limit + 1 to check if there are more results
36-
queryLimit := limit + 1
34+
func (a *APIStore) getPausedSandboxes(ctx context.Context, teamID uuid.UUID, runningSandboxesIDs []string, metadataFilter *map[string]string, queryLimit int32, cursorTime time.Time, cursorID string) ([]utils.PaginatedSandbox, error) {
3735
queryMetadata := dbtypes.JSONBStringMap{}
3836
if metadataFilter != nil {
3937
queryMetadata = *metadataFilter
@@ -115,14 +113,23 @@ func (a *APIStore) GetV2Sandboxes(c *gin.Context, params api.GetV2SandboxesParam
115113
states = append(states, *params.State...)
116114
}
117115

118-
limit := defaultSandboxListLimit
119-
if params.Limit != nil {
120-
limit = *params.Limit
121-
}
116+
// Initialize pagination
117+
pagination, err := utils.NewPagination[utils.PaginatedSandbox](
118+
utils.PaginationParams{
119+
Limit: params.Limit,
120+
NextToken: params.NextToken,
121+
},
122+
utils.PaginationConfig{
123+
DefaultLimit: sandboxesDefaultLimit,
124+
MaxLimit: sandboxesMaxLimit,
125+
DefaultID: utils.MaxSandboxID,
126+
},
127+
)
128+
if err != nil {
129+
telemetry.ReportError(ctx, "error parsing pagination cursor", err)
130+
a.sendAPIStoreError(c, http.StatusBadRequest, "Invalid next token")
122131

123-
// Clip limit to max
124-
if limit > maxSandboxListLimit {
125-
limit = maxSandboxListLimit
132+
return
126133
}
127134

128135
metadataFilter, err := utils.ParseMetadata(params.Metadata)
@@ -136,15 +143,6 @@ func (a *APIStore) GetV2Sandboxes(c *gin.Context, params api.GetV2SandboxesParam
136143
// Get sandboxes with pagination
137144
sandboxes := make([]utils.PaginatedSandbox, 0)
138145

139-
// Parse the next token to offset sandboxes for pagination
140-
cursorTime, cursorID, err := utils.ParseNextToken(params.NextToken)
141-
if err != nil {
142-
zap.L().Error("Error parsing cursor", zap.Error(err))
143-
a.sendAPIStoreError(c, http.StatusBadRequest, "Invalid next token")
144-
145-
return
146-
}
147-
148146
allSandboxes := a.orchestrator.GetSandboxes(ctx, team.ID, []sandbox.State{sandbox.StateRunning, sandbox.StatePausing})
149147
runningSandboxes := sharedUtils.Filter(allSandboxes, func(sbx sandbox.Sandbox) bool {
150148
return sbx.State == sandbox.StateRunning
@@ -163,7 +161,7 @@ func (a *APIStore) GetV2Sandboxes(c *gin.Context, params api.GetV2SandboxesParam
163161
c.Header("X-Total-Running", strconv.Itoa(len(runningSandboxList)))
164162

165163
// Filter based on cursor
166-
runningSandboxList = utils.FilterBasedOnCursor(runningSandboxList, cursorTime, cursorID)
164+
runningSandboxList = utils.FilterBasedOnCursor(runningSandboxList, pagination.CursorTime(), pagination.CursorID())
167165

168166
sandboxes = append(sandboxes, runningSandboxList...)
169167
}
@@ -178,7 +176,7 @@ func (a *APIStore) GetV2Sandboxes(c *gin.Context, params api.GetV2SandboxesParam
178176
runningSandboxesIDs = append(runningSandboxesIDs, utils.ShortID(info.SandboxID))
179177
}
180178

181-
pausedSandboxList, err := a.getPausedSandboxes(ctx, team.ID, runningSandboxesIDs, metadataFilter, limit, cursorTime, cursorID)
179+
pausedSandboxList, err := a.getPausedSandboxes(ctx, team.ID, runningSandboxesIDs, metadataFilter, pagination.QueryLimit(), pagination.CursorTime(), pagination.CursorID())
182180
if err != nil {
183181
zap.L().Error("Error getting paused sandboxes", zap.Error(err))
184182
a.sendAPIStoreError(c, http.StatusInternalServerError, "Error getting paused sandboxes")
@@ -188,7 +186,7 @@ func (a *APIStore) GetV2Sandboxes(c *gin.Context, params api.GetV2SandboxesParam
188186

189187
pausingSandboxList := instanceInfoToPaginatedSandboxes(pausingSandboxes)
190188
pausingSandboxList = utils.FilterSandboxesOnMetadata(pausingSandboxList, metadataFilter)
191-
pausingSandboxList = utils.FilterBasedOnCursor(pausingSandboxList, cursorTime, cursorID)
189+
pausingSandboxList = utils.FilterBasedOnCursor(pausingSandboxList, pagination.CursorTime(), pagination.CursorID())
192190

193191
sandboxes = append(sandboxes, pausedSandboxList...)
194192
sandboxes = append(sandboxes, pausingSandboxList...)
@@ -197,21 +195,9 @@ func (a *APIStore) GetV2Sandboxes(c *gin.Context, params api.GetV2SandboxesParam
197195
// We need to sort again after merging running and paused sandboxes
198196
utils.SortPaginatedSandboxesDesc(sandboxes)
199197

200-
var nextToken *string
201-
if len(sandboxes) > int(limit) {
202-
// We have more results than the limit, so we need to set the nextToken
203-
lastSandbox := sandboxes[limit-1]
204-
cursor := lastSandbox.GenerateCursor()
205-
nextToken = &cursor
206-
207-
// Trim to the requested limit
208-
sandboxes = sandboxes[:limit]
209-
}
210-
211-
// Add pagination info to headers
212-
if nextToken != nil {
213-
c.Header("X-Next-Token", *nextToken)
214-
}
198+
sandboxes = pagination.ProcessResultsWithHeader(c, sandboxes, func(s utils.PaginatedSandbox) (time.Time, string) {
199+
return s.PaginationTimestamp, s.SandboxID
200+
})
215201

216202
c.JSON(http.StatusOK, sandboxes)
217203
}

packages/api/internal/handlers/store.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ import (
3939
// This is a security measure to prevent the use of weak secrets (like empty).
4040
const minSupabaseJWTSecretLength = 16
4141

42+
var _ api.ServerInterface = (*APIStore)(nil)
43+
4244
type APIStore struct {
4345
Healthy bool
4446
config cfg.Config

packages/api/internal/handlers/template_build_status.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func (a *APIStore) GetTemplatesTemplateIDBuildsBuildIDStatus(c *gin.Context, tem
6565

6666
// early return if still waiting for build start
6767
if buildInfo.BuildStatus == envbuild.StatusWaiting {
68-
result := api.TemplateBuild{
68+
result := api.TemplateBuildInfo{
6969
LogEntries: make([]api.BuildLogEntry, 0),
7070
Logs: make([]string, 0),
7171
TemplateID: templateID,
@@ -79,7 +79,7 @@ func (a *APIStore) GetTemplatesTemplateIDBuildsBuildIDStatus(c *gin.Context, tem
7979
}
8080

8181
// Needs to be before logs request so the status is not set to done too early
82-
result := api.TemplateBuild{
82+
result := api.TemplateBuildInfo{
8383
LogEntries: nil,
8484
Logs: nil,
8585
TemplateID: templateID,

0 commit comments

Comments
 (0)