feat: enhanced paging support

This commit is contained in:
Paul Pan 2023-12-23 15:36:42 +08:00
parent 17123e6911
commit b45963f9b5
Signed by: Paul
GPG Key ID: D639BDF5BA578AF4
7 changed files with 32 additions and 19 deletions

View File

@ -14,7 +14,7 @@ type queryRequest struct {
Limit int `form:"limit" json:"limit" binding:"required"` Limit int `form:"limit" json:"limit" binding:"required"`
} }
type queryResponse struct { type submissionWithScore struct {
Submission model.Submission `json:"submission"` Submission model.Submission `json:"submission"`
Point int32 `json:"point"` Point int32 `json:"point"`
} }
@ -29,7 +29,8 @@ type queryResponse struct {
// @Param uid formData uint false "user id" // @Param uid formData uint false "user id"
// @Param offset formData int false "start position" // @Param offset formData int false "start position"
// @Param limit formData int true "limit number of records" // @Param limit formData int true "limit number of records"
// @Response 200 {object} e.Response[[]queryResponse] "queryResponse" // @Response 200 {object} e.Response[e.WithCount[submissionWithScore]] "status"
// @Security Authentication
// @Router /v1/status/query [post] // @Router /v1/status/query [post]
func (h *handler) Query(c *gin.Context) { func (h *handler) Query(c *gin.Context) {
claim, exist := c.Get("claim") claim, exist := c.Get("claim")
@ -55,10 +56,14 @@ func (h *handler) Query(c *gin.Context) {
role := claim.(*model.Claim).Role role := claim.(*model.Claim).Role
var response []*queryResponse var response []*queryResponse
var count int64
submissions, status := h.submissionService.Query(req.Pid, req.Uid, req.Offset, req.Limit, &count)
var response []*submissionWithScore
for _, submission := range submissions { for _, submission := range submissions {
cur, _ := h.statusService.Query(submission.ID, false) cur, _ := h.statusService.Query(submission.ID, false)
point := utils.If(cur == nil, -1, cur.Point) point := utils.If(cur == nil, -1, cur.Point)
resp := &queryResponse{ resp := &submissionWithScore{
Submission: *submission, Submission: *submission,
Point: point, Point: point,
} }
@ -71,5 +76,5 @@ func (h *handler) Query(c *gin.Context) {
response = append(response, resp) response = append(response, resp)
} }
e.Pong(c, status, response) e.Pong(c, status, e.WithCount[*submissionWithScore]{Count: count, Data: response})
} }

View File

@ -21,7 +21,7 @@ type queryByVersionRequest struct {
// @Param pvid formData uint true "problem version" // @Param pvid formData uint true "problem version"
// @Param offset formData int false "start position" // @Param offset formData int false "start position"
// @Param limit formData int true "max number of results" // @Param limit formData int true "max number of results"
// @Response 200 {object} e.Response[[]model.Status] "submission status array" // @Response 200 {object} e.Response[e.WithCount[model.Status]] "submission status array"
// @Security Authentication // @Security Authentication
// @Router /v1/status/query/version [post] // @Router /v1/status/query/version [post]
func (h *handler) QueryByProblemVersion(c *gin.Context) { func (h *handler) QueryByProblemVersion(c *gin.Context) {
@ -44,6 +44,7 @@ func (h *handler) QueryByProblemVersion(c *gin.Context) {
return return
} }
submitStatus, status := h.statusService.QueryByVersion(req.ProblemVersionID, req.Offset, req.Limit) var count int64
e.Pong(c, status, submitStatus) submitStatus, status := h.statusService.QueryByVersion(req.ProblemVersionID, req.Offset, req.Limit, &count)
e.Pong(c, status, e.WithCount[*model.Status]{Count: count, Data: submitStatus})
} }

View File

@ -12,6 +12,11 @@ type Response[T any] struct {
Body T `json:"body"` Body T `json:"body"`
} }
type WithCount[T any] struct {
Count int64 `json:"count"`
Data []T `json:"data"`
}
func wrap[T any](status Status, body T) Response[interface{}] { func wrap[T any](status Status, body T) Response[interface{}] {
return Response[interface{}]{ return Response[interface{}]{
Code: int(status), Code: int(status),

View File

@ -36,8 +36,8 @@ func (s *service) Query(sid uint, associations bool) (*model.Status, e.Status) {
return status, e.Success return status, e.Success
} }
func (s *service) QueryByVersion(pvid uint, offset int, limit int) ([]*model.Status, e.Status) { func (s *service) QueryByVersion(pvid uint, offset int, limit int, count *int64) ([]*model.Status, e.Status) {
var statuses []*model.Status var ret []*model.Status
status := &model.Status{ status := &model.Status{
ProblemVersionID: pvid, ProblemVersionID: pvid,
IsEnabled: true, IsEnabled: true,
@ -45,12 +45,13 @@ func (s *service) QueryByVersion(pvid uint, offset int, limit int) ([]*model.Sta
err := s.db.Get().Preload(clause.Associations). err := s.db.Get().Preload(clause.Associations).
Where(status). Where(status).
Limit(limit). Order("created_at DESC").
Offset(offset). Offset(offset).Limit(limit).Find(&ret).
Find(&statuses).Error Offset(-1).Limit(-1).Count(count).
Error
if err != nil { if err != nil {
s.log.Warn("DatabaseError", zap.Error(err), zap.Any("status", status)) s.log.Warn("DatabaseError", zap.Error(err), zap.Any("status", status))
return nil, e.DatabaseError return nil, e.DatabaseError
} }
return statuses, e.Success return ret, e.Success
} }

View File

@ -14,7 +14,7 @@ var _ Service = (*service)(nil)
type Service interface { type Service interface {
Create(data *CreateData) (*model.Status, e.Status) Create(data *CreateData) (*model.Status, e.Status)
Query(sid uint, associations bool) (*model.Status, e.Status) Query(sid uint, associations bool) (*model.Status, e.Status)
QueryByVersion(pvid uint, offset int, limit int) ([]*model.Status, e.Status) QueryByVersion(pvid uint, offset int, limit int, count *int64) ([]*model.Status, e.Status)
HealthCheck() error HealthCheck() error
} }

View File

@ -9,7 +9,7 @@ import (
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
) )
func (s *service) Query(pid uint, uid uint, offset int, limit int) ([]*model.Submission, e.Status) { func (s *service) Query(pid uint, uid uint, offset int, limit int, count *int64) ([]*model.Submission, e.Status) {
submissions := make([]*model.Submission, 0) submissions := make([]*model.Submission, 0)
submission := &model.Submission{ submission := &model.Submission{
@ -19,9 +19,10 @@ func (s *service) Query(pid uint, uid uint, offset int, limit int) ([]*model.Sub
err := s.db.Get().Preload(clause.Associations). err := s.db.Get().Preload(clause.Associations).
Where(submission). Where(submission).
Limit(limit). Order("created_at DESC").
Offset(offset). Offset(offset).Limit(limit).Find(&submissions).
Find(&submissions).Error Offset(-1).Limit(-1).Count(count).
Error
//if errors.Is(err, gorm.ErrRecordNotFound) { //if errors.Is(err, gorm.ErrRecordNotFound) {
// return nil, e.ProblemNotFound // return nil, e.ProblemNotFound

View File

@ -13,7 +13,7 @@ var _ Service = (*service)(nil)
type Service interface { type Service interface {
Create(data *CreateData) (*model.Submission, e.Status) Create(data *CreateData) (*model.Submission, e.Status)
Query(pid uint, uid uint, offset int, limit int) ([]*model.Submission, e.Status) Query(pid uint, uid uint, offset int, limit int, count *int64) ([]*model.Submission, e.Status)
QueryBySid(sid uint, associations bool) (*model.Submission, e.Status) QueryBySid(sid uint, associations bool) (*model.Submission, e.Status)
HealthCheck() error HealthCheck() error