subreddits: moved to bob

This commit is contained in:
Tigor Hutasuhut 2024-04-24 13:01:13 +07:00
parent 4f2905233d
commit c8c8cc892d
5 changed files with 56 additions and 38 deletions

View file

@ -43,7 +43,7 @@ build: build-dependencies prepare
prepare: gen prepare: gen
mkdir -p public mkdir -p public
tailwindcss -i views/styles.css -o public/styles.css tailwindcss -i views/style.css -o public/style.css
templ generate templ generate
gen: gen:

View file

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"github.com/robfig/cron/v3" "github.com/robfig/cron/v3"
"github.com/stephenafamo/bob"
"github.com/teivah/broadcast" "github.com/teivah/broadcast"
"github.com/tigorlazuardi/redmage/api/bmessage" "github.com/tigorlazuardi/redmage/api/bmessage"
"github.com/tigorlazuardi/redmage/api/reddit" "github.com/tigorlazuardi/redmage/api/reddit"
@ -18,6 +19,7 @@ import (
type API struct { type API struct {
queries *queries.Queries queries *queries.Queries
db *sql.DB db *sql.DB
exec bob.Executor
scheduler *cron.Cron scheduler *cron.Cron
scheduleMap map[cron.EntryID]queries.Subreddit scheduleMap map[cron.EntryID]queries.Subreddit
@ -43,6 +45,7 @@ func New(deps Dependencies) *API {
return &API{ return &API{
queries: deps.Queries, queries: deps.Queries,
db: deps.DB, db: deps.DB,
exec: bob.New(deps.DB),
scheduler: cron.New(), scheduler: cron.New(),
scheduleMap: make(map[cron.EntryID]queries.Subreddit, 8), scheduleMap: make(map[cron.EntryID]queries.Subreddit, 8),
downloadBroadcast: broadcast.NewRelay[bmessage.ImageDownloadMessage](), downloadBroadcast: broadcast.NewRelay[bmessage.ImageDownloadMessage](),

View file

@ -3,7 +3,10 @@ package api
import ( import (
"context" "context"
"github.com/tigorlazuardi/redmage/db/queries" "github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/sqlite/dialect"
"github.com/stephenafamo/bob/dialect/sqlite/sm"
"github.com/tigorlazuardi/redmage/models"
"github.com/tigorlazuardi/redmage/pkg/errs" "github.com/tigorlazuardi/redmage/pkg/errs"
) )
@ -11,46 +14,57 @@ type ListSubredditsParams struct {
Name string `json:"name"` Name string `json:"name"`
Limit int64 `json:"limit"` Limit int64 `json:"limit"`
Offset int64 `json:"offset"` Offset int64 `json:"offset"`
OrderBy string `json:"order_by"`
Sort string `json:"sort"`
}
func (l ListSubredditsParams) Query() (expr []bob.Mod[*dialect.SelectQuery]) {
if l.Name != "" {
expr = append(expr, models.SelectWhere.Subreddits.Name.Like("%"+l.Name+"%"))
}
if l.Limit > 0 {
expr = append(expr, sm.Limit(l.Limit))
}
if l.Offset > 0 {
expr = append(expr, sm.Offset(l.Offset))
}
if l.OrderBy != "" {
if l.Sort == "desc" {
expr = append(expr, sm.OrderBy(l.OrderBy).Desc())
} else {
expr = append(expr, sm.OrderBy(l.OrderBy).Asc())
}
}
return expr
}
func (l ListSubredditsParams) CountQuery() (expr []bob.Mod[*dialect.SelectQuery]) {
if l.Name != "" {
expr = append(expr, models.SelectWhere.Subreddits.Name.Like("%"+l.Name+"%"))
}
return expr
} }
type ListSubredditsResult struct { type ListSubredditsResult struct {
Total int64 Total int64
Data []queries.Subreddit Data models.SubredditSlice
} }
func (api *API) ListSubreddits(ctx context.Context, arg ListSubredditsParams) (result ListSubredditsResult, err error) { func (api *API) ListSubreddits(ctx context.Context, arg ListSubredditsParams) (result ListSubredditsResult, err error) {
ctx, span := tracer.Start(ctx, "api.ListSubreddits") ctx, span := tracer.Start(ctx, "api.ListSubreddits")
defer span.End() defer span.End()
if arg.Name != "" {
result.Data, err = api.queries.SubredditsSearch(ctx, queries.SubredditsSearchParams{ result.Data, err = models.Subreddits.Query(ctx, api.exec, arg.Query()...).All()
Name: "%" + arg.Name + "%",
Limit: arg.Limit,
Offset: arg.Offset,
})
if err != nil { if err != nil {
return result, errs.Wrapw(err, "failed to search subreddit", "query", arg) return result, errs.Wrapw(err, "failed to list subreddits", "query", arg)
}
result.Total, err = api.queries.SubredditsSearchCount(ctx, queries.SubredditsSearchCountParams{
Name: "%" + arg.Name + "%",
Limit: arg.Limit,
Offset: arg.Offset,
})
if err != nil {
return result, errs.Wrapw(err, "failed to count subreddit search", "query", arg)
}
return result, err
} }
result.Data, err = api.queries.SubredditsList(ctx, queries.SubredditsListParams{ result.Total, err = models.Subreddits.Query(ctx, api.exec, arg.CountQuery()...).Count()
Limit: arg.Limit,
Offset: arg.Offset,
})
if err != nil { if err != nil {
return result, errs.Wrapw(err, "failed to list subreddit", "query", arg) return result, errs.Wrapw(err, "failed to count subreddits", "query", arg)
} }
result.Total, err = api.queries.SubredditsListCount(ctx)
if err != nil { return result, nil
return result, errs.Wrapw(err, "failed to count subreddit list", "query", arg)
}
return result, err
} }

View file

@ -26,7 +26,7 @@ func (ch *ChiEntry) Write(status int, bytes int, header http.Header, elapsed tim
message := fmt.Sprintf("%s %s %d %s", ch.request.Method, ch.request.URL, status, elasedStr) message := fmt.Sprintf("%s %s %d %s", ch.request.Method, ch.request.URL, status, elasedStr)
requestLog := slog.Attr{Key: "request", Value: ch.extractRequestLog()} requestLog := slog.Attr{Key: "request", Value: ch.extractRequestLog()}
responseLog := slog.Group("response", "status", status, "headers", flatHeader(header), "bytes", bytes) responseLog := slog.Group("response", "status", status, "headers", flat(header), "bytes", bytes)
roundtripLog := slog.String("elapsed", elasedStr) roundtripLog := slog.String("elapsed", elasedStr)
group := slog.Group("http", requestLog, responseLog, roundtripLog) group := slog.Group("http", requestLog, responseLog, roundtripLog)
@ -57,13 +57,13 @@ func (ch *ChiEntry) extractRequestLog() slog.Value {
) )
queries := ch.request.URL.Query() queries := ch.request.URL.Query()
if len(queries) > 0 { if len(queries) > 0 {
values = append(values, slog.Any("query", queries)) values = append(values, slog.Any("query", flat(queries)))
} }
values = append(values, slog.Any("headers", flatHeader(ch.request.Header))) values = append(values, slog.Any("headers", flat(ch.request.Header)))
return slog.GroupValue(values...) return slog.GroupValue(values...)
} }
func flatHeader(header http.Header) map[string]string { func flat(header map[string][]string) map[string]string {
m := make(map[string]string, len(header)) m := make(map[string]string, len(header))
for k := range header { for k := range header {

View file

@ -40,6 +40,7 @@ func (routes *Routes) registerV1APIRoutes(router chi.Router) {
} }
func (routes *Routes) registerWWWRoutes(router chi.Router) { func (routes *Routes) registerWWWRoutes(router chi.Router) {
router.Use(chimiddleware.Compress(5, "text/html", "text/css", "application/javascript"))
router.Mount("/public", http.StripPrefix("/public", http.FileServer(http.FS(routes.PublicDir)))) router.Mount("/public", http.StripPrefix("/public", http.FileServer(http.FS(routes.PublicDir))))
router.Group(func(r chi.Router) { router.Group(func(r chi.Router) {