Skip to content

Commit

Permalink
update link index to also have pagination controls
Browse files Browse the repository at this point in the history
  • Loading branch information
Southclaws committed Dec 26, 2023
1 parent c9704e9 commit 19f2f9a
Show file tree
Hide file tree
Showing 25 changed files with 422 additions and 262 deletions.
50 changes: 31 additions & 19 deletions api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1777,11 +1777,7 @@ components:
description: Link list.
content:
application/json:
schema:
type: object
required: [links]
properties:
links: { $ref: "#/components/schemas/LinkList" }
schema: { $ref: "#/components/schemas/LinkListResult" }

LinkGetOK:
description: Link data.
Expand Down Expand Up @@ -1950,6 +1946,22 @@ components:
additionalProperties: true
x-go-type: any

PaginatedResult:
description: To be composed with paginated resource responses.
type: object
required: [page_size, results, total_pages, current_page]
properties:
page_size:
type: integer
results:
type: integer
total_pages:
type: integer
current_page:
type: integer
next_page:
type: integer

URL:
description: A web address
type: string
Expand Down Expand Up @@ -2481,20 +2493,12 @@ components:
$ref: "#/components/schemas/TagList"

PublicProfileListResult:
type: object
required: [page_size, results, total_pages, current_page, profiles]
properties:
page_size:
type: integer
results:
type: integer
total_pages:
type: integer
current_page:
type: integer
next_page:
type: integer
profiles: { $ref: "#/components/schemas/PublicProfileList" }
allOf:
- { $ref: "#/components/schemas/PaginatedResult" }
- type: object
required: [profiles]
properties:
profiles: { $ref: "#/components/schemas/PublicProfileList" }

PublicProfileList:
type: array
Expand Down Expand Up @@ -3182,6 +3186,14 @@ components:
type: array
items: { $ref: "#/components/schemas/Link" }

LinkListResult:
allOf:
- { $ref: "#/components/schemas/PaginatedResult" }
- type: object
required: [links]
properties:
links: { $ref: "#/components/schemas/LinkList" }

LinkInitialProps:
type: object
required: [url]
Expand Down
31 changes: 27 additions & 4 deletions app/resources/link/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package link
import (
"context"
"fmt"
"math"
"net/url"
"strings"

"github.com/Southclaws/fault"
"github.com/Southclaws/fault/fctx"
"github.com/Southclaws/opt"
"github.com/gosimple/slug"

"github.com/Southclaws/storyden/internal/ent"
Expand Down Expand Up @@ -43,7 +45,7 @@ func (d *database) Store(ctx context.Context, address, title, description string
fn(mutate)
}

create.OnConflictColumns("url").UpdateNewValues()
create.OnConflictColumns("url", "slug").UpdateNewValues()

r, err := create.Save(ctx)
if err != nil {
Expand All @@ -63,8 +65,16 @@ func (d *database) Store(ctx context.Context, address, title, description string
return link, nil
}

func (d *database) Search(ctx context.Context, filters ...Filter) ([]*Link, error) {
query := d.db.Link.Query()
func (d *database) Search(ctx context.Context, page int, size int, filters ...Filter) (*Result, error) {
total, err := d.db.Link.Query().Count(ctx)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

query := d.db.Link.Query().
Limit(size + 1).
Offset(page * size).
Order(ent.Desc(link.FieldCreatedAt))

for _, fn := range filters {
fn(query)
Expand All @@ -77,9 +87,22 @@ func (d *database) Search(ctx context.Context, filters ...Filter) ([]*Link, erro
return nil, fault.Wrap(err, fctx.With(ctx))
}

nextPage := opt.NewSafe(page+1, len(r) >= size)

if len(r) > 1 {
r = r[:len(r)-1]
}

links := MapA(r)

return links, nil
return &Result{
PageSize: size,
Results: len(links),
TotalPages: int(math.Ceil(float64(total) / float64(size))),
CurrentPage: page,
NextPage: nextPage,
Links: links,
}, nil
}

func getLinkAttrs(u url.URL) (string, string) {
Expand Down
17 changes: 10 additions & 7 deletions app/resources/link/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,22 @@ type Link struct {
Assets []*asset.Asset
}

type Result struct {
PageSize int
Results int
TotalPages int
CurrentPage int
NextPage opt.Optional[int]
Links []*Link
}

func (l *Link) AssetIDs() []asset.AssetID {
return dt.Map(l.Assets, func(a *asset.Asset) asset.AssetID { return a.ID })
}

type Repository interface {
Store(ctx context.Context, url, title, description string, opts ...Option) (*Link, error)
Search(ctx context.Context, filters ...Filter) ([]*Link, error)
Search(ctx context.Context, page int, size int, filters ...Filter) (*Result, error)
}

type (
Expand Down Expand Up @@ -69,12 +78,6 @@ func WithURL(s string) Filter {
}
}

func WithPage(page, size int) Filter {
return func(lq *ent.LinkQuery) {
lq.Limit(size).Offset(page * size)
}
}

func WithKeyword(s string) Filter {
return func(lq *ent.LinkQuery) {
lq.Where(link.Or(
Expand Down
2 changes: 1 addition & 1 deletion app/resources/profile_search/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (d *database) Search(ctx context.Context, page int, size int, filters ...Fi
q := d.db.Account.Query().
Limit(size + 1).
Offset(page * size).
Order(ent.Asc(account.FieldCreatedAt))
Order(ent.Desc(account.FieldCreatedAt))

for _, fn := range filters {
fn(q)
Expand Down
6 changes: 3 additions & 3 deletions app/services/hydrator/fetcher/fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ func (s *service) Fetch(ctx context.Context, url string) (*link.Link, error) {
return nil, fault.Wrap(errEmptyLink, fctx.With(ctx), ftag.With(ftag.InvalidArgument))
}

r, err := s.lr.Search(ctx, link.WithURL(url))
r, err := s.lr.Search(ctx, 0, 1, link.WithURL(url))
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}
if len(r) > 0 {
if len(r.Links) > 0 {
// revalidate stale data asynchronously
go s.scrapeAndStore(ctx, url)
return r[0], nil
return r.Links[0], nil
}

return s.scrapeAndStore(ctx, url)
Expand Down
37 changes: 24 additions & 13 deletions app/transports/openapi/bindings/links.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/Southclaws/dt"
"github.com/Southclaws/fault"
"github.com/Southclaws/fault/fctx"
"github.com/Southclaws/fault/ftag"
"github.com/Southclaws/opt"

"github.com/Southclaws/storyden/app/resources/link"
"github.com/Southclaws/storyden/app/resources/link_graph"
Expand Down Expand Up @@ -47,31 +47,42 @@ func (i *Links) LinkCreate(ctx context.Context, request openapi.LinkCreateReques
}

func (i *Links) LinkList(ctx context.Context, request openapi.LinkListRequestObject) (openapi.LinkListResponseObject, error) {
pageSize := 50

page := opt.NewPtrMap(request.Params.Page, func(s string) int {
v, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return 0
}

return max(1, int(v))

Check failure on line 58 in app/transports/openapi/bindings/links.go

View workflow job for this annotation

GitHub Actions / backend-test

undefined: max
}).Or(1)

opts := []link.Filter{}

if v := request.Params.Q; v != nil {
opts = append(opts, link.WithKeyword(*v))
}

if v := request.Params.Page; v != nil {
pageNumber, err := strconv.ParseInt(*v, 10, 32)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx), ftag.With(ftag.InvalidArgument))
}
// API is 1-indexed, internally it's 0-indexed.
page = max(0, page-1)

Check failure on line 68 in app/transports/openapi/bindings/links.go

View workflow job for this annotation

GitHub Actions / backend-test

undefined: max

opts = append(opts, link.WithPage(int(pageNumber-1), 50))
} else {
opts = append(opts, link.WithPage(0, 50))
}

links, err := i.lr.Search(ctx, opts...)
result, err := i.lr.Search(ctx, page, pageSize, opts...)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

// API is 1-indexed, internally it's 0-indexed.
page = result.CurrentPage + 1

return openapi.LinkList200JSONResponse{
LinkListOKJSONResponse: openapi.LinkListOKJSONResponse{
Links: dt.Map(links, serialiseLink),
PageSize: pageSize,
Results: result.Results,
TotalPages: result.TotalPages,
CurrentPage: page,
NextPage: result.NextPage.Ptr(),
Links: dt.Map(result.Links, serialiseLink),
},
}, nil
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ require (
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect
github.com/a8m/enter v0.0.0-20230407172335-1834787a98fe // indirect
github.com/andybalholm/brotli v1.0.6 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
Expand Down
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ github.com/Southclaws/fault v0.7.0 h1:qT0aOp+bUpvxm8fveBIJRcU/QfrBCmR6kMaAHyAknS
github.com/Southclaws/fault v0.7.0/go.mod h1:VUVkAWutC59SL16s6FTqf3I6I2z77RmnaW5XRz4bLOE=
github.com/Southclaws/opt v0.6.0 h1:DnsHXMfeW8vV1y2oa26bpx1dn76PERw4QNw25b6U498=
github.com/Southclaws/opt v0.6.0/go.mod h1:zGjXSHmM4ScFX3TLkCr8TdVvd4KAcZq0mwWtzqoqwwQ=
github.com/a8m/enter v0.0.0-20230407172335-1834787a98fe h1:Wx1QNWtwtyIOMCJ+zQ6NkweM+TB+DbNcoz56HibaBtI=
github.com/a8m/enter v0.0.0-20230407172335-1834787a98fe/go.mod h1:oIhrOH1HOtDThKUKzKLbeF979y2PjDTiLPSTe4kmTDE=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
Expand Down Expand Up @@ -378,6 +380,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI=
github.com/mattn/go-sqlite3 v1.14.18/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
Expand Down Expand Up @@ -417,6 +421,8 @@ github.com/oapi-codegen/runtime v1.1.0 h1:rJpoNUawn5XTvekgfkvSZr0RqEnoYpFkyvrzfW
github.com/oapi-codegen/runtime v1.1.0/go.mod h1:BeSfBkWWWnAnGdyS+S/GnlbmHKzf8/hwkvelJZDeKA8=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
Expand Down Expand Up @@ -466,7 +472,11 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down Expand Up @@ -704,6 +714,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
5 changes: 5 additions & 0 deletions internal/ent/migrate/schema.go

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

1 change: 1 addition & 0 deletions internal/ent/schema/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func (Link) Fields() []ent.Field {
func (Link) Indexes() []ent.Index {
return []ent.Index{
index.Fields("url"),
index.Fields("slug"),
}
}

Expand Down
Loading

2 comments on commit 19f2f9a

@vercel
Copy link

@vercel vercel bot commented on 19f2f9a Dec 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 19f2f9a Dec 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.