From 6bd219ea4f3a5d766ffe5e5ad9bb3dcdecff45d7 Mon Sep 17 00:00:00 2001 From: Tigor Hutasuhut Date: Tue, 7 May 2024 10:33:56 +0700 Subject: [PATCH] subreddit: starting download preemptively sends now sends "requires at least one device enabled message" if no devices are enabled --- api/devices_count.go | 19 ++++++++++++++++ server/routes/middleware/logger.go | 35 +++++++++++++++++++++++++----- server/routes/subreddit_start.go | 22 ++++++++++++++++++- 3 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 api/devices_count.go diff --git a/api/devices_count.go b/api/devices_count.go new file mode 100644 index 0000000..8bdbe38 --- /dev/null +++ b/api/devices_count.go @@ -0,0 +1,19 @@ +package api + +import ( + "context" + + "github.com/tigorlazuardi/redmage/models" + "github.com/tigorlazuardi/redmage/pkg/errs" +) + +func (api *API) DevicesCountEnabled(ctx context.Context) (int64, error) { + ctx, span := tracer.Start(ctx, "*API.DevicesCountEnabled") + defer span.End() + + count, err := models.Devices.Query(ctx, api.db, models.SelectWhere.Devices.Enable.EQ(1)).Count() + if err != nil { + return 0, errs.Wrapw(err, "failed to count enabled devices") + } + return count, nil +} diff --git a/server/routes/middleware/logger.go b/server/routes/middleware/logger.go index 711a746..4948a39 100644 --- a/server/routes/middleware/logger.go +++ b/server/routes/middleware/logger.go @@ -22,14 +22,18 @@ type ChiEntry struct { } func (ch *ChiEntry) Write(status int, bytes int, header http.Header, elapsed time.Duration, extra interface{}) { - elasedStr := formatDuration(elapsed) - message := fmt.Sprintf("%s %s %d %s", ch.request.Method, ch.request.URL, status, elasedStr) + elapsedStr := formatDuration(elapsed) + message := fmt.Sprintf("%s %s %d %s %s", ch.request.Method, ch.request.URL, status, elapsedStr, formatByteSize(bytes)) - requestLog := slog.Attr{Key: "request", Value: ch.extractRequestLog()} - responseLog := slog.Group("response", "status", status, "headers", flat(header), "bytes", bytes) - roundtripLog := slog.String("elapsed", elasedStr) + var group slog.Attr + + if status >= 500 { + requestLog := slog.Attr{Key: "request", Value: ch.extractRequestLog()} + responseLog := slog.Group("response", "status", status, "headers", flat(header), "bytes", bytes) + roundtripLog := slog.String("elapsed", elapsedStr) + group = slog.Group("http", requestLog, responseLog, roundtripLog) + } - group := slog.Group("http", requestLog, responseLog, roundtripLog) if status >= 400 { log.New(ch.request.Context()).With(group).Error(message) return @@ -38,6 +42,25 @@ func (ch *ChiEntry) Write(status int, bytes int, header http.Header, elapsed tim log.New(ch.request.Context()).With(group).Info(message) } +func formatByteSize(bytes int) string { + const ( + kb = 1024 + mb = 1024 * kb + gb = 1024 * mb + ) + + switch { + case bytes >= gb: + return fmt.Sprintf("%.2fGB", float64(bytes)/float64(gb)) + case bytes >= mb: + return fmt.Sprintf("%.2fMB", float64(bytes)/float64(mb)) + case bytes >= kb: + return fmt.Sprintf("%.2fKB", float64(bytes)/float64(kb)) + default: + return fmt.Sprintf("%d bytes", bytes) + } +} + func (ch *ChiEntry) Panic(v interface{}, stack []byte) { group := slog.Group("http", slog.Attr{Key: "request", Value: ch.extractRequestLog()}) entry := log.New(ch.request.Context()) diff --git a/server/routes/subreddit_start.go b/server/routes/subreddit_start.go index cf06c20..438bbe9 100644 --- a/server/routes/subreddit_start.go +++ b/server/routes/subreddit_start.go @@ -55,10 +55,30 @@ func (routes *Routes) SubredditStartDownloadHTMX(rw http.ResponseWriter, r *http return } + count, err := routes.API.DevicesCountEnabled(ctx) + if err != nil { + log.New(ctx).Err(err).Error("failed to devices") + code, message := errs.HTTPMessage(err) + rw.WriteHeader(code) + if err := components.ErrorNotication(message).Render(ctx, rw); err != nil { + log.New(ctx).Err(err).Error("failed to render error notification") + } + return + } + + if count == 0 { + msg := "Starting subreddit download requires at least one device configured and enabled" + rw.WriteHeader(http.StatusBadRequest) + if err := components.ErrorNotication(msg).Render(ctx, rw); err != nil { + log.New(ctx).Err(err).Error("failed to render error notification") + } + return + } + var body api.PubsubStartDownloadSubredditParams body.Subreddit = r.FormValue("subreddit") - err := routes.API.PubsubStartDownloadSubreddit(ctx, body) + err = routes.API.PubsubStartDownloadSubreddit(ctx, body) if err != nil { log.New(ctx).Err(err).Error("failed to start subreddit download", "subreddit", body.Subreddit) code, message := errs.HTTPMessage(err)