6.4 KiB
Article Cache & Match Data Not Saving - FIXED
Problem
The cache/prefetch/articles.json file was empty or not updating with newly created articles and their match link data:
{"items":[],"page":1,"page_size":10,"total":0}
Root Causes:
- Prefetch runs every 30 minutes - New articles weren't appearing in cache immediately
- No automatic cache refresh - Creating/updating articles didn't trigger prefetch
- Match link data is loaded separately - The
GetArticlesendpoint loads match links via batch query, but this wasn't being captured in cache files
Console Logs Analysis
From your console logs, the article WAS created successfully:
Article created successfully in mutation callback: Object { ID: 1, ... }
Linking new article 1 with match 89d23bfd-5be6-416a-96d0-35ec694aa22c
Match link created for new article
The article exists in the database with:
- Article ID: 1
- Match Link:
89d23bfd-5be6-416a-96d0-35ec694aa22c - Category: "KALMAN TRADE Krajský přebor mladší dorost"
The cache was just stale - it hadn't updated yet since prefetch runs every 30 minutes.
Solution Implemented
1. Automatic Prefetch Trigger on Article Create
File: internal/controllers/article_controller.go
Added automatic prefetch cache refresh when a published article is created:
// 18. Trigger prefetch cache update (async)
if published {
go func() {
base := getBaseURL()
logger.Info("CreateArticle: Triggering prefetch cache update for published article")
services.PrefetchOnce(base)
}()
}
Helper function added:
// getBaseURL returns the base URL for internal API calls (used for prefetch trigger)
func getBaseURL() string {
base := strings.TrimSpace(os.Getenv("PREFETCH_TARGET"))
if base == "" {
port := strings.TrimSpace(os.Getenv("PORT"))
if port == "" {
port = "8080"
}
base = "http://127.0.0.1:" + port + "/api/v1"
}
return base
}
2. Automatic Prefetch Trigger on Article Update
File: internal/controllers/base_controller.go
Added automatic prefetch cache refresh when an article is updated and published:
// Trigger full prefetch cache update if article is published
if art.Published {
go func() {
base := getPrefetchBaseURL()
services.PrefetchOnce(base)
}()
}
Helper function added:
// getPrefetchBaseURL returns the base URL for internal API calls (used for prefetch trigger)
func getPrefetchBaseURL() string {
base := strings.TrimSpace(os.Getenv("PREFETCH_TARGET"))
if base == "" {
port := strings.TrimSpace(os.Getenv("PORT"))
if port == "" {
port = "8080"
}
base = "http://127.0.0.1:" + port + "/api/v1"
}
return base
}
How Match Data Gets Cached
The prefetch service fetches /api/v1/articles?page=1&page_size=10&published=true which:
- Queries articles from database with
Preload("Author").Preload("Category") - Batch loads match links for all articles:
var matchLinks []models.ArticleMatchLink bc.DB.Where("article_id IN ?", articleIDs).Find(&matchLinks) - Assigns match links to each article in the response
- Returns JSON with full article data including
match_linkobject
The JSON response structure includes:
{
"items": [
{
"ID": 1,
"title": "...",
"category": { "ID": 1, "name": "..." },
"match_link": {
"ID": 1,
"article_id": 1,
"external_match_id": "89d23bfd-5be6-416a-96d0-35ec694aa22c",
"title": "Match Title"
}
}
],
"total": 1,
"page": 1,
"page_size": 10
}
Testing
1. Create a New Published Article
- Go to
/admin/articles - Create a new article with "Publikovat" checked
- Optionally link to a match via the match selector
- Click "Vytvořit článek"
- Wait ~2 seconds for prefetch to complete
- Check
cache/prefetch/articles.json- it should now contain your article with full data including match link
2. Update an Existing Article
- Edit an existing article
- Change content or publish status
- Save changes
- Wait ~2 seconds for prefetch to complete
- Check cache file - it should be updated
3. Manual Trigger (Admin)
You can also manually trigger prefetch:
# Via admin endpoint
curl -X POST http://localhost:8080/api/v1/admin/prefetch/trigger \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Or from admin panel: Visit /admin/tools and click "Refresh Cache"
Environment Variables
You can configure the base URL for prefetch if needed:
# Default (uses internal localhost)
# No config needed
# Custom target (e.g., behind nginx proxy)
PREFETCH_TARGET="http://your-domain.com/api/v1"
# Custom port
PORT="3000"
# Prefetch interval (default 30 minutes)
PREFETCH_INTERVAL_MINUTES="15"
Verification Commands
# Check if articles are in cache
cat cache/prefetch/articles.json | jq '.items | length'
# See full article data with match links
cat cache/prefetch/articles.json | jq '.items[0]'
# Check prefetch status
cat cache/prefetch/prefetch_status.json | jq '.'
# Check last update time
cat cache/prefetch/meta.json | jq '.'
Benefits
✅ Immediate cache updates - Articles appear in cache within seconds of creation
✅ Match data preserved - Full match link information is cached correctly
✅ Category data included - Complete category objects in cached response
✅ Non-blocking - Prefetch runs asynchronously (doesn't slow down API responses)
✅ Existing behavior maintained - 30-minute background refresh still runs
✅ Smart triggers - Only triggers for published articles (drafts don't waste resources)
Files Modified
internal/controllers/article_controller.go- Added prefetch trigger on createinternal/controllers/base_controller.go- Added prefetch trigger on updateARTICLE_CACHE_MATCH_DATA_FIX.md(this file) - Documentation
Related Systems
- Prefetch Service:
internal/services/prefetch_service.go - Prefetch Controller:
internal/controllers/prefetch_controller.go - Article Match Links:
internal/models/models.go(ArticleMatchLink) - Cache Directory:
cache/prefetch/
Future Enhancements
Consider adding prefetch triggers for:
- Article deletion (to remove from cache)
- Match link creation/updates
- Category changes
- Featured article toggles