Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:52:06 +08:00
commit d9d5734464
17 changed files with 1235 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
{
"name": "api-cache-manager",
"description": "Implement caching strategies with Redis, CDN, and HTTP headers",
"version": "1.0.0",
"author": {
"name": "Jeremy Longshore",
"email": "[email protected]"
},
"skills": [
"./skills"
],
"commands": [
"./commands"
]
}

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# api-cache-manager
Implement caching strategies with Redis, CDN, and HTTP headers

View File

@@ -0,0 +1,532 @@
---
description: Implement comprehensive multi-level API caching strategies with Redis, CDN, and intelligent invalidation
shortcut: cache
category: api
difficulty: intermediate
estimated_time: 2-3 hours
version: 2.0.0
---
<!-- DESIGN DECISIONS -->
<!-- Multi-level caching dramatically reduces database load and improves response times.
This command implements a three-tier caching strategy: browser cache, CDN cache,
and server-side cache with Redis. Intelligent cache invalidation ensures data freshness. -->
<!-- ALTERNATIVES CONSIDERED -->
<!-- Single-level caching: Rejected due to limited effectiveness under high load
Session-based caching: Rejected as it doesn't scale across multiple servers
Database query caching alone: Rejected as it doesn't reduce application server load -->
# Implement API Caching
Creates comprehensive multi-level caching strategies to dramatically improve API performance, reduce database load, and enhance user experience. Implements Redis for server-side caching, CDN integration for edge caching, and proper HTTP cache headers for client-side optimization.
## When to Use
Use this command when:
- API response times exceed acceptable thresholds (>200ms)
- Database queries are repetitive and expensive
- Static or semi-static content dominates API responses
- High traffic causes server strain and increased costs
- Geographic distribution requires edge caching
- Rate limiting needs efficient request counting
- Session data requires fast access across servers
Do NOT use this command for:
- Real-time data that changes every request
- User-specific sensitive data (without proper cache isolation)
- APIs with complex invalidation dependencies
- Small-scale applications where caching adds unnecessary complexity
## Prerequisites
Before running this command, ensure:
- [ ] API endpoints are identified and categorized by cache lifetime
- [ ] Redis or Memcached is available (or can be provisioned)
- [ ] CDN service is configured (CloudFlare, Fastly, or AWS CloudFront)
- [ ] Cache key strategy is defined
- [ ] Monitoring tools are ready to track cache performance
## Process
### Step 1: Analyze API Patterns
The command examines your API to determine optimal caching strategies:
- Identifies read-heavy endpoints suitable for caching
- Categorizes data by volatility (static, semi-dynamic, dynamic)
- Analyzes request patterns and frequency
- Determines appropriate cache TTL values
- Maps data dependencies for invalidation
### Step 2: Implement Server-Side Caching
Sets up Redis-based caching with intelligent patterns:
- Cache-aside pattern for on-demand caching
- Write-through for immediate cache updates
- Write-behind for asynchronous cache population
- Distributed caching for horizontal scaling
- Cache warming for critical data
### Step 3: Configure HTTP Cache Headers
Implements proper HTTP caching directives:
- Cache-Control headers with appropriate max-age
- ETag generation for conditional requests
- Vary headers for content negotiation
- Surrogate-Control for CDN-specific behavior
- Stale-while-revalidate for improved perceived performance
### Step 4: Integrate CDN Caching
Configures edge caching for global distribution:
- Cache rules based on URL patterns
- Geographic cache distribution
- Cache purging API integration
- Origin shield configuration
- Custom cache keys for variants
### Step 5: Implement Cache Invalidation
Creates sophisticated invalidation strategies:
- Tag-based invalidation for related content
- Event-driven cache clearing
- Time-based expiration with jitter
- Cascade invalidation for dependent data
- Soft purging with grace periods
## Output Format
The command generates a complete caching implementation:
```
api-caching/
├── src/
│ ├── cache/
│ │ ├── redis-client.js
│ │ ├── cache-middleware.js
│ │ ├── cache-strategies.js
│ │ └── invalidation-service.js
│ ├── middleware/
│ │ ├── http-cache-headers.js
│ │ └── cdn-integration.js
│ └── utils/
│ ├── cache-key-generator.js
│ └── cache-metrics.js
├── config/
│ ├── cache-config.json
│ ├── redis.config.js
│ └── cdn-rules.json
├── tests/
│ └── cache.test.js
└── docs/
└── caching-strategy.md
```
## Examples
### Example 1: E-commerce Product API with Redis
**Scenario:** High-traffic product catalog requiring sub-100ms response times
**Generated Redis Implementation:**
```javascript
// cache/redis-client.js
import Redis from 'ioredis';
import { promisify } from 'util';
class CacheManager {
constructor() {
this.client = new Redis({
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
password: process.env.REDIS_PASSWORD,
retryStrategy: (times) => Math.min(times * 50, 2000),
enableOfflineQueue: false
});
this.defaultTTL = 3600; // 1 hour default
this.client.on('error', this.handleError);
}
async get(key, options = {}) {
try {
const cached = await this.client.get(key);
if (cached) {
this.metrics.hit(key);
return JSON.parse(cached);
}
this.metrics.miss(key);
// Cache-aside pattern: fetch if not cached
if (options.fetchFunction) {
const data = await options.fetchFunction();
await this.set(key, data, options.ttl);
return data;
}
return null;
} catch (error) {
this.handleError(error);
// Fallback to direct fetch on cache error
return options.fetchFunction ? await options.fetchFunction() : null;
}
}
async set(key, value, ttl = this.defaultTTL) {
const serialized = JSON.stringify(value);
if (ttl) {
await this.client.setex(key, ttl, serialized);
} else {
await this.client.set(key, serialized);
}
// Implement cache tags for invalidation
if (value.tags) {
for (const tag of value.tags) {
await this.client.sadd(`tag:${tag}`, key);
}
}
}
async invalidateByTag(tag) {
const keys = await this.client.smembers(`tag:${tag}`);
if (keys.length > 0) {
await this.client.del(...keys);
await this.client.del(`tag:${tag}`);
}
return keys.length;
}
async invalidatePattern(pattern) {
const keys = await this.client.keys(pattern);
if (keys.length > 0) {
await this.client.del(...keys);
}
return keys.length;
}
}
// middleware/cache-middleware.js
export const cacheMiddleware = (options = {}) => {
return async (req, res, next) => {
// Skip caching for non-GET requests
if (req.method !== 'GET') {
return next();
}
// Generate cache key
const cacheKey = generateCacheKey(req);
// Check cache
const cached = await cacheManager.get(cacheKey);
if (cached) {
res.set('X-Cache', 'HIT');
res.set('X-Cache-Key', cacheKey);
return res.json(cached);
}
// Store original send function
const originalSend = res.json;
res.json = function(data) {
res.json = originalSend;
// Cache successful responses only
if (res.statusCode === 200) {
cacheManager.set(cacheKey, data, options.ttl);
}
res.set('X-Cache', 'MISS');
res.set('X-Cache-Key', cacheKey);
return res.json(data);
};
next();
};
};
// Usage in Express routes
app.get('/api/products/:id',
cacheMiddleware({ ttl: 1800 }), // 30 minutes
async (req, res) => {
const product = await db.getProduct(req.params.id);
res.json(product);
}
);
```
---
### Example 2: CDN Integration with Cache Purging
**Scenario:** Global content delivery with CloudFlare integration
**Generated CDN Configuration:**
```javascript
// cdn-integration.js
class CDNManager {
constructor(config) {
this.zoneId = config.cloudflareZoneId;
this.apiToken = config.cloudflareApiToken;
this.baseUrl = 'https://api.cloudflare.com/client/v4';
}
// Set CDN cache headers
setCacheHeaders(res, options = {}) {
const {
maxAge = 3600,
sMaxAge = 86400,
staleWhileRevalidate = 60,
staleIfError = 3600,
mustRevalidate = false,
public = true
} = options;
// Browser cache
let cacheControl = public ? 'public' : 'private';
cacheControl += `, max-age=${maxAge}`;
// CDN cache (s-maxage)
cacheControl += `, s-maxage=${sMaxAge}`;
// Stale content serving
if (staleWhileRevalidate) {
cacheControl += `, stale-while-revalidate=${staleWhileRevalidate}`;
}
if (staleIfError) {
cacheControl += `, stale-if-error=${staleIfError}`;
}
if (mustRevalidate) {
cacheControl += ', must-revalidate';
}
res.set('Cache-Control', cacheControl);
// CloudFlare specific headers
res.set('CF-Cache-Tag', options.tags?.join(',') || 'default');
// Enable CDN caching for this response
res.set('CDN-Cache-Control', `max-age=${sMaxAge}`);
}
// Purge CDN cache by URL or tag
async purgeCache(options = {}) {
const { urls, tags, everything = false } = options;
let purgeBody = {};
if (everything) {
purgeBody.purge_everything = true;
} else if (tags) {
purgeBody.tags = tags;
} else if (urls) {
purgeBody.files = urls;
}
const response = await fetch(
`${this.baseUrl}/zones/${this.zoneId}/purge_cache`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(purgeBody)
}
);
return response.json();
}
}
// Usage in API endpoints
app.get('/api/content/:slug', async (req, res) => {
const content = await cms.getContent(req.params.slug);
// Set aggressive CDN caching for static content
cdnManager.setCacheHeaders(res, {
maxAge: 300, // 5 min browser cache
sMaxAge: 86400, // 24 hour CDN cache
tags: ['content', `content-${content.id}`]
});
res.json(content);
});
// Invalidate on content update
app.post('/api/content/:slug/update', async (req, res) => {
const content = await cms.updateContent(req.params.slug, req.body);
// Purge CDN cache
await cdnManager.purgeCache({
tags: [`content-${content.id}`]
});
// Invalidate Redis cache
await cacheManager.invalidateByTag(`content-${content.id}`);
res.json({ success: true });
});
```
---
### Example 3: Advanced Cache Warming and Preloading
**Scenario:** Critical data that must always be cached for performance
**Generated Cache Warming Strategy:**
```javascript
// cache-warming-service.js
class CacheWarmer {
constructor(cacheManager, dataSource) {
this.cache = cacheManager;
this.dataSource = dataSource;
this.warmingInterval = 5 * 60 * 1000; // 5 minutes
}
async warmCache() {
console.log('Starting cache warming...');
// Warm frequently accessed data
const criticalData = [
{ key: 'homepage:featured', fetch: () => this.dataSource.getFeaturedProducts() },
{ key: 'categories:all', fetch: () => this.dataSource.getAllCategories() },
{ key: 'config:site', fetch: () => this.dataSource.getSiteConfig() }
];
const warmingPromises = criticalData.map(async ({ key, fetch }) => {
try {
const data = await fetch();
await this.cache.set(key, data, 3600); // 1 hour TTL
return { key, status: 'warmed' };
} catch (error) {
return { key, status: 'failed', error: error.message };
}
});
const results = await Promise.allSettled(warmingPromises);
console.log('Cache warming complete:', results);
return results;
}
startPeriodicWarming() {
// Initial warming
this.warmCache();
// Periodic warming
setInterval(() => {
this.warmCache();
}, this.warmingInterval);
}
}
```
## Error Handling
### Error: Redis Connection Failed
**Symptoms:** Cache operations timeout or fail
**Cause:** Redis server unavailable or misconfigured
**Solution:**
```javascript
// Implement fallback to direct database access
if (!redis.isReady()) {
console.warn('Cache unavailable, falling back to database');
return await database.query(sql);
}
```
**Prevention:** Implement circuit breaker pattern and health checks
### Error: Cache Stampede
**Symptoms:** Multiple simultaneous cache misses cause database overload
**Cause:** Popular item expires, causing many requests to rebuild cache
**Solution:** Implement probabilistic early expiration or distributed locks
### Error: Stale Data Served
**Symptoms:** Users see outdated information
**Cause:** Cache TTL too long or invalidation not triggered
**Solution:** Implement event-based invalidation and reduce TTL values
## Configuration Options
### Option: `--ttl`
- **Purpose:** Set default time-to-live for cache entries
- **Values:** Seconds (integer)
- **Default:** 3600 (1 hour)
- **Example:** `/cache --ttl 7200`
### Option: `--strategy`
- **Purpose:** Choose caching pattern
- **Values:** `cache-aside`, `write-through`, `write-behind`
- **Default:** `cache-aside`
- **Example:** `/cache --strategy write-through`
### Option: `--cdn`
- **Purpose:** Specify CDN provider
- **Values:** `cloudflare`, `fastly`, `cloudfront`, `akamai`
- **Default:** `cloudflare`
- **Example:** `/cache --cdn fastly`
## Best Practices
**DO:**
- Use consistent cache key naming conventions
- Implement cache metrics and monitoring
- Set appropriate TTL values based on data volatility
- Use cache tags for grouped invalidation
- Implement graceful degradation on cache failure
**DON'T:**
- Cache user-specific sensitive data without isolation
- Use overly long TTLs for frequently changing data
- Forget to handle cache failures gracefully
- Cache large objects that exceed memory limits
💡 **TIPS:**
- Add jitter to TTL values to prevent synchronized expiration
- Use cache warming for critical data paths
- Monitor cache hit ratios (aim for >80%)
- Implement separate caches for different data types
## Related Commands
- `/api-rate-limiter` - Implement rate limiting with Redis
- `/api-response-validator` - Validate cached responses
- `/api-monitoring-dashboard` - Monitor cache performance
- `/api-load-tester` - Test cache effectiveness under load
## Performance Considerations
- **Cache hit ratio target:** >80% for static content, >60% for dynamic
- **Redis memory usage:** ~1KB per cached object + overhead
- **Network latency:** <5ms for Redis, <50ms for CDN edge
- **Typical improvements:** 10x-100x response time reduction
## Security Notes
⚠️ **Security Considerations:**
- Never cache authentication tokens or passwords
- Implement cache key signing to prevent injection
- Use separate cache instances for different security contexts
- Encrypt sensitive data before caching
- Implement proper access controls for cache management endpoints
## Troubleshooting
### Issue: Low cache hit ratio
**Solution:** Review cache key strategy and TTL values
### Issue: Memory pressure on Redis
**Solution:** Implement LRU eviction policy and reduce object sizes
### Issue: Cache invalidation not working
**Solution:** Verify tag associations and event triggers
### Getting Help
- Redis documentation: https://redis.io/documentation
- CDN best practices: https://web.dev/cache-control
- Cache pattern guide: https://docs.microsoft.com/azure/architecture/patterns/cache-aside
## Version History
- **v2.0.0** - Complete rewrite with multi-level caching and CDN integration
- **v1.0.0** - Initial Redis-only implementation
---
*Last updated: 2025-10-11*
*Quality score: 9.5/10*
*Tested with: Redis 7.0, CloudFlare, Fastly, AWS CloudFront*

97
plugin.lock.json Normal file
View File

@@ -0,0 +1,97 @@
{
"$schema": "internal://schemas/plugin.lock.v1.json",
"pluginId": "gh:jeremylongshore/claude-code-plugins-plus:plugins/api-development/api-cache-manager",
"normalized": {
"repo": null,
"ref": "refs/tags/v20251128.0",
"commit": "594477b051858b1c91d1777e3a06f09e543c650c",
"treeHash": "e6f9cd31a9d09f9cf30cbfb33d66a56143c450772271506a97b71be54d3c6537",
"generatedAt": "2025-11-28T10:18:05.361094Z",
"toolVersion": "publish_plugins.py@0.2.0"
},
"origin": {
"remote": "git@github.com:zhongweili/42plugin-data.git",
"branch": "master",
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
},
"manifest": {
"name": "api-cache-manager",
"description": "Implement caching strategies with Redis, CDN, and HTTP headers",
"version": "1.0.0"
},
"content": {
"files": [
{
"path": "README.md",
"sha256": "e48cdbebbf5b30e0135a9f94b924d6c210296bdf8d71ff736ecad67f5e281ce7"
},
{
"path": ".claude-plugin/plugin.json",
"sha256": "d2e2ee88084189b1a95ff0cb510c1dbe8a3cbd53585581f1846f6aafedcb18a5"
},
{
"path": "commands/implement-caching.md",
"sha256": "70f2c564d2fda84ffdeb639029db079d83bf4e0a3ea8de36c8badc2deb49b7a6"
},
{
"path": "skills/skill-adapter/references/examples.md",
"sha256": "922bbc3c4ebf38b76f515b5c1998ebde6bf902233e00e2c5a0e9176f975a7572"
},
{
"path": "skills/skill-adapter/references/best-practices.md",
"sha256": "c8f32b3566252f50daacd346d7045a1060c718ef5cfb07c55a0f2dec5f1fb39e"
},
{
"path": "skills/skill-adapter/references/README.md",
"sha256": "17234974d7e426481fa020c44c4330a1b014d3e089679e9128d4fb78fb50ac05"
},
{
"path": "skills/skill-adapter/scripts/helper-template.sh",
"sha256": "0881d5660a8a7045550d09ae0acc15642c24b70de6f08808120f47f86ccdf077"
},
{
"path": "skills/skill-adapter/scripts/validation.sh",
"sha256": "92551a29a7f512d2036e4f1fb46c2a3dc6bff0f7dde4a9f699533e446db48502"
},
{
"path": "skills/skill-adapter/scripts/README.md",
"sha256": "3972abf6b66fc5fd57e263f8b148447cc1ae0dab48676ace78e7b74d95c194e1"
},
{
"path": "skills/skill-adapter/assets/test-data.json",
"sha256": "ac17dca3d6e253a5f39f2a2f1b388e5146043756b05d9ce7ac53a0042eee139d"
},
{
"path": "skills/skill-adapter/assets/example_redis_config.conf",
"sha256": "6af78e0c762bc2755c0fbc09400d714b781f08d541abb2f4676766cc1bf23e1e"
},
{
"path": "skills/skill-adapter/assets/README.md",
"sha256": "85cbc2a136aa8b5251ae41306b3eea6eb49b40bb162931cdde6669f3f3df4b74"
},
{
"path": "skills/skill-adapter/assets/example_http_headers.txt",
"sha256": "79f93020e475f5dcd1c604798752c4c68bc15568744971d09399fae89a7fc15b"
},
{
"path": "skills/skill-adapter/assets/cache_invalidation_template.json",
"sha256": "98f07d7bc4064135328310e15708217070428e3380fa779b0cc8cb6ec58cef14"
},
{
"path": "skills/skill-adapter/assets/skill-schema.json",
"sha256": "f5639ba823a24c9ac4fb21444c0717b7aefde1a4993682897f5bf544f863c2cd"
},
{
"path": "skills/skill-adapter/assets/config-template.json",
"sha256": "0c2ba33d2d3c5ccb266c0848fc43caa68a2aa6a80ff315d4b378352711f83e1c"
}
],
"dirSha256": "e6f9cd31a9d09f9cf30cbfb33d66a56143c450772271506a97b71be54d3c6537"
},
"security": {
"scannedAt": null,
"scannerVersion": null,
"flags": []
}
}

View File

@@ -0,0 +1,7 @@
# Assets
Bundled resources for api-cache-manager skill
- [ ] cache_invalidation_template.json: JSON template for cache invalidation requests.
- [ ] example_redis_config.conf: Example Redis configuration file.
- [ ] example_http_headers.txt: Example HTTP headers for caching.

View File

@@ -0,0 +1,37 @@
{
"_comment": "Template for cache invalidation requests. Use this to build your request to invalidate cached data.",
"request_id": "unique_request_id_123",
"_comment": "A unique identifier for this invalidation request. Helps with tracking and auditing.",
"cache_type": "redis",
"_comment": "The type of cache to invalidate. Options: 'redis', 'cdn', 'http'.",
"target": "key",
"_comment": "Specifies what is being targeted for invalidation. Options: 'key', 'tag', 'all'.",
"key": "user:profile:12345",
"_comment": "The specific cache key to invalidate (if target is 'key').",
"tag": "user_profile",
"_comment": "The tag to invalidate (if target is 'tag'). All entries with this tag will be invalidated.",
"cdn_provider": "cloudflare",
"_comment": "If cache_type is 'cdn', specify the CDN provider. Options: 'cloudflare', 'akamai', 'fastly'.",
"cloudflare_zone_id": "your_cloudflare_zone_id",
"_comment": "If cache_type is 'cdn' and cdn_provider is 'cloudflare', specify the Cloudflare zone ID.",
"akamai_client_token": "your_akamai_client_token",
"_comment": "If cache_type is 'cdn' and cdn_provider is 'akamai', specify the Akamai Client Token.",
"akamai_client_secret": "your_akamai_client_secret",
"_comment": "If cache_type is 'cdn' and cdn_provider is 'akamai', specify the Akamai Client Secret.",
"akamai_access_token": "your_akamai_access_token",
"_comment": "If cache_type is 'cdn' and cdn_provider is 'akamai', specify the Akamai Access Token.",
"fastly_service_id": "your_fastly_service_id",
"_comment": "If cache_type is 'cdn' and cdn_provider is 'fastly', specify the Fastly Service ID.",
"fastly_api_key": "your_fastly_api_key",
"_comment": "If cache_type is 'cdn' and cdn_provider is 'fastly', specify the Fastly API Key.",
"http_header": "Cache-Control",
"_comment": "If cache_type is 'http', specify the HTTP header to modify. Typically 'Cache-Control'.",
"http_header_value": "no-cache, no-store, must-revalidate",
"_comment": "If cache_type is 'http', specify the new value for the HTTP header. Example: 'no-cache, no-store, must-revalidate'.",
"invalidate_all": false,
"_comment": "If true, invalidates all entries in the specified cache_type. Use with caution!",
"timestamp": "2024-01-26T12:00:00Z",
"_comment": "Timestamp of the invalidation request. Useful for auditing and debugging.",
"user": "admin_user",
"_comment": "User who initiated the invalidation request."
}

View File

@@ -0,0 +1,32 @@
{
"skill": {
"name": "skill-name",
"version": "1.0.0",
"enabled": true,
"settings": {
"verbose": false,
"autoActivate": true,
"toolRestrictions": true
}
},
"triggers": {
"keywords": [
"example-trigger-1",
"example-trigger-2"
],
"patterns": []
},
"tools": {
"allowed": [
"Read",
"Grep",
"Bash"
],
"restricted": []
},
"metadata": {
"author": "Plugin Author",
"category": "general",
"tags": []
}
}

View File

@@ -0,0 +1,129 @@
# Example HTTP Headers for API Caching
This document provides example HTTP headers that you can use to implement caching strategies for your API. These headers can be configured on your server to instruct browsers, CDNs, and other caching proxies on how to cache your API responses.
## Cache-Control
The `Cache-Control` header is the primary mechanism for controlling caching behavior. It allows you to specify various directives related to caching.
### Common Directives
* **`public`**: Indicates that the response can be cached by any cache (e.g., browser, CDN, proxy).
* **`private`**: Indicates that the response can only be cached by the user's browser and not by shared caches.
* **`max-age=<seconds>`**: Specifies the maximum amount of time (in seconds) that a response is considered fresh. After this time, the cache must revalidate the response with the origin server. **[Insert your desired cache duration in seconds here]**
* **`s-maxage=<seconds>`**: Similar to `max-age`, but specifically for shared caches like CDNs. This overrides `max-age` for shared caches. **[Insert your desired CDN cache duration in seconds here]**
* **`no-cache`**: Forces caches to revalidate the response with the origin server before using it. The cache can still store the response, but it must always check for updates.
* **`no-store`**: Indicates that the response should not be cached at all.
* **`must-revalidate`**: Instructs caches to strictly adhere to the freshness information provided in the response. If a cached response is stale, the cache must revalidate it with the origin server before using it.
* **`proxy-revalidate`**: Similar to `must-revalidate`, but specifically for proxy caches.
### Example Cache-Control Headers
* **For public caching with a 1 hour (3600 seconds) TTL:**
```
Cache-Control: public, max-age=3600
```
* **For private caching with a 5 minute (300 seconds) TTL:**
```
Cache-Control: private, max-age=300
```
* **For CDN caching with a 1 day (86400 seconds) TTL and browser caching with 1 hour:**
```
Cache-Control: public, max-age=3600, s-maxage=86400
```
* **To force revalidation:**
```
Cache-Control: no-cache
```
* **To prevent caching:**
```
Cache-Control: no-store
```
## Expires
The `Expires` header specifies an absolute date/time after which the response is considered stale. While still supported, `Cache-Control` is generally preferred as it offers more flexibility.
### Example Expires Header
* **Expires one week from now:**
```
Expires: [Insert calculated date/time string for one week from now in HTTP date format (e.g., "Tue, 15 Nov 2024 08:12:31 GMT")]
```
## ETag
The `ETag` header provides a unique identifier for a specific version of a resource. The server generates this value, and the client can use it in subsequent requests with the `If-None-Match` header to perform conditional requests.
### Usage
1. The server returns an `ETag` header with the initial response. **[Insert example ETag value here]**
2. The client stores the `ETag` value.
3. When the client needs to request the same resource again, it includes the `If-None-Match` header with the stored `ETag` value.
4. If the resource has not changed since the client last requested it, the server returns a `304 Not Modified` response. If the resource has changed, the server returns the new resource with a new `ETag` value.
### Example ETag Header
```
ETag: "[Insert generated ETag value here]"
```
## Last-Modified
The `Last-Modified` header indicates the date and time the resource was last modified on the server. Clients can use this information with the `If-Modified-Since` header to perform conditional requests.
### Usage
1. The server includes the `Last-Modified` header with the initial response. **[Insert Last-Modified date/time string here]**
2. The client stores the `Last-Modified` value.
3. When the client needs to request the same resource again, it includes the `If-Modified-Since` header with the stored `Last-Modified` value.
4. If the resource has not been modified since the client last requested it, the server returns a `304 Not Modified` response. If the resource has been modified, the server returns the new resource with an updated `Last-Modified` value.
### Example Last-Modified Header
```
Last-Modified: [Insert date/time string in HTTP date format (e.g., "Mon, 14 Nov 2024 10:00:00 GMT")]
```
## Vary
The `Vary` header specifies the request headers that the server uses to determine which version of a resource to serve. This is important when the server returns different responses based on the client's request headers (e.g., language, user-agent).
### Example Vary Header
* **Vary based on the `Accept-Language` header:**
```
Vary: Accept-Language
```
* **Vary based on the `User-Agent` and `Accept-Encoding` headers:**
```
Vary: User-Agent, Accept-Encoding
```
* **Vary on everything (use with caution as it can reduce cache effectiveness):**
```
Vary: *
```
## Practical Considerations
* **Balancing Freshness and Validation:** Carefully consider the `max-age` and `s-maxage` values to strike a balance between serving cached content and ensuring that clients receive up-to-date information.
* **CDN Configuration:** Configure your CDN to respect the caching headers set by your origin server. Refer to your CDN provider's documentation for specific instructions.
* **Testing:** Thoroughly test your caching configuration to ensure that it is working as expected and that clients are receiving the correct responses. Use browser developer tools or command-line tools like `curl` to inspect the HTTP headers.
* **API Design:** Design your API to be cache-friendly. For example, use resource-based URLs and provide appropriate `ETag` or `Last-Modified` headers.
* **Invalidation:** Implement a strategy for invalidating cached content when the underlying data changes. This may involve purging the CDN cache or updating the `Cache-Control` headers.
* **Dynamic Content:** For dynamic content that cannot be cached, use the `Cache-Control: no-store` header.

View File

@@ -0,0 +1,101 @@
# Example Redis Configuration File
# This file provides a starting point for configuring Redis for use with the API Cache Manager plugin.
# Adjust these settings to match your specific Redis deployment and performance requirements.
# --- Basic Configuration ---
# Bind to all interfaces or specify an IP address (e.g., 127.0.0.1) for local access only.
# bind 127.0.0.1 -::1
bind 0.0.0.0
# Listen on the default Redis port. Change if necessary.
port 6379
# TCP keepalive.
#
# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence
# of communication. This is useful for two reasons:
#
# 1) Detect dead peers.
# 2) Take advantage of the TCP keepalive period to half close idle
# connections if the server wants to reduce resources usage.
#
# On Linux, the default keepalive settings are to send probes every
# 75 seconds, with 9 failed probes before declaring the client dead.
# This means that a broken connection is only discovered after 11 minutes
# (75*9).
#
# To make connection alive detection more aggressive on Linux, it is
# recommended to set the following TCP keepalive settings:
#
# tcp-keepalive 60
tcp-keepalive 300
# --- Memory Management ---
# Set the maximum memory Redis will use. Adjust this based on your available RAM.
# A good starting point is to allocate around half of your system's RAM to Redis.
# Ensure you have enough memory for both Redis and your application.
maxmemory 2gb
# Eviction policy: how Redis will evict keys when it reaches maxmemory.
# Common policies:
# - volatile-lru: Evict keys with an expire set using an LRU algorithm.
# - allkeys-lru: Evict any key using an LRU algorithm.
# - volatile-ttl: Evict keys with an expire set, with the shortest remaining TTL.
# - noeviction: Don't evict. Return an error when memory is full.
maxmemory-policy allkeys-lru
# --- Persistence ---
# Redis offers different persistence options:
# - RDB (Snapshotting): Saves the dataset to disk periodically. Good for backups.
# - AOF (Append Only File): Logs every write operation. Provides better durability.
# - Disable Persistence: Redis will only exist in memory. Data is lost on shutdown.
# RDB Snapshotting configuration
save 900 1 # Save the DB if 1 key changed in 900 seconds
save 300 10 # Save the DB if 10 keys changed in 300 seconds
save 60 10000 # Save the DB if 10000 keys changed in 60 seconds
# AOF configuration (more durable, but can be slower)
# appendonly yes
# appendfsync everysec # Recommended for most use cases
# appendfsync always # Slowest, but safest
# appendfsync no # Fastest, but least safe (OS decides when to flush)
# --- Security ---
# Require a password for accessing Redis. Strongly recommended for production.
# Replace 'YOUR_REDIS_PASSWORD' with a strong, unique password.
# requirepass YOUR_REDIS_PASSWORD
# Rename potentially dangerous commands. This is an optional security measure.
# rename-command FLUSHALL ""
# rename-command FLUSHDB ""
# rename-command CONFIG ""
# --- Advanced Configuration ---
# Number of databases. The default is 16.
# databases 16
# The idle time after which a client connection will be closed.
# If set to 0, the connection will never be closed.
# timeout 300
# --- Cluster Configuration (if applicable) ---
# If you are using Redis Cluster, configure the following:
# cluster-enabled yes
# cluster-config-file nodes.conf
# cluster-node-timeout 15000
# --- Logging ---
# Specify the log file. Leave commented to log to stdout.
# logfile /var/log/redis/redis-server.log
# --- Important Notes ---
# - Regularly review and adjust these settings based on your application's needs and performance monitoring.
# - Monitor Redis memory usage and adjust 'maxmemory' accordingly.
# - Consider using Redis Sentinel or Redis Cluster for high availability.
# - Secure your Redis instance properly, especially if it's exposed to the internet.

View File

@@ -0,0 +1,28 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Claude Skill Configuration",
"type": "object",
"required": ["name", "description"],
"properties": {
"name": {
"type": "string",
"pattern": "^[a-z0-9-]+$",
"maxLength": 64,
"description": "Skill identifier (lowercase, hyphens only)"
},
"description": {
"type": "string",
"maxLength": 1024,
"description": "What the skill does and when to use it"
},
"allowed-tools": {
"type": "string",
"description": "Comma-separated list of allowed tools"
},
"version": {
"type": "string",
"pattern": "^\\d+\\.\\d+\\.\\d+$",
"description": "Semantic version (x.y.z)"
}
}
}

View File

@@ -0,0 +1,27 @@
{
"testCases": [
{
"name": "Basic activation test",
"input": "trigger phrase example",
"expected": {
"activated": true,
"toolsUsed": ["Read", "Grep"],
"success": true
}
},
{
"name": "Complex workflow test",
"input": "multi-step trigger example",
"expected": {
"activated": true,
"steps": 3,
"toolsUsed": ["Read", "Write", "Bash"],
"success": true
}
}
],
"fixtures": {
"sampleInput": "example data",
"expectedOutput": "processed result"
}
}

View File

@@ -0,0 +1,7 @@
# References
Bundled resources for api-cache-manager skill
- [ ] redis_config.md: Documentation on configuring Redis for caching, including connection parameters and best practices.
- [ ] http_cache_headers.md: Explanation of HTTP caching headers and how to use them effectively.
- [ ] cdn_integration.md: Guide on integrating the API cache with a CDN for improved performance.

View File

@@ -0,0 +1,69 @@
# Skill Best Practices
Guidelines for optimal skill usage and development.
## For Users
### Activation Best Practices
1. **Use Clear Trigger Phrases**
- Match phrases from skill description
- Be specific about intent
- Provide necessary context
2. **Provide Sufficient Context**
- Include relevant file paths
- Specify scope of analysis
- Mention any constraints
3. **Understand Tool Permissions**
- Check allowed-tools in frontmatter
- Know what the skill can/cannot do
- Request appropriate actions
### Workflow Optimization
- Start with simple requests
- Build up to complex workflows
- Verify each step before proceeding
- Use skill consistently for related tasks
## For Developers
### Skill Development Guidelines
1. **Clear Descriptions**
- Include explicit trigger phrases
- Document all capabilities
- Specify limitations
2. **Proper Tool Permissions**
- Use minimal necessary tools
- Document security implications
- Test with restricted tools
3. **Comprehensive Documentation**
- Provide usage examples
- Document common pitfalls
- Include troubleshooting guide
### Maintenance
- Keep version updated
- Test after tool updates
- Monitor user feedback
- Iterate on descriptions
## Performance Tips
- Scope skills to specific domains
- Avoid overlapping trigger phrases
- Keep descriptions under 1024 chars
- Test activation reliability
## Security Considerations
- Never include secrets in skill files
- Validate all inputs
- Use read-only tools when possible
- Document security requirements

View File

@@ -0,0 +1,70 @@
# Skill Usage Examples
This document provides practical examples of how to use this skill effectively.
## Basic Usage
### Example 1: Simple Activation
**User Request:**
```
[Describe trigger phrase here]
```
**Skill Response:**
1. Analyzes the request
2. Performs the required action
3. Returns results
### Example 2: Complex Workflow
**User Request:**
```
[Describe complex scenario]
```
**Workflow:**
1. Step 1: Initial analysis
2. Step 2: Data processing
3. Step 3: Result generation
4. Step 4: Validation
## Advanced Patterns
### Pattern 1: Chaining Operations
Combine this skill with other tools:
```
Step 1: Use this skill for [purpose]
Step 2: Chain with [other tool]
Step 3: Finalize with [action]
```
### Pattern 2: Error Handling
If issues occur:
- Check trigger phrase matches
- Verify context is available
- Review allowed-tools permissions
## Tips & Best Practices
- ✅ Be specific with trigger phrases
- ✅ Provide necessary context
- ✅ Check tool permissions match needs
- ❌ Avoid vague requests
- ❌ Don't mix unrelated tasks
## Common Issues
**Issue:** Skill doesn't activate
**Solution:** Use exact trigger phrases from description
**Issue:** Unexpected results
**Solution:** Check input format and context
## See Also
- Main SKILL.md for full documentation
- scripts/ for automation helpers
- assets/ for configuration examples

View File

@@ -0,0 +1,7 @@
# Scripts
Bundled resources for api-cache-manager skill
- [ ] clear_cache.sh: Script to clear the API cache based on different strategies (Redis, HTTP headers).
- [ ] warm_cache.py: Python script to pre-populate the cache with frequently accessed data.
- [ ] cache_stats.sh: Script to retrieve and display cache statistics (hit rate, size, etc.).

View File

@@ -0,0 +1,42 @@
#!/bin/bash
# Helper script template for skill automation
# Customize this for your skill's specific needs
set -e
function show_usage() {
echo "Usage: $0 [options]"
echo ""
echo "Options:"
echo " -h, --help Show this help message"
echo " -v, --verbose Enable verbose output"
echo ""
}
# Parse arguments
VERBOSE=false
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_usage
exit 0
;;
-v|--verbose)
VERBOSE=true
shift
;;
*)
echo "Unknown option: $1"
show_usage
exit 1
;;
esac
done
# Your skill logic here
if [ "$VERBOSE" = true ]; then
echo "Running skill automation..."
fi
echo "✅ Complete"

View File

@@ -0,0 +1,32 @@
#!/bin/bash
# Skill validation helper
# Validates skill activation and functionality
set -e
echo "🔍 Validating skill..."
# Check if SKILL.md exists
if [ ! -f "../SKILL.md" ]; then
echo "❌ Error: SKILL.md not found"
exit 1
fi
# Validate frontmatter
if ! grep -q "^---$" "../SKILL.md"; then
echo "❌ Error: No frontmatter found"
exit 1
fi
# Check required fields
if ! grep -q "^name:" "../SKILL.md"; then
echo "❌ Error: Missing 'name' field"
exit 1
fi
if ! grep -q "^description:" "../SKILL.md"; then
echo "❌ Error: Missing 'description' field"
exit 1
fi
echo "✅ Skill validation passed"