Always return results in time desc order from PostStore

This commit is contained in:
Brian Picciano 2022-05-20 17:31:44 -06:00
parent 99f8c1188c
commit 47d4787907
5 changed files with 19 additions and 76 deletions

View File

@ -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

View File

@ -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),

View File

@ -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),

View File

@ -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,18 +184,16 @@ 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
FROM posts p FROM posts p
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)

View File

@ -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"}