# 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
