Skip to content

Commit 634744d

Browse files
committed
Constrain UI to last complete month, consolidate month helpers
- Rename web.GetCurrentMonth → GetLastCompleteMonth (it always returned last month, not the actual current month); rename GetActualCurrentMonth → GetCurrentMonth to match - Apply the same constraint to UI handlers: list pages (packages, countries, fun/current) and series/chart pages now query up to the last complete month instead of the actual current (partial) month - Move MaxEndMonth out of layout/constants into systemarchitectures as a local endMonthUnbounded constant; remove unused MonthMultiplier - Remove layout.LastCompleteMonth() wrapper; callers now call web.GetLastCompleteMonth() directly, leaving constants.go with only SeriesLimit
1 parent bc07aa9 commit 634744d

11 files changed

Lines changed: 29 additions & 32 deletions

File tree

internal/packages/handler_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (m *mockRepository) FindSeriesByName(ctx context.Context, name string, star
3232
}
3333

3434
func currentMonth() int {
35-
return web.GetCurrentMonth()
35+
return web.GetLastCompleteMonth()
3636
}
3737

3838
func newTestMux(repo Repository) *http.ServeMux {

internal/systemarchitectures/handler_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ func TestHandleList_PaginationInvalidCases(t *testing.T) {
200200
}
201201

202202
func currentMonth() int {
203-
return web.GetCurrentMonth()
203+
return web.GetLastCompleteMonth()
204204
}
205205

206206
func TestHandleList_MonthZeroMeansCurrentMonth(t *testing.T) {

internal/ui/compare/handler.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"pkgstatsd/internal/chartdata"
99
"pkgstatsd/internal/packages"
1010
"pkgstatsd/internal/ui/layout"
11+
"pkgstatsd/internal/web"
1112
)
1213

1314
const maxPackages = 10
@@ -40,7 +41,7 @@ func (h *Handler) HandleCompare(w http.ResponseWriter, r *http.Request) {
4041
continue
4142
}
4243

43-
list, err := h.repo.FindSeriesByName(r.Context(), name, 0, layout.MaxEndMonth, layout.SeriesLimit, 0)
44+
list, err := h.repo.FindSeriesByName(r.Context(), name, 0, web.GetLastCompleteMonth(), layout.SeriesLimit, 0)
4445
if err != nil {
4546
// Sanitize 'name' before logging to prevent log injection.
4647
sanitizedName := strings.ReplaceAll(name, "\n", " ")

internal/ui/countrypage/handler.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"pkgstatsd/internal/countries"
77
"pkgstatsd/internal/ui/layout"
8+
"pkgstatsd/internal/web"
89
)
910

1011
const allCountries = 300
@@ -19,7 +20,7 @@ func NewHandler(repo countries.Repository, manifest *layout.Manifest) *Handler {
1920
}
2021

2122
func (h *Handler) HandleCountries(w http.ResponseWriter, r *http.Request) {
22-
currentMonth := layout.CurrentMonth()
23+
currentMonth := web.GetLastCompleteMonth()
2324

2425
list, err := h.repo.FindAll(r.Context(), "", currentMonth, currentMonth, allCountries, 0)
2526
if err != nil {

internal/ui/fundetail/handler.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"pkgstatsd/internal/packages"
1010
"pkgstatsd/internal/ui/fun"
1111
"pkgstatsd/internal/ui/layout"
12+
"pkgstatsd/internal/web"
1213
)
1314

1415
const (
@@ -50,7 +51,7 @@ func (h *Handler) HandleFunDetail(w http.ResponseWriter, r *http.Request) {
5051
}
5152

5253
func (h *Handler) handleCurrent(w http.ResponseWriter, r *http.Request, category *fun.Category) {
53-
currentMonth := layout.CurrentMonth()
54+
currentMonth := web.GetLastCompleteMonth()
5455

5556
var pkgs []packages.PackagePopularity
5657

@@ -80,7 +81,7 @@ func (h *Handler) handleHistory(w http.ResponseWriter, r *http.Request, category
8081
var allSeries []packages.PackagePopularity
8182

8283
for _, name := range category.Packages {
83-
list, err := h.repo.FindSeriesByName(r.Context(), name, 0, layout.MaxEndMonth, layout.SeriesLimit, 0)
84+
list, err := h.repo.FindSeriesByName(r.Context(), name, 0, web.GetLastCompleteMonth(), layout.SeriesLimit, 0)
8485
if err != nil {
8586
slog.Error("failed to fetch package series", "error", err, "name", name)
8687
continue

internal/ui/layout/constants.go

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,3 @@
11
package layout
22

3-
import "time"
4-
5-
const (
6-
MonthMultiplier = 100
7-
SeriesLimit = 10000
8-
MaxEndMonth = 999912
9-
)
10-
11-
func CurrentMonth() int {
12-
now := time.Now()
13-
return now.Year()*MonthMultiplier + int(now.Month())
14-
}
3+
const SeriesLimit = 10000

internal/ui/packagedetail/handler.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"pkgstatsd/internal/chartdata"
77
"pkgstatsd/internal/packages"
88
"pkgstatsd/internal/ui/layout"
9+
"pkgstatsd/internal/web"
910
)
1011

1112
type Handler struct {
@@ -24,7 +25,7 @@ func (h *Handler) HandlePackageDetail(w http.ResponseWriter, r *http.Request) {
2425
return
2526
}
2627

27-
list, err := h.repo.FindSeriesByName(r.Context(), name, 0, layout.MaxEndMonth, layout.SeriesLimit, 0)
28+
list, err := h.repo.FindSeriesByName(r.Context(), name, 0, web.GetLastCompleteMonth(), layout.SeriesLimit, 0)
2829
if err != nil {
2930
layout.ServerError(w, "failed to fetch package series", err)
3031
return

internal/ui/packagepage/handler.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"pkgstatsd/internal/packages"
1111
"pkgstatsd/internal/ui/layout"
12+
"pkgstatsd/internal/web"
1213
)
1314

1415
const (
@@ -36,7 +37,7 @@ func (h *Handler) HandlePackages(w http.ResponseWriter, r *http.Request) {
3637
limit = max(limit, 1)
3738
offset = max(offset, 0)
3839

39-
currentMonth := layout.CurrentMonth()
40+
currentMonth := web.GetLastCompleteMonth()
4041

4142
list, err := h.repo.FindAll(r.Context(), query, currentMonth, currentMonth, limit, offset)
4243
if err != nil {

internal/ui/systemarchitectures/handler.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import (
77
"pkgstatsd/internal/chartdata"
88
"pkgstatsd/internal/systemarchitectures"
99
"pkgstatsd/internal/ui/layout"
10+
"pkgstatsd/internal/web"
1011
)
1112

1213
const (
1314
startMonthCurrent = 202105
1415
endMonthLegacy = 201812
1516
startMonthCommunity = 201712
17+
endMonthUnbounded = 999912
1618
)
1719

1820
type preset struct {
@@ -27,13 +29,13 @@ var presets = []preset{
2729
Label: "current",
2830
Architectures: []string{"aarch64", "armv5", "armv6", "armv7", "i686", "loong64", "riscv64", "x86_64", "x86_64_v2", "x86_64_v3", "x86_64_v4"},
2931
StartMonth: startMonthCurrent,
30-
EndMonth: layout.MaxEndMonth,
32+
EndMonth: endMonthUnbounded,
3133
},
3234
{
3335
Label: "all",
3436
Architectures: []string{"aarch64", "armv5", "armv6", "armv7", "i686", "loong64", "riscv64", "x86_64", "x86_64_v2", "x86_64_v3", "x86_64_v4"},
3537
StartMonth: 0,
36-
EndMonth: layout.MaxEndMonth,
38+
EndMonth: endMonthUnbounded,
3739
},
3840
{
3941
Label: "i686-x86_64",
@@ -45,13 +47,13 @@ var presets = []preset{
4547
Label: "x86_64",
4648
Architectures: []string{"x86_64", "x86_64_v2", "x86_64_v3", "x86_64_v4"},
4749
StartMonth: startMonthCurrent,
48-
EndMonth: layout.MaxEndMonth,
50+
EndMonth: endMonthUnbounded,
4951
},
5052
{
5153
Label: "community",
5254
Architectures: []string{"aarch64", "armv5", "armv6", "armv7", "i686", "loong64", "riscv64"},
5355
StartMonth: startMonthCommunity,
54-
EndMonth: layout.MaxEndMonth,
56+
EndMonth: endMonthUnbounded,
5557
},
5658
}
5759

@@ -78,8 +80,9 @@ func (h *Handler) HandleCompare(w http.ResponseWriter, r *http.Request) {
7880

7981
var allSeries []systemarchitectures.SystemArchitecturePopularity
8082

83+
endMonth := min(p.EndMonth, web.GetLastCompleteMonth())
8184
for _, arch := range p.Architectures {
82-
list, err := h.repo.FindSeriesByName(r.Context(), arch, p.StartMonth, p.EndMonth, layout.SeriesLimit, 0)
85+
list, err := h.repo.FindSeriesByName(r.Context(), arch, p.StartMonth, endMonth, layout.SeriesLimit, 0)
8386
if err != nil {
8487
// G706: Log injection via taint analysis (gosec)
8588
// 'arch' is a hardcoded string from presets, not user input.

internal/web/request.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,23 @@ func ParseIntParam(r *http.Request, key string, defaultValue int) (int, error) {
3434
return v, nil
3535
}
3636

37-
// GetCurrentMonth returns the last complete month as an integer (YYYYMM).
38-
func GetCurrentMonth() int {
37+
// GetLastCompleteMonth returns the last complete month as an integer (YYYYMM).
38+
func GetLastCompleteMonth() int {
3939
now := time.Now()
4040
lastMonth := now.AddDate(0, -1, 0)
4141
return lastMonth.Year()*monthMultiplier + int(lastMonth.Month())
4242
}
4343

44-
// GetActualCurrentMonth returns the actual current month as an integer (YYYYMM).
45-
func GetActualCurrentMonth() int {
44+
// GetCurrentMonth returns the actual current month as an integer (YYYYMM).
45+
func GetCurrentMonth() int {
4646
now := time.Now()
4747
return now.Year()*monthMultiplier + int(now.Month())
4848
}
4949

5050
// ParseMonthRange extracts and validates startMonth and endMonth from query parameters.
5151
func ParseMonthRange(r *http.Request) (startMonth, endMonth int, err error) {
52-
defaultMonth := GetCurrentMonth()
53-
actualMonth := GetActualCurrentMonth()
52+
defaultMonth := GetLastCompleteMonth()
53+
actualMonth := GetCurrentMonth()
5454

5555
startMonth, err = ParseIntParam(r, "startMonth", defaultMonth)
5656
if err != nil {

0 commit comments

Comments
 (0)