mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
dev day #80
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
# 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:
|
||||
|
||||
```json
|
||||
{"items":[],"page":1,"page_size":10,"total":0}
|
||||
```
|
||||
|
||||
**Root Causes:**
|
||||
1. **Prefetch runs every 30 minutes** - New articles weren't appearing in cache immediately
|
||||
2. **No automatic cache refresh** - Creating/updating articles didn't trigger prefetch
|
||||
3. **Match link data is loaded separately** - The `GetArticles` endpoint 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:
|
||||
|
||||
```go
|
||||
// 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:**
|
||||
```go
|
||||
// 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:
|
||||
|
||||
```go
|
||||
// Trigger full prefetch cache update if article is published
|
||||
if art.Published {
|
||||
go func() {
|
||||
base := getPrefetchBaseURL()
|
||||
services.PrefetchOnce(base)
|
||||
}()
|
||||
}
|
||||
```
|
||||
|
||||
**Helper function added:**
|
||||
```go
|
||||
// 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:
|
||||
|
||||
1. Queries articles from database with `Preload("Author").Preload("Category")`
|
||||
2. **Batch loads match links** for all articles:
|
||||
```go
|
||||
var matchLinks []models.ArticleMatchLink
|
||||
bc.DB.Where("article_id IN ?", articleIDs).Find(&matchLinks)
|
||||
```
|
||||
3. Assigns match links to each article in the response
|
||||
4. Returns JSON with full article data including `match_link` object
|
||||
|
||||
The JSON response structure includes:
|
||||
```json
|
||||
{
|
||||
"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
|
||||
1. Go to `/admin/articles`
|
||||
2. Create a new article with "Publikovat" checked
|
||||
3. Optionally link to a match via the match selector
|
||||
4. Click "Vytvořit článek"
|
||||
5. **Wait ~2 seconds** for prefetch to complete
|
||||
6. Check `cache/prefetch/articles.json` - it should now contain your article with full data including match link
|
||||
|
||||
### 2. Update an Existing Article
|
||||
1. Edit an existing article
|
||||
2. Change content or publish status
|
||||
3. Save changes
|
||||
4. **Wait ~2 seconds** for prefetch to complete
|
||||
5. Check cache file - it should be updated
|
||||
|
||||
### 3. Manual Trigger (Admin)
|
||||
You can also manually trigger prefetch:
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
1. `internal/controllers/article_controller.go` - Added prefetch trigger on create
|
||||
2. `internal/controllers/base_controller.go` - Added prefetch trigger on update
|
||||
3. `ARTICLE_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
|
||||
Reference in New Issue
Block a user