M api/graph/model/cursor.go => api/graph/model/cursor.go +3 -8
@@ 12,7 12,6 @@ import (
type Cursor struct {
Count int `json:"count"`
Next string `json:"next"`
- OrderBy string `json:"order_by"`
Search string `json:"search"`
}
@@ 53,18 52,14 @@ func derefOrInt(i *int, d int) int {
func NewCursor(filter *Filter) *Cursor {
if filter != nil {
return &Cursor{
- Next: "",
-
- Count: derefOrInt(filter.Count, 25),
- // TODO:
- OrderBy: "",
- Search: "",
+ Next: "",
+ Count: derefOrInt(filter.Count, 25),
+ Search: "", // TODO
}
}
return &Cursor{
Count: 25,
Next: "",
- OrderBy: "",
Search: "",
}
}
M api/graph/model/repository.go => api/graph/model/repository.go +43 -10
@@ 2,6 2,7 @@ package model
import (
"context"
+ "database/sql"
"time"
"strconv"
@@ 64,7 65,8 @@ func (r *Repository) Select(ctx context.Context) []string {
"upstreamUrl": "upstream_uri",
}),
database.WithAlias(r.alias, "path"),
- database.WithAlias(r.alias, "owner_id"))
+ database.WithAlias(r.alias, "owner_id"),
+ database.WithAlias(r.alias, "updated"))
}
func (r *Repository) As(alias string) *Repository {
@@ 82,20 84,51 @@ func (r *Repository) Fields(ctx context.Context) []interface{} {
"visibility": &r.Visibility,
"upstream_url": &r.UpstreamURL,
})
- return append(fields, &r.Path, &r.OwnerID)
+ return append(fields, &r.Path, &r.OwnerID, &r.Updated)
}
-func (r *Repository) ApplyCursor(q sq.SelectBuilder, c *Cursor) sq.SelectBuilder {
- if c.Next != "" {
- id, _ := strconv.Atoi(c.Next)
- q = q.Where(r.alias + `.id <= ?`, id)
+func (r *Repository) QueryWithCursor(ctx context.Context,
+ db *sql.DB, q sq.SelectBuilder, cur *Cursor) ([]*Repository, *Cursor) {
+ var (
+ err error
+ rows *sql.Rows
+ )
+
+ if cur.Next != "" {
+ ts, _ := strconv.ParseInt(cur.Next, 10, 64)
+ updated := time.Unix(ts, 0)
+ q = q.Where(database.WithAlias(r.alias, "updated") + "<= ?", updated)
+ }
+ q = q.
+ OrderBy(database.WithAlias(r.alias, "updated") + " DESC").
+ Limit(uint64(cur.Count + 1))
+
+ if rows, err = q.RunWith(db).QueryContext(ctx); err != nil {
+ panic(err)
}
- if c.OrderBy != "" {
- q = q.OrderBy(c.OrderBy)
+ defer rows.Close()
+
+ var repos []*Repository
+ for rows.Next() {
+ var repo Repository
+ if err := rows.Scan(repo.Fields(ctx)...); err != nil {
+ panic(err)
+ }
+ repos = append(repos, &repo)
+ }
+
+ if len(repos) > cur.Count {
+ cur = &Cursor{
+ Count: cur.Count,
+ Next: strconv.FormatInt(repos[len(repos)-1].Updated.Unix(), 10),
+ Search: cur.Search,
+ }
+ repos = repos[:cur.Count]
} else {
- q = q.OrderBy(r.alias + `.id DESC`)
+ cur = nil
}
- return q.Limit(uint64(c.Count + 1))
+
+ return repos, cur
}
func (r *Repository) DefaultSearch(query sq.SelectBuilder,
M api/graph/schema.resolvers.go => api/graph/schema.resolvers.go +2 -66
@@ 5,10 5,8 @@ package graph
import (
"context"
- "database/sql"
"fmt"
"sort"
- "strconv"
"strings"
"git.sr.ht/~sircmpwn/git.sr.ht/api/auth"
@@ 76,11 74,6 @@ func (r *queryResolver) User(ctx context.Context, username string) (*model.User,
}
func (r *queryResolver) Repositories(ctx context.Context, cursor *model.Cursor, filter *model.Filter) (*model.RepositoryCursor, error) {
- var (
- err error
- rows *sql.Rows
- )
-
if cursor == nil {
cursor = model.NewCursor(filter)
}
@@ 90,34 83,8 @@ func (r *queryResolver) Repositories(ctx context.Context, cursor *model.Cursor,
Select(ctx, repo).
From(`repository repo`).
Where(`repo.owner_id = ?`, auth.ForContext(ctx).ID)
- query = repo.ApplyCursor(query, cursor)
-
- if rows, err = query.RunWith(r.DB).QueryContext(ctx); err != nil {
- panic(err)
- }
- defer rows.Close()
-
- var repos []*model.Repository
- for rows.Next() {
- var repo model.Repository
- if err := rows.Scan(repo.Fields(ctx)...); err != nil {
- panic(err)
- }
- repos = append(repos, &repo)
- }
-
- if len(repos) > cursor.Count {
- cursor = &model.Cursor{
- Count: cursor.Count,
- Next: strconv.Itoa(repos[len(repos)-1].ID),
- OrderBy: `id DESC`,
- Search: "",
- }
- repos = repos[:cursor.Count]
- } else {
- cursor = nil
- }
+ repos, cursor := repo.QueryWithCursor(ctx, r.DB, query, cursor)
return &model.RepositoryCursor{repos, cursor}, nil
}
@@ 173,11 140,6 @@ func (r *treeResolver) Entries(ctx context.Context, obj *model.Tree, cursor *mod
}
func (r *userResolver) Repositories(ctx context.Context, obj *model.User, cursor *model.Cursor, filter *model.Filter) (*model.RepositoryCursor, error) {
- var (
- err error
- rows *sql.Rows
- )
-
if cursor == nil {
cursor = model.NewCursor(filter)
}
@@ 187,34 149,8 @@ func (r *userResolver) Repositories(ctx context.Context, obj *model.User, cursor
Select(ctx, repo).
From(`repository repo`).
Where(`repo.owner_id = ?`, obj.ID)
- query = repo.ApplyCursor(query, cursor)
-
- if rows, err = query.RunWith(r.DB).QueryContext(ctx); err != nil {
- panic(err)
- }
- defer rows.Close()
-
- var repos []*model.Repository
- for rows.Next() {
- var repo model.Repository
- if err := rows.Scan(repo.Fields(ctx)...); err != nil {
- panic(err)
- }
- repos = append(repos, &repo)
- }
-
- if len(repos) > cursor.Count {
- cursor = &model.Cursor{
- Count: cursor.Count,
- Next: strconv.Itoa(repos[len(repos)-1].ID),
- OrderBy: `id DESC`,
- Search: "",
- }
- repos = repos[:cursor.Count]
- } else {
- cursor = nil
- }
+ repos, cursor := repo.QueryWithCursor(ctx, r.DB, query, cursor)
return &model.RepositoryCursor{repos, cursor}, nil
}