mirror of
https://github.com/ksyasuda/dotfiles.git
synced 2026-03-21 18:11:27 -07:00
update skills
This commit is contained in:
194
.agents/skills/cloudflare-deploy/references/cache-reserve/api.md
Normal file
194
.agents/skills/cloudflare-deploy/references/cache-reserve/api.md
Normal file
@@ -0,0 +1,194 @@
|
||||
# Cache Reserve API
|
||||
|
||||
## Workers Integration
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────────┐
|
||||
│ CRITICAL: Workers Cache API ≠ Cache Reserve │
|
||||
│ │
|
||||
│ • Workers caches.default / cache.put() → edge cache ONLY │
|
||||
│ • Cache Reserve → zone-level setting, automatic, no per-req │
|
||||
│ • You CANNOT selectively write to Cache Reserve from Workers │
|
||||
│ • Cache Reserve works with standard fetch(), not cache.put() │
|
||||
└────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Cache Reserve is a **zone-level configuration**, not a per-request API. It works automatically when enabled for the zone:
|
||||
|
||||
### Standard Fetch (Recommended)
|
||||
|
||||
```typescript
|
||||
// Cache Reserve works automatically via standard fetch
|
||||
export default {
|
||||
async fetch(request: Request, env: Env): Promise<Response> {
|
||||
// Standard fetch uses Cache Reserve automatically
|
||||
return await fetch(request);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Cache API Limitations
|
||||
|
||||
**IMPORTANT**: `cache.put()` is **NOT compatible** with Cache Reserve or Tiered Cache.
|
||||
|
||||
```typescript
|
||||
// ❌ WRONG: cache.put() bypasses Cache Reserve
|
||||
const cache = caches.default;
|
||||
let response = await cache.match(request);
|
||||
if (!response) {
|
||||
response = await fetch(request);
|
||||
await cache.put(request, response.clone()); // Bypasses Cache Reserve!
|
||||
}
|
||||
|
||||
// ✅ CORRECT: Use standard fetch for Cache Reserve compatibility
|
||||
return await fetch(request);
|
||||
|
||||
// ✅ CORRECT: Use Cache API only for custom cache namespaces
|
||||
const customCache = await caches.open('my-custom-cache');
|
||||
let response = await customCache.match(request);
|
||||
if (!response) {
|
||||
response = await fetch(request);
|
||||
await customCache.put(request, response.clone()); // Custom cache OK
|
||||
}
|
||||
```
|
||||
|
||||
## Purging and Cache Management
|
||||
|
||||
### Purge by URL (Instant)
|
||||
|
||||
```typescript
|
||||
// Purge specific URL from Cache Reserve immediately
|
||||
const purgeCacheReserveByURL = async (
|
||||
zoneId: string,
|
||||
apiToken: string,
|
||||
urls: string[]
|
||||
) => {
|
||||
const response = await fetch(
|
||||
`https://api.cloudflare.com/client/v4/zones/${zoneId}/purge_cache`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${apiToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ files: urls })
|
||||
}
|
||||
);
|
||||
return await response.json();
|
||||
};
|
||||
|
||||
// Example usage
|
||||
await purgeCacheReserveByURL('zone123', 'token456', [
|
||||
'https://example.com/image.jpg',
|
||||
'https://example.com/video.mp4'
|
||||
]);
|
||||
```
|
||||
|
||||
### Purge by Tag/Host/Prefix (Revalidation)
|
||||
|
||||
```typescript
|
||||
// Purge by cache tag - forces revalidation, not immediate removal
|
||||
await fetch(
|
||||
`https://api.cloudflare.com/client/v4/zones/${zoneId}/purge_cache`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': `Bearer ${apiToken}`, 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ tags: ['tag1', 'tag2'] })
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
**Purge behavior:**
|
||||
- **By URL**: Immediate removal from Cache Reserve + edge cache
|
||||
- **By tag/host/prefix**: Revalidation only, assets remain in storage (costs continue)
|
||||
|
||||
### Clear All Cache Reserve Data
|
||||
|
||||
```typescript
|
||||
// Requires Cache Reserve OFF first
|
||||
await fetch(
|
||||
`https://api.cloudflare.com/client/v4/zones/${zoneId}/cache/cache_reserve_clear`,
|
||||
{ method: 'POST', headers: { 'Authorization': `Bearer ${apiToken}` } }
|
||||
);
|
||||
|
||||
// Check status: GET same endpoint returns { state: "In-progress" | "Completed" }
|
||||
```
|
||||
|
||||
**Process**: Disable Cache Reserve → Call clear endpoint → Wait up to 24hr → Re-enable
|
||||
|
||||
## Monitoring and Analytics
|
||||
|
||||
### Dashboard Analytics
|
||||
|
||||
Navigate to **Caching > Cache Reserve** to view:
|
||||
|
||||
- **Egress Savings**: Total bytes served from Cache Reserve vs origin egress cost saved
|
||||
- **Requests Served**: Cache Reserve hits vs misses breakdown
|
||||
- **Storage Used**: Current GB stored in Cache Reserve (billed monthly)
|
||||
- **Operations**: Class A (writes) and Class B (reads) operation counts
|
||||
- **Cost Tracking**: Estimated monthly costs based on current usage
|
||||
|
||||
### Logpush Integration
|
||||
|
||||
```typescript
|
||||
// Logpush field: CacheReserveUsed (boolean) - filter for Cache Reserve hits
|
||||
// Query Cache Reserve hits in analytics
|
||||
const logpushQuery = `
|
||||
SELECT
|
||||
ClientRequestHost,
|
||||
COUNT(*) as requests,
|
||||
SUM(EdgeResponseBytes) as bytes_served,
|
||||
COUNT(CASE WHEN CacheReserveUsed = true THEN 1 END) as cache_reserve_hits,
|
||||
COUNT(CASE WHEN CacheReserveUsed = false THEN 1 END) as cache_reserve_misses
|
||||
FROM http_requests
|
||||
WHERE Timestamp >= NOW() - INTERVAL '24 hours'
|
||||
GROUP BY ClientRequestHost
|
||||
ORDER BY requests DESC
|
||||
`;
|
||||
|
||||
// Filter only Cache Reserve hits
|
||||
const crHitsQuery = `
|
||||
SELECT ClientRequestHost, COUNT(*) as requests, SUM(EdgeResponseBytes) as bytes
|
||||
FROM http_requests
|
||||
WHERE CacheReserveUsed = true AND Timestamp >= NOW() - INTERVAL '7 days'
|
||||
GROUP BY ClientRequestHost
|
||||
ORDER BY bytes DESC
|
||||
`;
|
||||
```
|
||||
|
||||
### GraphQL Analytics
|
||||
|
||||
```graphql
|
||||
query CacheReserveAnalytics($zoneTag: string, $since: string, $until: string) {
|
||||
viewer {
|
||||
zones(filter: { zoneTag: $zoneTag }) {
|
||||
httpRequests1dGroups(
|
||||
filter: { datetime_geq: $since, datetime_leq: $until }
|
||||
limit: 1000
|
||||
) {
|
||||
dimensions { date }
|
||||
sum {
|
||||
cachedBytes
|
||||
cachedRequests
|
||||
bytes
|
||||
requests
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Pricing
|
||||
|
||||
```typescript
|
||||
// Storage: $0.015/GB-month | Class A (writes): $4.50/M | Class B (reads): $0.36/M
|
||||
// Cache miss: 1A + 1B | Cache hit: 1B | Assets >1GB: proportionally more ops
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [README](./README.md) - Overview and core concepts
|
||||
- [Configuration](./configuration.md) - Setup and Cache Rules
|
||||
- [Patterns](./patterns.md) - Best practices and optimization
|
||||
- [Gotchas](./gotchas.md) - Common issues and troubleshooting
|
||||
Reference in New Issue
Block a user