Skip to content

feat: add pagination for server entities #1347

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 27, 2024
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
1,950 changes: 1,486 additions & 464 deletions api/openapispec/docs.go

Large diffs are not rendered by default.

1,950 changes: 1,486 additions & 464 deletions api/openapispec/swagger.json

Large diffs are not rendered by default.

1,177 changes: 856 additions & 321 deletions api/openapispec/swagger.yaml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pkg/domain/constant/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ const (
ResourcePageDefault = 1
ResourcePageSizeDefault = 100
ResourcePageSizeLarge = 1000
RunPageDefault = 1
RunPageSizeDefault = 10
CommonPageDefault = 1
CommonPageSizeDefault = 10
)
9 changes: 9 additions & 0 deletions pkg/domain/entity/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ type Backend struct {
UpdateTimestamp time.Time `yaml:"updateTimestamp,omitempty" json:"updateTimestamp,omitempty"`
}

type BackendFilter struct {
Pagination *Pagination
}

type BackendListResult struct {
Backends []*Backend
Total int
}

// Validate checks if the backend is valid.
// It returns an error if the backend is not valid.
func (w *Backend) Validate() error {
Expand Down
7 changes: 7 additions & 0 deletions pkg/domain/entity/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ type ModuleWithVersion struct {
type ModuleFilter struct {
// ModuleName is the name of the module to filter by.
ModuleName string
Pagination *Pagination
}

type ModuleListResult struct {
Modules []*Module
ModulesWithVersion []*ModuleWithVersion
Total int
}

// Validate checks if the module is valid.
Expand Down
9 changes: 9 additions & 0 deletions pkg/domain/entity/organization.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ type Organization struct {
UpdateTimestamp time.Time `yaml:"updateTimestamp,omitempty" json:"updateTimestamp,omitempty"`
}

type OrganizationFilter struct {
Pagination *Pagination
}

type OrganizationListResult struct {
Organizations []*Organization
Total int
}

// Validate checks if the organization is valid.
// It returns an error if the organization is not valid.
func (p *Organization) Validate() error {
Expand Down
10 changes: 8 additions & 2 deletions pkg/domain/entity/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,14 @@ type Project struct {
}

type ProjectFilter struct {
OrgID uint
Name string
OrgID uint
Name string
Pagination *Pagination
}

type ProjectListResult struct {
Projects []*Project
Total int
}

// Validate checks if the project is valid.
Expand Down
6 changes: 6 additions & 0 deletions pkg/domain/entity/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ type ResourceFilter struct {
ResourceType string
KusionResourceID string
Status string
Pagination *Pagination
}

type ResourceListResult struct {
Resources []*Resource
Total int
}

// Validate checks if the resource is valid.
Expand Down
6 changes: 6 additions & 0 deletions pkg/domain/entity/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ type Source struct {

type SourceFilter struct {
SourceName string
Pagination *Pagination
}

type SourceListResult struct {
Sources []*Source
Total int
}

// Validate checks if the source is valid.
Expand Down
12 changes: 9 additions & 3 deletions pkg/domain/entity/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,15 @@ type Stack struct {
}

type StackFilter struct {
OrgID uint
ProjectID uint
Path string
OrgID uint
ProjectID uint
Path string
Pagination *Pagination
}

type StackListResult struct {
Stacks []*Stack
Total int
}

// Validate checks if the stack is valid.
Expand Down
10 changes: 8 additions & 2 deletions pkg/domain/entity/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,14 @@ func (s *SecretStore) ConvertToKusionSecretStore() (*v1.SecretStore, error) {
}

type WorkspaceFilter struct {
BackendID uint
Name string
BackendID uint
Name string
Pagination *Pagination
}

type WorkspaceListResult struct {
Workspaces []*Workspace
Total int
}

// Validate checks if the workspace is valid.
Expand Down
16 changes: 8 additions & 8 deletions pkg/domain/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type OrganizationRepository interface {
// GetByName retrieves a organization by its name.
GetByName(ctx context.Context, name string) (*entity.Organization, error)
// List retrieves all existing organizations.
List(ctx context.Context) ([]*entity.Organization, error)
List(ctx context.Context, filter *entity.OrganizationFilter) (*entity.OrganizationListResult, error)
}

// ProjectRepository is an interface that defines the repository operations
Expand All @@ -37,7 +37,7 @@ type ProjectRepository interface {
// GetByName retrieves a project by its name.
GetByName(ctx context.Context, name string) (*entity.Project, error)
// List retrieves all existing projects.
List(ctx context.Context, filter *entity.ProjectFilter) ([]*entity.Project, error)
List(ctx context.Context, filter *entity.ProjectFilter) (*entity.ProjectListResult, error)
}

// StackRepository is an interface that defines the repository operations
Expand All @@ -52,7 +52,7 @@ type StackRepository interface {
// Get retrieves a stack by its ID.
Get(ctx context.Context, id uint) (*entity.Stack, error)
// List retrieves all existing stacks.
List(ctx context.Context, filter *entity.StackFilter) ([]*entity.Stack, error)
List(ctx context.Context, filter *entity.StackFilter) (*entity.StackListResult, error)
}

// SourceRepository is an interface that defines the repository operations
Expand All @@ -63,7 +63,7 @@ type SourceRepository interface {
// GetByRemote retrieves a source by its remote.
GetByRemote(ctx context.Context, remote string) (*entity.Source, error)
// List retrieves all existing sources.
List(ctx context.Context, filter *entity.SourceFilter) ([]*entity.Source, error)
List(ctx context.Context, filter *entity.SourceFilter) (*entity.SourceListResult, error)
// Create creates a new source.
Create(ctx context.Context, source *entity.Source) error
// Delete deletes a stack by its ID.
Expand All @@ -86,7 +86,7 @@ type WorkspaceRepository interface {
// GetByName retrieves a workspace by its name.
GetByName(ctx context.Context, name string) (*entity.Workspace, error)
// List retrieves all existing workspace.
List(ctx context.Context, filter *entity.WorkspaceFilter) ([]*entity.Workspace, error)
List(ctx context.Context, filter *entity.WorkspaceFilter) (*entity.WorkspaceListResult, error)
}

// BackendRepository is an interface that defines the repository operations
Expand All @@ -101,7 +101,7 @@ type BackendRepository interface {
// Get retrieves a backend by its ID.
Get(ctx context.Context, id uint) (*entity.Backend, error)
// List retrieves all existing backend.
List(ctx context.Context) ([]*entity.Backend, error)
List(ctx context.Context, filter *entity.BackendFilter) (*entity.BackendListResult, error)
}

// ResourceRepository is an interface that defines the repository operations
Expand All @@ -120,7 +120,7 @@ type ResourceRepository interface {
// GetByKusionResourceURN retrieves a resource by its Kusion resource URN.
GetByKusionResourceURN(ctx context.Context, urn string) (*entity.Resource, error)
// List retrieves all existing resource.
List(ctx context.Context, filter *entity.ResourceFilter) ([]*entity.Resource, error)
List(ctx context.Context, filter *entity.ResourceFilter) (*entity.ResourceListResult, error)
}

// ModuleRepository is an interface that defines the repository operations
Expand All @@ -135,7 +135,7 @@ type ModuleRepository interface {
// Get retrieves a module by its name.
Get(ctx context.Context, name string) (*entity.Module, error)
// List retrives all the existing modules.
List(ctx context.Context, filter *entity.ModuleFilter) ([]*entity.Module, error)
List(ctx context.Context, filter *entity.ModuleFilter) (*entity.ModuleListResult, error)
}

// RunRepository is an interface that defines the repository operations
Expand Down
10 changes: 10 additions & 0 deletions pkg/domain/response/backend.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package response

import "kusionstack.io/kusion/pkg/domain/entity"

type PaginatedBackendResponse struct {
Backends []*entity.Backend `json:"backends"`
Total int `json:"total"`
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
}
11 changes: 11 additions & 0 deletions pkg/domain/response/module.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package response

import "kusionstack.io/kusion/pkg/domain/entity"

type PaginatedModuleResponse struct {
Modules []*entity.Module `json:"modules"`
ModulesWithVersion []*entity.ModuleWithVersion `json:"modulesWithVersion"`
Total int `json:"total"`
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
}
10 changes: 10 additions & 0 deletions pkg/domain/response/organization.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package response

import "kusionstack.io/kusion/pkg/domain/entity"

type PaginatedOrganizationResponse struct {
Organizations []*entity.Organization `json:"organizations"`
Total int `json:"total"`
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
}
10 changes: 10 additions & 0 deletions pkg/domain/response/project.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package response

import "kusionstack.io/kusion/pkg/domain/entity"

type PaginatedProjectResponse struct {
Projects []*entity.Project `json:"projects"`
Total int `json:"total"`
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
}
10 changes: 10 additions & 0 deletions pkg/domain/response/source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package response

import "kusionstack.io/kusion/pkg/domain/entity"

type PaginatedSourceResponse struct {
Sources []*entity.Source `json:"sources"`
Total int `json:"total"`
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
}
10 changes: 10 additions & 0 deletions pkg/domain/response/stack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package response

import "kusionstack.io/kusion/pkg/domain/entity"

type PaginatedStackResponse struct {
Stacks []*entity.Stack `json:"stacks"`
Total int `json:"total"`
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
}
10 changes: 10 additions & 0 deletions pkg/domain/response/workspace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package response

import "kusionstack.io/kusion/pkg/domain/entity"

type PaginatedWorkspaceResponse struct {
Workspaces []*entity.Workspace `json:"workspaces"`
Total int `json:"total"`
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
}
17 changes: 14 additions & 3 deletions pkg/infra/persistence/backend.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//nolint:dupl
package persistence

import (
Expand Down Expand Up @@ -95,10 +96,17 @@ func (r *backendRepository) Get(ctx context.Context, id uint) (*entity.Backend,
}

// List retrieves all backends.
func (r *backendRepository) List(ctx context.Context) ([]*entity.Backend, error) {
func (r *backendRepository) List(ctx context.Context, filter *entity.BackendFilter) (*entity.BackendListResult, error) {
var dataModel []BackendModel
backendEntityList := make([]*entity.Backend, 0)
result := r.db.WithContext(ctx).Find(&dataModel)

// Get total rows.
var totalRows int64
r.db.WithContext(ctx).Model(dataModel).Count(&totalRows)

// Fetch paginated data with offset and limit.
offset := (filter.Pagination.Page - 1) * filter.Pagination.PageSize
result := r.db.WithContext(ctx).Offset(offset).Limit(filter.Pagination.PageSize).Find(&dataModel)
if result.Error != nil {
return nil, result.Error
}
Expand All @@ -109,5 +117,8 @@ func (r *backendRepository) List(ctx context.Context) ([]*entity.Backend, error)
}
backendEntityList = append(backendEntityList, backendEntity)
}
return backendEntityList, nil
return &entity.BackendListResult{
Backends: backendEntityList,
Total: int(totalRows),
}, nil
}
19 changes: 16 additions & 3 deletions pkg/infra/persistence/backend_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//nolint:dupl
package persistence

import (
Expand All @@ -9,6 +10,7 @@ import (
"gorm.io/gorm"

v1 "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1"
"kusionstack.io/kusion/pkg/domain/constant"
"kusionstack.io/kusion/pkg/domain/entity"
)

Expand Down Expand Up @@ -139,14 +141,25 @@ func TestBackendRepository(t *testing.T) {
expectedIDSecond uint = 2
expectedNameSecond = "mockedBackend2"
)
sqlMock.ExpectQuery("SELECT .* FROM `backend`").

sqlMock.ExpectQuery("SELECT count(.*) FROM `backend`").
WillReturnRows(
sqlmock.NewRows([]string{"count"}).
AddRow(2))

sqlMock.ExpectQuery("SELECT .* FROM `backend` .* IS NULL LIMIT").
WillReturnRows(
sqlmock.NewRows([]string{"id", "name"}).
AddRow(expectedIDFirst, expectedNameFirst).
AddRow(expectedIDSecond, expectedNameSecond))

actual, err := repo.List(context.Background())
actual, err := repo.List(context.Background(), &entity.BackendFilter{
Pagination: &entity.Pagination{
Page: constant.CommonPageDefault,
PageSize: constant.CommonPageSizeDefault,
},
})
require.NoError(t, err)
require.Len(t, actual, 2)
require.Len(t, actual.Backends, 2)
})
}
18 changes: 15 additions & 3 deletions pkg/infra/persistence/module.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//nolint:dupl
package persistence

import (
Expand Down Expand Up @@ -93,11 +94,19 @@ func (r *moduleRepository) Get(ctx context.Context, name string) (*entity.Module
}

// List retrieves all the modules.
func (r *moduleRepository) List(ctx context.Context, filter *entity.ModuleFilter) ([]*entity.Module, error) {
func (r *moduleRepository) List(ctx context.Context, filter *entity.ModuleFilter) (*entity.ModuleListResult, error) {
var dataModel []ModuleModel
moduleEntityList := make([]*entity.Module, 0)
pattern, args := GetModuleQuery(filter)
result := r.db.WithContext(ctx).Where(pattern, args...).Find(&dataModel)
searchResult := r.db.WithContext(ctx).Where(pattern, args...)

// Get total rows
var totalRows int64
searchResult.Model(dataModel).Count(&totalRows)

// Fetch paginated data from searchResult with offset and limit
offset := (filter.Pagination.Page - 1) * filter.Pagination.PageSize
result := searchResult.Offset(offset).Limit(filter.Pagination.PageSize).Find(&dataModel)
if result.Error != nil {
return nil, result.Error
}
Expand All @@ -110,5 +119,8 @@ func (r *moduleRepository) List(ctx context.Context, filter *entity.ModuleFilter
moduleEntityList = append(moduleEntityList, moduleEntity)
}

return moduleEntityList, nil
return &entity.ModuleListResult{
Modules: moduleEntityList,
Total: int(totalRows),
}, nil
}
Loading
Loading