Always return results in time desc order from PostStore
This commit is contained in:
parent
99f8c1188c
commit
47d4787907
@ -26,7 +26,7 @@ func (a *api) renderFeedHandler() http.Handler {
|
|||||||
Author: author,
|
Author: author,
|
||||||
}
|
}
|
||||||
|
|
||||||
recentPosts, _, err := a.params.PostStore.WithOrderDesc().Get(0, 20)
|
recentPosts, _, err := a.params.PostStore.Get(0, 20)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
apiutil.InternalServerError(rw, r, fmt.Errorf("fetching recent posts: %w", err))
|
apiutil.InternalServerError(rw, r, fmt.Errorf("fetching recent posts: %w", err))
|
||||||
return
|
return
|
||||||
|
@ -30,7 +30,7 @@ func (a *api) renderIndexHandler() http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
posts, hasMore, err := a.params.PostStore.WithOrderDesc().Get(page, pageCount)
|
posts, hasMore, err := a.params.PostStore.Get(page, pageCount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
apiutil.InternalServerError(
|
apiutil.InternalServerError(
|
||||||
rw, r, fmt.Errorf("fetching page %d of posts: %w", page, err),
|
rw, r, fmt.Errorf("fetching page %d of posts: %w", page, err),
|
||||||
|
@ -69,11 +69,11 @@ func (a *api) postToPostTplPayload(storedPost post.StoredPost) (postTplPayload,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !foundThis {
|
if !foundThis {
|
||||||
tplPayload.SeriesPrevious = &seriesPost
|
tplPayload.SeriesNext = &seriesPost
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
tplPayload.SeriesNext = &seriesPost
|
tplPayload.SeriesPrevious = &seriesPost
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,7 +138,7 @@ func (a *api) renderPostsIndexHandler() http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
posts, hasMore, err := a.params.PostStore.WithOrderDesc().Get(page, pageCount)
|
posts, hasMore, err := a.params.PostStore.Get(page, pageCount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
apiutil.InternalServerError(
|
apiutil.InternalServerError(
|
||||||
rw, r, fmt.Errorf("fetching page %d of posts: %w", page, err),
|
rw, r, fmt.Errorf("fetching page %d of posts: %w", page, err),
|
||||||
|
@ -61,40 +61,28 @@ type Store interface {
|
|||||||
GetByID(id string) (StoredPost, error)
|
GetByID(id string) (StoredPost, error)
|
||||||
|
|
||||||
// GetBySeries returns all StoredPosts with the given series, sorted time
|
// GetBySeries returns all StoredPosts with the given series, sorted time
|
||||||
// ascending, or empty slice.
|
// descending, or empty slice.
|
||||||
GetBySeries(series string) ([]StoredPost, error)
|
GetBySeries(series string) ([]StoredPost, error)
|
||||||
|
|
||||||
// GetByTag returns all StoredPosts with the given tag, sorted time
|
// GetByTag returns all StoredPosts with the given tag, sorted time
|
||||||
// ascending, or empty slice.
|
// descending, or empty slice.
|
||||||
GetByTag(tag string) ([]StoredPost, error)
|
GetByTag(tag string) ([]StoredPost, error)
|
||||||
|
|
||||||
// WithOrderDesc will return a Store whose Get operations return Posts in
|
|
||||||
// time descending order, rather than ascending.
|
|
||||||
WithOrderDesc() Store
|
|
||||||
|
|
||||||
// Delete will delete the StoredPost with the given ID.
|
// Delete will delete the StoredPost with the given ID.
|
||||||
Delete(id string) error
|
Delete(id string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type store struct {
|
type store struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
order string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStore initializes a new Store using an existing SQLDB.
|
// NewStore initializes a new Store using an existing SQLDB.
|
||||||
func NewStore(db *SQLDB) Store {
|
func NewStore(db *SQLDB) Store {
|
||||||
return &store{
|
return &store{
|
||||||
db: db.db,
|
db: db.db,
|
||||||
order: "ASC",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *store) WithOrderDesc() Store {
|
|
||||||
s2 := *s
|
|
||||||
s2.order = "DESC"
|
|
||||||
return &s2
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the callback returns an error then the transaction is aborted.
|
// if the callback returns an error then the transaction is aborted.
|
||||||
func (s *store) withTx(cb func(*sql.Tx) error) error {
|
func (s *store) withTx(cb func(*sql.Tx) error) error {
|
||||||
|
|
||||||
@ -196,8 +184,8 @@ func (s *store) get(
|
|||||||
[]StoredPost, error,
|
[]StoredPost, error,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
query := fmt.Sprintf(
|
query := `
|
||||||
`SELECT
|
SELECT
|
||||||
p.id, p.title, p.description, p.series, GROUP_CONCAT(pt.tag),
|
p.id, p.title, p.description, p.series, GROUP_CONCAT(pt.tag),
|
||||||
p.published_at, p.last_updated_at,
|
p.published_at, p.last_updated_at,
|
||||||
p.body
|
p.body
|
||||||
@ -205,9 +193,7 @@ func (s *store) get(
|
|||||||
LEFT JOIN post_tags pt ON (p.id = pt.post_id)
|
LEFT JOIN post_tags pt ON (p.id = pt.post_id)
|
||||||
` + where + `
|
` + where + `
|
||||||
GROUP BY (p.id)
|
GROUP BY (p.id)
|
||||||
ORDER BY p.published_at %s, p.title %s`,
|
ORDER BY p.published_at DESC, p.title DESC`
|
||||||
s.order, s.order,
|
|
||||||
)
|
|
||||||
|
|
||||||
if limit > 0 {
|
if limit > 0 {
|
||||||
query += fmt.Sprintf(" LIMIT %d", limit)
|
query += fmt.Sprintf(" LIMIT %d", limit)
|
||||||
|
@ -152,49 +152,6 @@ func TestStore(t *testing.T) {
|
|||||||
|
|
||||||
now := h.clock.Now().UTC()
|
now := h.clock.Now().UTC()
|
||||||
|
|
||||||
posts := []StoredPost{
|
|
||||||
h.testStoredPost(0),
|
|
||||||
h.testStoredPost(1),
|
|
||||||
h.testStoredPost(2),
|
|
||||||
h.testStoredPost(3),
|
|
||||||
}
|
|
||||||
|
|
||||||
posts[1].Tags = []string{"1", "2"}
|
|
||||||
|
|
||||||
for _, post := range posts {
|
|
||||||
assert.NoError(t, h.store.Set(post.Post, now))
|
|
||||||
}
|
|
||||||
|
|
||||||
gotPosts, hasMore, err := h.store.Get(0, 2)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.True(t, hasMore)
|
|
||||||
assertPostsEqual(t, posts[:2], gotPosts)
|
|
||||||
|
|
||||||
gotPosts, hasMore, err = h.store.Get(1, 2)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.False(t, hasMore)
|
|
||||||
assertPostsEqual(t, posts[2:4], gotPosts)
|
|
||||||
|
|
||||||
posts = append(posts, h.testStoredPost(4))
|
|
||||||
assert.NoError(t, h.store.Set(posts[4].Post, now))
|
|
||||||
|
|
||||||
gotPosts, hasMore, err = h.store.Get(1, 2)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.True(t, hasMore)
|
|
||||||
assertPostsEqual(t, posts[2:4], gotPosts)
|
|
||||||
|
|
||||||
gotPosts, hasMore, err = h.store.Get(2, 2)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.False(t, hasMore)
|
|
||||||
assertPostsEqual(t, posts[4:], gotPosts)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("get_desc", func(t *testing.T) {
|
|
||||||
h := newStoreTestHarness(t)
|
|
||||||
h.store = h.store.WithOrderDesc()
|
|
||||||
|
|
||||||
now := h.clock.Now().UTC()
|
|
||||||
|
|
||||||
posts := []StoredPost{
|
posts := []StoredPost{
|
||||||
h.testStoredPost(3),
|
h.testStoredPost(3),
|
||||||
h.testStoredPost(2),
|
h.testStoredPost(2),
|
||||||
@ -236,10 +193,10 @@ func TestStore(t *testing.T) {
|
|||||||
now := h.clock.Now().UTC()
|
now := h.clock.Now().UTC()
|
||||||
|
|
||||||
posts := []StoredPost{
|
posts := []StoredPost{
|
||||||
h.testStoredPost(0),
|
|
||||||
h.testStoredPost(1),
|
|
||||||
h.testStoredPost(2),
|
|
||||||
h.testStoredPost(3),
|
h.testStoredPost(3),
|
||||||
|
h.testStoredPost(2),
|
||||||
|
h.testStoredPost(1),
|
||||||
|
h.testStoredPost(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
posts[0].Series = "foo"
|
posts[0].Series = "foo"
|
||||||
@ -270,10 +227,10 @@ func TestStore(t *testing.T) {
|
|||||||
now := h.clock.Now().UTC()
|
now := h.clock.Now().UTC()
|
||||||
|
|
||||||
posts := []StoredPost{
|
posts := []StoredPost{
|
||||||
h.testStoredPost(0),
|
|
||||||
h.testStoredPost(1),
|
|
||||||
h.testStoredPost(2),
|
|
||||||
h.testStoredPost(3),
|
h.testStoredPost(3),
|
||||||
|
h.testStoredPost(2),
|
||||||
|
h.testStoredPost(1),
|
||||||
|
h.testStoredPost(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
posts[0].Tags = []string{"foo"}
|
posts[0].Tags = []string{"foo"}
|
||||||
|
Loading…
Reference in New Issue
Block a user