Skip to content

Commit

Permalink
Merge pull request #247 from systemli/Make-Queries-configurable-to-pr…
Browse files Browse the repository at this point in the history
…eload-associations

🗃️ Make Queries configurable to preload associations
  • Loading branch information
0x46616c6b authored Oct 20, 2023
2 parents 4bf7a2e + f15423d commit f712eb8
Show file tree
Hide file tree
Showing 14 changed files with 419 additions and 204 deletions.
52 changes: 26 additions & 26 deletions internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ type handler struct {
// @host localhost:8080
// @BasePath /v1

func API(config config.Config, storage storage.Storage, log *logrus.Logger) *gin.Engine {
func API(config config.Config, store storage.Storage, log *logrus.Logger) *gin.Engine {
handler := handler{
config: config,
storage: storage,
bridges: bridge.RegisterBridges(config, storage),
storage: store,
bridges: bridge.RegisterBridges(config, store),
}

// TOOD: Make this configurable via config file
Expand All @@ -65,11 +65,11 @@ func API(config config.Config, storage storage.Storage, log *logrus.Logger) *gin
r.Use(limits.RequestSizeLimiter(1024 * 1024 * 10))

// the jwt middleware
authMiddleware := auth.AuthMiddleware(storage, config.Secret)
authMiddleware := auth.AuthMiddleware(store, config.Secret)

admin := r.Group("/v1/admin")
{
meMiddleware := me.MeMiddleware(storage)
meMiddleware := me.MeMiddleware(store)
admin.Use(authMiddleware.MiddlewareFunc())
admin.Use(meMiddleware)

Expand All @@ -78,32 +78,32 @@ func API(config config.Config, storage storage.Storage, log *logrus.Logger) *gin
admin.GET("/features", handler.GetFeatures)

admin.GET(`/tickers`, handler.GetTickers)
admin.GET(`/tickers/:tickerID`, ticker.PrefetchTicker(storage), handler.GetTicker)
admin.GET(`/tickers/:tickerID`, ticker.PrefetchTicker(store, storage.WithPreload()), handler.GetTicker)
admin.POST(`/tickers`, user.NeedAdmin(), handler.PostTicker)
admin.PUT(`/tickers/:tickerID`, ticker.PrefetchTicker(storage), handler.PutTicker)
admin.PUT(`/tickers/:tickerID/telegram`, ticker.PrefetchTicker(storage), handler.PutTickerTelegram)
admin.DELETE(`/tickers/:tickerID/telegram`, ticker.PrefetchTicker(storage), handler.DeleteTickerTelegram)
admin.PUT(`/tickers/:tickerID/mastodon`, ticker.PrefetchTicker(storage), handler.PutTickerMastodon)
admin.DELETE(`/tickers/:tickerID/mastodon`, ticker.PrefetchTicker(storage), handler.DeleteTickerMastodon)
admin.DELETE(`/tickers/:tickerID`, user.NeedAdmin(), ticker.PrefetchTicker(storage), handler.DeleteTicker)
admin.PUT(`/tickers/:tickerID/reset`, ticker.PrefetchTicker(storage), ticker.PrefetchTicker(storage), handler.ResetTicker)
admin.GET(`/tickers/:tickerID/users`, ticker.PrefetchTicker(storage), handler.GetTickerUsers)
admin.PUT(`/tickers/:tickerID/users`, user.NeedAdmin(), ticker.PrefetchTicker(storage), handler.PutTickerUsers)
admin.DELETE(`/tickers/:tickerID/users/:userID`, user.NeedAdmin(), ticker.PrefetchTicker(storage), handler.DeleteTickerUser)

admin.GET(`/tickers/:tickerID/messages`, ticker.PrefetchTicker(storage), handler.GetMessages)
admin.GET(`/tickers/:tickerID/messages/:messageID`, ticker.PrefetchTicker(storage), message.PrefetchMessage(storage), handler.GetMessage)
admin.POST(`/tickers/:tickerID/messages`, ticker.PrefetchTicker(storage), handler.PostMessage)
admin.DELETE(`/tickers/:tickerID/messages/:messageID`, ticker.PrefetchTicker(storage), message.PrefetchMessage(storage), handler.DeleteMessage)
admin.PUT(`/tickers/:tickerID`, ticker.PrefetchTicker(store, storage.WithPreload()), handler.PutTicker)
admin.PUT(`/tickers/:tickerID/telegram`, ticker.PrefetchTicker(store, storage.WithPreload()), handler.PutTickerTelegram)
admin.DELETE(`/tickers/:tickerID/telegram`, ticker.PrefetchTicker(store, storage.WithPreload()), handler.DeleteTickerTelegram)
admin.PUT(`/tickers/:tickerID/mastodon`, ticker.PrefetchTicker(store, storage.WithPreload()), handler.PutTickerMastodon)
admin.DELETE(`/tickers/:tickerID/mastodon`, ticker.PrefetchTicker(store, storage.WithPreload()), handler.DeleteTickerMastodon)
admin.DELETE(`/tickers/:tickerID`, user.NeedAdmin(), ticker.PrefetchTicker(store), handler.DeleteTicker)
admin.PUT(`/tickers/:tickerID/reset`, ticker.PrefetchTicker(store, storage.WithPreload()), ticker.PrefetchTicker(store), handler.ResetTicker)
admin.GET(`/tickers/:tickerID/users`, ticker.PrefetchTicker(store), handler.GetTickerUsers)
admin.PUT(`/tickers/:tickerID/users`, user.NeedAdmin(), ticker.PrefetchTicker(store), handler.PutTickerUsers)
admin.DELETE(`/tickers/:tickerID/users/:userID`, user.NeedAdmin(), ticker.PrefetchTicker(store), handler.DeleteTickerUser)

admin.GET(`/tickers/:tickerID/messages`, ticker.PrefetchTicker(store, storage.WithPreload()), handler.GetMessages)
admin.GET(`/tickers/:tickerID/messages/:messageID`, ticker.PrefetchTicker(store, storage.WithPreload()), message.PrefetchMessage(store), handler.GetMessage)
admin.POST(`/tickers/:tickerID/messages`, ticker.PrefetchTicker(store), handler.PostMessage)
admin.DELETE(`/tickers/:tickerID/messages/:messageID`, ticker.PrefetchTicker(store), message.PrefetchMessage(store), handler.DeleteMessage)

admin.POST(`/upload`, handler.PostUpload)

admin.GET(`/users`, user.NeedAdmin(), handler.GetUsers)
admin.GET(`/users/:userID`, user.PrefetchUser(storage), handler.GetUser)
admin.GET(`/users/:userID`, user.PrefetchUser(store), handler.GetUser)
admin.POST(`/users`, user.NeedAdmin(), handler.PostUser)
admin.PUT(`/users/me`, handler.PutMe)
admin.PUT(`/users/:userID`, user.NeedAdmin(), user.PrefetchUser(storage), handler.PutUser)
admin.DELETE(`/users/:userID`, user.NeedAdmin(), user.PrefetchUser(storage), handler.DeleteUser)
admin.PUT(`/users/:userID`, user.NeedAdmin(), user.PrefetchUser(store), handler.PutUser)
admin.DELETE(`/users/:userID`, user.NeedAdmin(), user.PrefetchUser(store), handler.DeleteUser)

admin.GET(`/settings/:name`, user.NeedAdmin(), handler.GetSetting)
admin.PUT(`/settings/inactive_settings`, user.NeedAdmin(), handler.PutInactiveSettings)
Expand All @@ -115,8 +115,8 @@ func API(config config.Config, storage storage.Storage, log *logrus.Logger) *gin
public.POST(`/admin/login`, authMiddleware.LoginHandler)

public.GET(`/init`, response_cache.CachePage(inMemoryCache, cacheTtl, handler.GetInit))
public.GET(`/timeline`, ticker.PrefetchTickerFromRequest(storage), response_cache.CachePage(inMemoryCache, cacheTtl, handler.GetTimeline))
public.GET(`/feed`, ticker.PrefetchTickerFromRequest(storage), response_cache.CachePage(inMemoryCache, cacheTtl, handler.GetFeed))
public.GET(`/timeline`, ticker.PrefetchTickerFromRequest(store), response_cache.CachePage(inMemoryCache, cacheTtl, handler.GetTimeline))
public.GET(`/feed`, ticker.PrefetchTickerFromRequest(store), response_cache.CachePage(inMemoryCache, cacheTtl, handler.GetFeed))
}

r.GET(`/media/:fileName`, handler.GetMedia)
Expand Down
3 changes: 2 additions & 1 deletion internal/api/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/systemli/ticker/internal/api/helper"
"github.com/systemli/ticker/internal/api/response"
"github.com/systemli/ticker/internal/storage"
)

// GetInit returns the basic settings for the ticker.
Expand All @@ -30,7 +31,7 @@ func (h *handler) GetInit(c *gin.Context) {
return
}

ticker, err := h.storage.FindTickerByDomain(domain)
ticker, err := h.storage.FindTickerByDomain(domain, storage.WithInformation())
if err != nil || !ticker.Active {
settings.InactiveSettings = h.storage.GetInactiveSettings()
c.JSON(http.StatusOK, response.SuccessResponse(map[string]interface{}{"ticker": nil, "settings": settings}))
Expand Down
4 changes: 2 additions & 2 deletions internal/api/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestGetInit(t *testing.T) {
ticker.Active = true
s := &storage.MockStorage{}
s.On("GetRefreshIntervalSettings").Return(storage.DefaultRefreshIntervalSettings())
s.On("FindTickerByDomain", mock.AnythingOfType("string")).Return(ticker, nil)
s.On("FindTickerByDomain", mock.AnythingOfType("string"), mock.Anything).Return(ticker, nil)

h := handler{
storage: s,
Expand Down Expand Up @@ -60,7 +60,7 @@ func TestGetInitInactiveTicker(t *testing.T) {
s := &storage.MockStorage{}
s.On("GetRefreshIntervalSettings").Return(storage.DefaultRefreshIntervalSettings())
s.On("GetInactiveSettings").Return(storage.DefaultInactiveSettings())
s.On("FindTickerByDomain", mock.AnythingOfType("string")).Return(ticker, nil)
s.On("FindTickerByDomain", mock.AnythingOfType("string"), mock.Anything).Return(ticker, nil)

h := handler{
storage: s,
Expand Down
2 changes: 1 addition & 1 deletion internal/api/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func (h *handler) GetMessages(c *gin.Context) {
}

pagination := pagination.NewPagination(c)
messages, err := h.storage.FindMessagesByTickerAndPagination(ticker, *pagination)
messages, err := h.storage.FindMessagesByTickerAndPagination(ticker, *pagination, storage.WithAttachments())
if err != nil {
c.JSON(http.StatusNotFound, response.ErrorResponse(response.CodeDefault, response.StorageError))
return
Expand Down
6 changes: 3 additions & 3 deletions internal/api/messages_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestGetMessagesStorageError(t *testing.T) {
c, _ := gin.CreateTestContext(w)
c.Set("ticker", storage.Ticker{})
s := &storage.MockStorage{}
s.On("FindMessagesByTickerAndPagination", mock.Anything, mock.Anything).Return([]storage.Message{}, errors.New("storage error"))
s.On("FindMessagesByTickerAndPagination", mock.Anything, mock.Anything, mock.Anything).Return([]storage.Message{}, errors.New("storage error"))
h := handler{
storage: s,
config: config.NewConfig(),
Expand All @@ -55,7 +55,7 @@ func TestGetMessagesEmptyResult(t *testing.T) {
c, _ := gin.CreateTestContext(w)
c.Set("ticker", storage.Ticker{})
s := &storage.MockStorage{}
s.On("FindMessagesByTickerAndPagination", mock.Anything, mock.Anything).Return([]storage.Message{}, errors.New("not found"))
s.On("FindMessagesByTickerAndPagination", mock.Anything, mock.Anything, mock.Anything).Return([]storage.Message{}, errors.New("not found"))
h := handler{
storage: s,
config: config.NewConfig(),
Expand All @@ -71,7 +71,7 @@ func TestGetMessages(t *testing.T) {
c, _ := gin.CreateTestContext(w)
c.Set("ticker", storage.Ticker{})
s := &storage.MockStorage{}
s.On("FindMessagesByTickerAndPagination", mock.Anything, mock.Anything).Return([]storage.Message{}, nil)
s.On("FindMessagesByTickerAndPagination", mock.Anything, mock.Anything, mock.Anything).Return([]storage.Message{}, nil)
h := handler{
storage: s,
config: config.NewConfig(),
Expand Down
2 changes: 1 addition & 1 deletion internal/api/middleware/message/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func PrefetchMessage(s storage.Storage) gin.HandlerFunc {
return
}

message, err := s.FindMessage(ticker.ID, messageID)
message, err := s.FindMessage(ticker.ID, messageID, storage.WithAttachments())
if err != nil {
c.JSON(http.StatusNotFound, response.ErrorResponse(response.CodeNotFound, response.MessageNotFound))
return
Expand Down
4 changes: 2 additions & 2 deletions internal/api/middleware/message/message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func TestPrefetchMessageStorageError(t *testing.T) {
c.AddParam("messageID", "1")
c.Set("ticker", storage.Ticker{})
s := &storage.MockStorage{}
s.On("FindMessage", mock.Anything, mock.Anything).Return(storage.Message{}, errors.New("storage error"))
s.On("FindMessage", mock.Anything, mock.Anything, mock.Anything).Return(storage.Message{}, errors.New("storage error"))
mw := PrefetchMessage(s)

mw(c)
Expand All @@ -49,7 +49,7 @@ func TestPrefetchMessage(t *testing.T) {
c.Set("ticker", storage.Ticker{})
s := &storage.MockStorage{}
message := storage.Message{ID: 1}
s.On("FindMessage", mock.Anything, mock.Anything).Return(message, nil)
s.On("FindMessage", mock.Anything, mock.Anything, mock.Anything).Return(message, nil)
mw := PrefetchMessage(s)

mw(c)
Expand Down
9 changes: 5 additions & 4 deletions internal/api/middleware/ticker/ticker.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import (
"github.com/systemli/ticker/internal/api/response"
"github.com/systemli/ticker/internal/storage"
"github.com/systemli/ticker/internal/util"
"gorm.io/gorm"
)

func PrefetchTicker(s storage.Storage) gin.HandlerFunc {
func PrefetchTicker(s storage.Storage, opts ...func(*gorm.DB) *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
user, _ := helper.Me(c)
tickerID, err := strconv.Atoi(c.Param("tickerID"))
Expand All @@ -31,7 +32,7 @@ func PrefetchTicker(s storage.Storage) gin.HandlerFunc {
}
}

ticker, err := s.FindTickerByID(tickerID)
ticker, err := s.FindTickerByID(tickerID, opts...)

if err != nil {
c.JSON(http.StatusNotFound, response.ErrorResponse(response.CodeNotFound, response.TickerNotFound))
Expand All @@ -42,15 +43,15 @@ func PrefetchTicker(s storage.Storage) gin.HandlerFunc {
}
}

func PrefetchTickerFromRequest(s storage.Storage) gin.HandlerFunc {
func PrefetchTickerFromRequest(s storage.Storage, opts ...func(*gorm.DB) *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
domain, err := helper.GetDomain(c)
if err != nil {
c.JSON(http.StatusOK, response.ErrorResponse(response.CodeDefault, response.TickerNotFound))
return
}

ticker, err := s.FindTickerByDomain(domain)
ticker, err := s.FindTickerByDomain(domain, opts...)
if err != nil {
c.JSON(http.StatusOK, response.ErrorResponse(response.CodeDefault, response.TickerNotFound))
return
Expand Down
6 changes: 3 additions & 3 deletions internal/api/tickers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestGetTickersStorageError(t *testing.T) {
c, _ := gin.CreateTestContext(w)
c.Set("me", storage.User{IsSuperAdmin: true})
s := &storage.MockStorage{}
s.On("FindTickers").Return([]storage.Ticker{}, errors.New("storage error"))
s.On("FindTickers", mock.Anything).Return([]storage.Ticker{}, errors.New("storage error"))
h := handler{
storage: s,
config: config.NewConfig(),
Expand All @@ -56,7 +56,7 @@ func TestGetTickers(t *testing.T) {
c, _ := gin.CreateTestContext(w)
c.Set("me", storage.User{IsSuperAdmin: false, Tickers: []storage.Ticker{{ID: 2}}})
s := &storage.MockStorage{}
s.On("FindTickersByIDs", mock.Anything).Return([]storage.Ticker{}, nil)
s.On("FindTickersByIDs", mock.Anything, mock.Anything).Return([]storage.Ticker{}, nil)
h := handler{
storage: s,
config: config.NewConfig(),
Expand Down Expand Up @@ -115,7 +115,7 @@ func TestGetTickerUsers(t *testing.T) {
c, _ := gin.CreateTestContext(w)
c.Set("ticker", storage.Ticker{})
s := &storage.MockStorage{}
s.On("FindUsersByTicker", mock.Anything).Return([]storage.User{}, nil)
s.On("FindUsersByTicker", mock.Anything, mock.Anything).Return([]storage.User{}, nil)
h := handler{
storage: s,
config: config.NewConfig(),
Expand Down
Loading

0 comments on commit f712eb8

Please sign in to comment.