Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions packages/api/internal/api/api.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

217 changes: 110 additions & 107 deletions packages/api/internal/api/spec.gen.go

Large diffs are not rendered by default.

92 changes: 82 additions & 10 deletions packages/api/internal/api/types.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 25 additions & 39 deletions packages/api/internal/handlers/sandboxes_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,11 @@ import (
)

const (
maxSandboxListLimit int32 = 100
defaultSandboxListLimit int32 = 100
sandboxesDefaultLimit = int32(100)
sandboxesMaxLimit = int32(100)
)

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) {
// Apply limit + 1 to check if there are more results
queryLimit := limit + 1
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) {
queryMetadata := dbtypes.JSONBStringMap{}
if metadataFilter != nil {
queryMetadata = *metadataFilter
Expand Down Expand Up @@ -115,14 +113,23 @@ func (a *APIStore) GetV2Sandboxes(c *gin.Context, params api.GetV2SandboxesParam
states = append(states, *params.State...)
}

limit := defaultSandboxListLimit
if params.Limit != nil {
limit = *params.Limit
}
// Initialize pagination
pagination, err := utils.NewPagination[utils.PaginatedSandbox](
utils.PaginationParams{
Limit: params.Limit,
NextToken: params.NextToken,
},
utils.PaginationConfig{
DefaultLimit: sandboxesDefaultLimit,
MaxLimit: sandboxesMaxLimit,
DefaultID: utils.MaxSandboxID,
},
)
if err != nil {
telemetry.ReportError(ctx, "error parsing pagination cursor", err)
a.sendAPIStoreError(c, http.StatusBadRequest, "Invalid next token")

// Clip limit to max
if limit > maxSandboxListLimit {
limit = maxSandboxListLimit
return
}

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

// Parse the next token to offset sandboxes for pagination
cursorTime, cursorID, err := utils.ParseNextToken(params.NextToken)
if err != nil {
zap.L().Error("Error parsing cursor", zap.Error(err))
a.sendAPIStoreError(c, http.StatusBadRequest, "Invalid next token")

return
}

allSandboxes := a.orchestrator.GetSandboxes(ctx, team.ID, []sandbox.State{sandbox.StateRunning, sandbox.StatePausing})
runningSandboxes := sharedUtils.Filter(allSandboxes, func(sbx sandbox.Sandbox) bool {
return sbx.State == sandbox.StateRunning
Expand All @@ -163,7 +161,7 @@ func (a *APIStore) GetV2Sandboxes(c *gin.Context, params api.GetV2SandboxesParam
c.Header("X-Total-Running", strconv.Itoa(len(runningSandboxList)))

// Filter based on cursor
runningSandboxList = utils.FilterBasedOnCursor(runningSandboxList, cursorTime, cursorID)
runningSandboxList = utils.FilterBasedOnCursor(runningSandboxList, pagination.CursorTime(), pagination.CursorID())

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

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

pausingSandboxList := instanceInfoToPaginatedSandboxes(pausingSandboxes)
pausingSandboxList = utils.FilterSandboxesOnMetadata(pausingSandboxList, metadataFilter)
pausingSandboxList = utils.FilterBasedOnCursor(pausingSandboxList, cursorTime, cursorID)
pausingSandboxList = utils.FilterBasedOnCursor(pausingSandboxList, pagination.CursorTime(), pagination.CursorID())

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

var nextToken *string
if len(sandboxes) > int(limit) {
// We have more results than the limit, so we need to set the nextToken
lastSandbox := sandboxes[limit-1]
cursor := lastSandbox.GenerateCursor()
nextToken = &cursor

// Trim to the requested limit
sandboxes = sandboxes[:limit]
}

// Add pagination info to headers
if nextToken != nil {
c.Header("X-Next-Token", *nextToken)
}
sandboxes = pagination.ProcessResultsWithHeader(c, sandboxes, func(s utils.PaginatedSandbox) (time.Time, string) {
return s.PaginationTimestamp, s.SandboxID
})

c.JSON(http.StatusOK, sandboxes)
}
Expand Down
2 changes: 2 additions & 0 deletions packages/api/internal/handlers/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import (
// This is a security measure to prevent the use of weak secrets (like empty).
const minSupabaseJWTSecretLength = 16

var _ api.ServerInterface = (*APIStore)(nil)

type APIStore struct {
Healthy bool
config cfg.Config
Expand Down
4 changes: 2 additions & 2 deletions packages/api/internal/handlers/template_build_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func (a *APIStore) GetTemplatesTemplateIDBuildsBuildIDStatus(c *gin.Context, tem

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

// Needs to be before logs request so the status is not set to done too early
result := api.TemplateBuild{
result := api.TemplateBuildInfo{
LogEntries: nil,
Logs: nil,
TemplateID: templateID,
Expand Down
Loading
Loading