From 8bca777a6d133062e981b24fdec4a455d84cf993 Mon Sep 17 00:00:00 2001 From: Julien Voisin Date: Wed, 13 Aug 2025 04:46:14 +0200 Subject: [PATCH] refactor(model): remove some indirection For small fixed-size structures, it's better to use a slice of values, instead of a slice of pointers to values: they're stored contiguously and thus can be iterated on quickly by the CPU, and it does remove an indirection per object every time the GC kicks in. --- internal/model/api_key.go | 4 +++- internal/model/category.go | 7 ++++--- internal/model/user_session.go | 2 +- internal/storage/api_key.go | 2 +- internal/storage/category.go | 4 ++-- internal/storage/user_session.go | 2 +- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/internal/model/api_key.go b/internal/model/api_key.go index f6609902..06fe84ce 100644 --- a/internal/model/api_key.go +++ b/internal/model/api_key.go @@ -8,6 +8,8 @@ import ( ) // APIKey represents an application API key. +// We need to use a pointer for LastUsedAt, +// as the value obtained from the database might sometimes be nil. type APIKey struct { ID int64 `json:"id"` UserID int64 `json:"user_id"` @@ -18,7 +20,7 @@ type APIKey struct { } // APIKeys represents a collection of API Key. -type APIKeys []*APIKey +type APIKeys []APIKey // APIKeyCreationRequest represents the request to create a new API Key. type APIKeyCreationRequest struct { diff --git a/internal/model/category.go b/internal/model/category.go index 9e85de6d..2e82322c 100644 --- a/internal/model/category.go +++ b/internal/model/category.go @@ -11,8 +11,9 @@ type Category struct { Title string `json:"title"` UserID int64 `json:"user_id"` HideGlobally bool `json:"hide_globally"` - FeedCount *int `json:"feed_count,omitempty"` - TotalUnread *int `json:"total_unread,omitempty"` + // Pointers are needed to avoid breaking /v1/categories?counts=true + FeedCount *int `json:"feed_count,omitempty"` + TotalUnread *int `json:"total_unread,omitempty"` } func (c *Category) String() string { @@ -40,4 +41,4 @@ func (c *CategoryModificationRequest) Patch(category *Category) { } // Categories represents a list of categories. -type Categories []*Category +type Categories []Category diff --git a/internal/model/user_session.go b/internal/model/user_session.go index bec4cc77..46660744 100644 --- a/internal/model/user_session.go +++ b/internal/model/user_session.go @@ -30,7 +30,7 @@ func (u *UserSession) UseTimezone(tz string) { } // UserSessions represents a list of sessions. -type UserSessions []*UserSession +type UserSessions []UserSession // UseTimezone converts creation date of all sessions to the given timezone. func (u UserSessions) UseTimezone(tz string) { diff --git a/internal/storage/api_key.go b/internal/storage/api_key.go index 66a6fa55..dd4c6954 100644 --- a/internal/storage/api_key.go +++ b/internal/storage/api_key.go @@ -62,7 +62,7 @@ func (s *Storage) APIKeys(userID int64) (model.APIKeys, error) { return nil, fmt.Errorf(`store: unable to fetch API Key row: %v`, err) } - apiKeys = append(apiKeys, &apiKey) + apiKeys = append(apiKeys, apiKey) } return apiKeys, nil diff --git a/internal/storage/category.go b/internal/storage/category.go index 4f8ea5de..8035c374 100644 --- a/internal/storage/category.go +++ b/internal/storage/category.go @@ -103,7 +103,7 @@ func (s *Storage) Categories(userID int64) (model.Categories, error) { return nil, fmt.Errorf(`store: unable to fetch category row: %v`, err) } - categories = append(categories, &category) + categories = append(categories, category) } return categories, nil @@ -158,7 +158,7 @@ func (s *Storage) CategoriesWithFeedCount(userID int64) (model.Categories, error return nil, fmt.Errorf(`store: unable to fetch category row: %v`, err) } - categories = append(categories, &category) + categories = append(categories, category) } return categories, nil diff --git a/internal/storage/user_session.go b/internal/storage/user_session.go index a16f8b8d..2e5b1ff4 100644 --- a/internal/storage/user_session.go +++ b/internal/storage/user_session.go @@ -48,7 +48,7 @@ func (s *Storage) UserSessions(userID int64) (model.UserSessions, error) { return nil, fmt.Errorf(`store: unable to fetch user session row: %v`, err) } - sessions = append(sessions, &session) + sessions = append(sessions, session) } return sessions, nil