From 3d900df15b68a0b10eaef5b399ed7b14a31139a6 Mon Sep 17 00:00:00 2001 From: dbastrikin Date: Sun, 22 Feb 2026 15:30:40 +0200 Subject: [PATCH] fix: increase connectTimeout and replace expires_at stored column refs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - api_client.dart: connectTimeout 10s → 60s — Flutter was cancelling requests to /recommendations after 10s while the server waited for OpenAI, causing 'context canceled' on the server side - product/repository.go ListForPrompt: expires_at is computed via (added_at + storage_days * INTERVAL '1 day'), not a stored column; wrap in CTE to reference it by alias in SELECT/ORDER BY - home/handler.go getExpiringSoon: same fix — use CTE to compute expires_at before filtering/ordering by it Co-Authored-By: Claude Sonnet 4.6 --- backend/internal/home/handler.go | 12 ++++++++---- backend/internal/product/repository.go | 9 +++++++-- client/lib/core/api/api_client.dart | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/backend/internal/home/handler.go b/backend/internal/home/handler.go index 1592dac..2f92a46 100644 --- a/backend/internal/home/handler.go +++ b/backend/internal/home/handler.go @@ -150,12 +150,16 @@ func defaultPlan() []MealPlan { // getExpiringSoon returns products expiring within the next 3 days. func (h *Handler) getExpiringSoon(ctx context.Context, userID string) []ExpiringSoon { rows, err := h.pool.Query(ctx, ` + WITH p AS ( + SELECT name, quantity, unit, + (added_at + storage_days * INTERVAL '1 day') AS expires_at + FROM products + WHERE user_id = $1 + ) SELECT name, quantity, unit, GREATEST(0, EXTRACT(EPOCH FROM (expires_at - now())) / 86400)::int - FROM products - WHERE user_id = $1 - AND expires_at IS NOT NULL - AND expires_at > now() + FROM p + WHERE expires_at > now() AND expires_at <= now() + INTERVAL '3 days' ORDER BY expires_at LIMIT 5`, diff --git a/backend/internal/product/repository.go b/backend/internal/product/repository.go index 52264f2..ebce450 100644 --- a/backend/internal/product/repository.go +++ b/backend/internal/product/repository.go @@ -117,9 +117,14 @@ func (r *Repository) Delete(ctx context.Context, id, userID string) error { // Expiring soon items are marked with ⚠. func (r *Repository) ListForPrompt(ctx context.Context, userID string) ([]string, error) { rows, err := r.pool.Query(ctx, ` + WITH p AS ( + SELECT name, quantity, unit, + (added_at + storage_days * INTERVAL '1 day') AS expires_at + FROM products + WHERE user_id = $1 + ) SELECT name, quantity, unit, expires_at - FROM products - WHERE user_id = $1 + FROM p ORDER BY expires_at ASC`, userID) if err != nil { return nil, fmt.Errorf("list products for prompt: %w", err) diff --git a/client/lib/core/api/api_client.dart b/client/lib/core/api/api_client.dart index ebc381e..0799fcf 100644 --- a/client/lib/core/api/api_client.dart +++ b/client/lib/core/api/api_client.dart @@ -8,7 +8,7 @@ class ApiClient { ApiClient({required String baseUrl, required SecureStorageService storage}) { _dio = Dio(BaseOptions( baseUrl: baseUrl, - connectTimeout: const Duration(seconds: 10), + connectTimeout: const Duration(seconds: 60), receiveTimeout: const Duration(seconds: 120), headers: {'Content-Type': 'application/json'}, ));