@wipal/agent-team 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/rules/common/general-rules.md +141 -0
- package/.claude/rules/lessons/lessons.md +91 -0
- package/.claude/rules/role-rules/dev-fe-rules.md +146 -0
- package/.claude/rules/role-rules/sa-rules.md +226 -0
- package/.claude/skills/SKILL-INDEX.md +299 -0
- package/.claude/skills/community/security-validator/SKILL.md +392 -0
- package/.claude/skills/core/agent-creation/SKILL.md +338 -0
- package/.claude/skills/core/code-review/SKILL.md +154 -0
- package/.claude/skills/core/git-automation/SKILL.md +93 -0
- package/.claude/skills/core/retrospect-work/SKILL.md +172 -0
- package/.claude/skills/domain/architecture/adr-writing/SKILL.md +254 -0
- package/.claude/skills/domain/architecture/adr-writing/references/adr-best-practices.md +257 -0
- package/.claude/skills/domain/architecture/adr-writing/references/adr-examples.md +246 -0
- package/.claude/skills/domain/architecture/adr-writing/references/adr-template.md +160 -0
- package/.claude/skills/domain/architecture/architecture-patterns/SKILL.md +316 -0
- package/.claude/skills/domain/architecture/architecture-patterns/references/event-driven.md +393 -0
- package/.claude/skills/domain/architecture/architecture-patterns/references/microservices.md +315 -0
- package/.claude/skills/domain/architecture/architecture-patterns/references/monolith.md +321 -0
- package/.claude/skills/domain/architecture/architecture-patterns/references/serverless.md +457 -0
- package/.claude/skills/domain/architecture/performance-engineering/SKILL.md +227 -0
- package/.claude/skills/domain/architecture/performance-engineering/references/benchmarking.md +336 -0
- package/.claude/skills/domain/architecture/performance-engineering/references/caching-strategies.md +284 -0
- package/.claude/skills/domain/architecture/performance-engineering/references/optimization.md +298 -0
- package/.claude/skills/domain/architecture/security-architecture/SKILL.md +206 -0
- package/.claude/skills/domain/architecture/security-architecture/references/auth-patterns.md +209 -0
- package/.claude/skills/domain/architecture/security-architecture/references/compliance.md +246 -0
- package/.claude/skills/domain/architecture/security-architecture/references/threat-modeling.md +219 -0
- package/.claude/skills/domain/architecture/system-design/SKILL.md +227 -0
- package/.claude/skills/domain/architecture/system-design/references/distributed-systems.md +231 -0
- package/.claude/skills/domain/architecture/system-design/references/resilience.md +344 -0
- package/.claude/skills/domain/architecture/system-design/references/scalability.md +303 -0
- package/.claude/skills/domain/architecture/tech-selection/SKILL.md +192 -0
- package/.claude/skills/domain/architecture/tech-selection/references/build-vs-buy.md +258 -0
- package/.claude/skills/domain/architecture/tech-selection/references/evaluation-framework.md +203 -0
- package/.claude/skills/domain/architecture/tech-selection/references/tech-radar.md +257 -0
- package/.claude/skills/domain/backend/api-design/SKILL.md +121 -0
- package/.claude/skills/domain/backend/database-design/SKILL.md +156 -0
- package/.claude/skills/domain/backend/performance-be/SKILL.md +210 -0
- package/.claude/skills/domain/backend/security/SKILL.md +138 -0
- package/.claude/skills/domain/backend/testing-be/SKILL.md +203 -0
- package/.claude/skills/domain/devops/ci-cd/SKILL.md +188 -0
- package/.claude/skills/domain/devops/containerization/SKILL.md +177 -0
- package/.claude/skills/domain/devops/deployment/SKILL.md +198 -0
- package/.claude/skills/domain/devops/infrastructure-as-code/SKILL.md +178 -0
- package/.claude/skills/domain/devops/monitoring/SKILL.md +163 -0
- package/.claude/skills/domain/frontend/accessibility/SKILL.md +179 -0
- package/.claude/skills/domain/frontend/frontend-design/SKILL.md +138 -0
- package/.claude/skills/domain/frontend/performance-fe/SKILL.md +195 -0
- package/.claude/skills/domain/frontend/state-management/SKILL.md +190 -0
- package/.claude/skills/domain/frontend/testing-fe/SKILL.md +193 -0
- package/.claude/skills/domain/product/requirements-gathering/SKILL.md +136 -0
- package/.claude/skills/domain/product/roadmap-planning/SKILL.md +169 -0
- package/.claude/skills/domain/product/sprint-planning/SKILL.md +151 -0
- package/.claude/skills/domain/product/stakeholder-communication/SKILL.md +162 -0
- package/.claude/skills/domain/product/user-stories/SKILL.md +141 -0
- package/.claude/skills/domain/quality/bug-reporting/SKILL.md +150 -0
- package/.claude/skills/domain/quality/regression-testing/SKILL.md +178 -0
- package/.claude/skills/domain/quality/test-automation/SKILL.md +185 -0
- package/.claude/skills/domain/quality/test-planning/SKILL.md +177 -0
- package/.claude/skills/leadership/code-review-advanced/SKILL.md +167 -0
- package/.claude/skills/leadership/mentoring/SKILL.md +151 -0
- package/.claude/skills/leadership/technical-debt/SKILL.md +166 -0
- package/.claude/skills/leadership/technical-decision/SKILL.md +160 -0
- package/.claude/skills/security-reports/.gitkeep +0 -0
- package/.claude/skills/skills-registry.yaml +441 -0
- package/README.md +232 -0
- package/bin/agent-team.js +107 -0
- package/package.json +51 -0
- package/src/commands/add.js +227 -0
- package/src/commands/init.js +136 -0
- package/src/commands/list.js +66 -0
- package/src/commands/remove.js +71 -0
- package/src/commands/switch.js +53 -0
- package/src/index.js +11 -0
- package/src/interactive/prompts.js +153 -0
- package/src/server/api/agents.js +150 -0
- package/src/server/api/roles.js +97 -0
- package/src/server/api/skills.js +79 -0
- package/src/server/index.js +78 -0
- package/src/ui/agents.html +174 -0
- package/src/ui/css/styles.css +470 -0
- package/src/ui/index.html +107 -0
- package/src/ui/roles.html +371 -0
- package/src/ui/skills.html +332 -0
- package/src/utils/file-utils.js +193 -0
- package/src/utils/skill-resolver.js +594 -0
- package/src/utils/skill-scanner.js +154 -0
- package/templates/CLAUDE.md.tmpl +42 -0
- package/templates/knowledge.md.tmpl +31 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# Benchmarking & Load Testing
|
|
2
|
+
|
|
3
|
+
## Load Testing Types
|
|
4
|
+
|
|
5
|
+
### 1. Load Testing
|
|
6
|
+
```
|
|
7
|
+
Purpose: Verify system handles expected load
|
|
8
|
+
|
|
9
|
+
Configuration:
|
|
10
|
+
- Expected concurrent users
|
|
11
|
+
- Expected request rate
|
|
12
|
+
- Typical usage patterns
|
|
13
|
+
|
|
14
|
+
Success Criteria:
|
|
15
|
+
- Response time within SLA
|
|
16
|
+
- Error rate below threshold
|
|
17
|
+
- Resource utilization acceptable
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 2. Stress Testing
|
|
21
|
+
```
|
|
22
|
+
Purpose: Find system breaking point
|
|
23
|
+
|
|
24
|
+
Configuration:
|
|
25
|
+
- Gradually increase load beyond capacity
|
|
26
|
+
- Monitor for degradation
|
|
27
|
+
- Identify failure mode
|
|
28
|
+
|
|
29
|
+
Success Criteria:
|
|
30
|
+
- Understand system limits
|
|
31
|
+
- Identify bottleneck
|
|
32
|
+
- Graceful degradation behavior
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 3. Spike Testing
|
|
36
|
+
```
|
|
37
|
+
Purpose: Test sudden traffic increase
|
|
38
|
+
|
|
39
|
+
Configuration:
|
|
40
|
+
- Baseline load
|
|
41
|
+
- Sudden spike (10x traffic)
|
|
42
|
+
- Return to baseline
|
|
43
|
+
|
|
44
|
+
Success Criteria:
|
|
45
|
+
- Auto-scaling triggers
|
|
46
|
+
- No cascade failures
|
|
47
|
+
- Recovery to normal
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 4. Soak Testing
|
|
51
|
+
```
|
|
52
|
+
Purpose: Find issues over time
|
|
53
|
+
|
|
54
|
+
Configuration:
|
|
55
|
+
- Sustained load (hours/days)
|
|
56
|
+
- Monitor for degradation
|
|
57
|
+
- Look for memory leaks
|
|
58
|
+
|
|
59
|
+
Success Criteria:
|
|
60
|
+
- Stable performance over time
|
|
61
|
+
- No memory growth
|
|
62
|
+
- No resource exhaustion
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Load Testing Tools
|
|
66
|
+
|
|
67
|
+
### k6 (Recommended)
|
|
68
|
+
```javascript
|
|
69
|
+
// script.js
|
|
70
|
+
import http from 'k6/http';
|
|
71
|
+
import { check, sleep } from 'k6';
|
|
72
|
+
|
|
73
|
+
export const options = {
|
|
74
|
+
stages: [
|
|
75
|
+
{ duration: '30s', target: 20 }, // Ramp up
|
|
76
|
+
{ duration: '1m', target: 20 }, // Stay
|
|
77
|
+
{ duration: '30s', target: 100 }, // Spike
|
|
78
|
+
{ duration: '1m', target: 100 }, // Stay
|
|
79
|
+
{ duration: '30s', target: 0 }, // Ramp down
|
|
80
|
+
],
|
|
81
|
+
thresholds: {
|
|
82
|
+
http_req_duration: ['p(95)<500'], // 95% under 500ms
|
|
83
|
+
http_req_failed: ['rate<0.01'], // <1% errors
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export default function () {
|
|
88
|
+
const res = http.get('https://api.example.com/users');
|
|
89
|
+
|
|
90
|
+
check(res, {
|
|
91
|
+
'status is 200': (r) => r.status === 200,
|
|
92
|
+
'response time OK': (r) => r.timings.duration < 500,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
sleep(1);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Run: k6 run script.js
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Locust (Python)
|
|
102
|
+
```python
|
|
103
|
+
from locust import HttpUser, task, between
|
|
104
|
+
|
|
105
|
+
class WebsiteUser(HttpUser):
|
|
106
|
+
wait_time = between(1, 5)
|
|
107
|
+
|
|
108
|
+
@task
|
|
109
|
+
def get_users(self):
|
|
110
|
+
self.client.get("/users")
|
|
111
|
+
|
|
112
|
+
@task(3) # 3x more frequent
|
|
113
|
+
def get_products(self):
|
|
114
|
+
self.client.get("/products")
|
|
115
|
+
|
|
116
|
+
# Run: locust -f locustfile.py
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Artillery (Node.js)
|
|
120
|
+
```yaml
|
|
121
|
+
config:
|
|
122
|
+
target: 'https://api.example.com'
|
|
123
|
+
phases:
|
|
124
|
+
- duration: 60
|
|
125
|
+
arrivalRate: 10
|
|
126
|
+
name: Warm up
|
|
127
|
+
- duration: 120
|
|
128
|
+
arrivalRate: 50
|
|
129
|
+
name: Sustained load
|
|
130
|
+
|
|
131
|
+
scenarios:
|
|
132
|
+
- flow:
|
|
133
|
+
- get:
|
|
134
|
+
url: "/users"
|
|
135
|
+
- think: 2
|
|
136
|
+
- get:
|
|
137
|
+
url: "/products"
|
|
138
|
+
|
|
139
|
+
# Run: artillery run config.yml
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Performance Metrics
|
|
143
|
+
|
|
144
|
+
### Key Metrics to Track
|
|
145
|
+
```
|
|
146
|
+
1. Throughput
|
|
147
|
+
- Requests per second (RPS)
|
|
148
|
+
- Transactions per second (TPS)
|
|
149
|
+
- Messages per second
|
|
150
|
+
|
|
151
|
+
2. Latency
|
|
152
|
+
- p50 (median)
|
|
153
|
+
- p90
|
|
154
|
+
- p95
|
|
155
|
+
- p99
|
|
156
|
+
- p99.9
|
|
157
|
+
|
|
158
|
+
3. Error Rate
|
|
159
|
+
- HTTP 4xx errors
|
|
160
|
+
- HTTP 5xx errors
|
|
161
|
+
- Timeouts
|
|
162
|
+
- Connection errors
|
|
163
|
+
|
|
164
|
+
4. Resource Utilization
|
|
165
|
+
- CPU usage
|
|
166
|
+
- Memory usage
|
|
167
|
+
- Disk I/O
|
|
168
|
+
- Network I/O
|
|
169
|
+
- Database connections
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Interpreting Results
|
|
173
|
+
```
|
|
174
|
+
Good Results:
|
|
175
|
+
- Flat latency as load increases (until saturation)
|
|
176
|
+
- Linear throughput increase with load
|
|
177
|
+
- Error rate < 0.1%
|
|
178
|
+
- Resource utilization < 80%
|
|
179
|
+
|
|
180
|
+
Warning Signs:
|
|
181
|
+
- Latency increases exponentially
|
|
182
|
+
- Throughput plateaus while latency increases
|
|
183
|
+
- Error rate spikes
|
|
184
|
+
- Resource exhaustion
|
|
185
|
+
|
|
186
|
+
Bottleneck Indicators:
|
|
187
|
+
- High CPU, low throughput → Algorithm optimization
|
|
188
|
+
- High memory → Memory leak, inefficient data structures
|
|
189
|
+
- High I/O wait → Disk bottleneck, database queries
|
|
190
|
+
- High network → Bandwidth limitation
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Test Environment
|
|
194
|
+
|
|
195
|
+
### Production-Like Environment
|
|
196
|
+
```
|
|
197
|
+
Requirements:
|
|
198
|
+
- Same hardware specifications
|
|
199
|
+
- Same software versions
|
|
200
|
+
- Same configuration
|
|
201
|
+
- Same data volume (or representative subset)
|
|
202
|
+
- Same network conditions
|
|
203
|
+
|
|
204
|
+
Database:
|
|
205
|
+
- Use production-like data distribution
|
|
206
|
+
- Same indexes
|
|
207
|
+
- Same query patterns
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Test Data
|
|
211
|
+
```
|
|
212
|
+
Options:
|
|
213
|
+
1. Production data (anonymized)
|
|
214
|
+
2. Synthetic data (realistic distribution)
|
|
215
|
+
3. Subset of production
|
|
216
|
+
|
|
217
|
+
Considerations:
|
|
218
|
+
- Data volume affects performance
|
|
219
|
+
- Data distribution affects query plans
|
|
220
|
+
- Sensitive data handling
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Benchmarking Best Practices
|
|
224
|
+
|
|
225
|
+
### Before Testing
|
|
226
|
+
```
|
|
227
|
+
1. Define clear objectives
|
|
228
|
+
- What are you testing?
|
|
229
|
+
- What's the success criteria?
|
|
230
|
+
|
|
231
|
+
2. Establish baseline
|
|
232
|
+
- Run tests on known-good configuration
|
|
233
|
+
- Document baseline metrics
|
|
234
|
+
|
|
235
|
+
3. Prepare environment
|
|
236
|
+
- Clean state
|
|
237
|
+
- No other load
|
|
238
|
+
- Monitoring ready
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### During Testing
|
|
242
|
+
```
|
|
243
|
+
1. Monitor all layers
|
|
244
|
+
- Application logs
|
|
245
|
+
- Database metrics
|
|
246
|
+
- Infrastructure metrics
|
|
247
|
+
- Network metrics
|
|
248
|
+
|
|
249
|
+
2. Capture data
|
|
250
|
+
- Response times
|
|
251
|
+
- Error logs
|
|
252
|
+
- Resource utilization
|
|
253
|
+
- GC pauses (if applicable)
|
|
254
|
+
|
|
255
|
+
3. Note observations
|
|
256
|
+
- When did degradation start?
|
|
257
|
+
- What failed first?
|
|
258
|
+
- Error patterns?
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### After Testing
|
|
262
|
+
```
|
|
263
|
+
1. Analyze results
|
|
264
|
+
- Compare to baseline
|
|
265
|
+
- Identify bottlenecks
|
|
266
|
+
- Document findings
|
|
267
|
+
|
|
268
|
+
2. Report
|
|
269
|
+
- Executive summary
|
|
270
|
+
- Key metrics
|
|
271
|
+
- Recommendations
|
|
272
|
+
|
|
273
|
+
3. Action items
|
|
274
|
+
- Prioritize fixes
|
|
275
|
+
- Estimate effort
|
|
276
|
+
- Plan retest
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Continuous Performance Testing
|
|
280
|
+
|
|
281
|
+
### CI/CD Integration
|
|
282
|
+
```yaml
|
|
283
|
+
# .github/workflows/performance.yml
|
|
284
|
+
name: Performance Tests
|
|
285
|
+
|
|
286
|
+
on:
|
|
287
|
+
schedule:
|
|
288
|
+
- cron: '0 2 * * *' # Daily at 2am
|
|
289
|
+
workflow_dispatch:
|
|
290
|
+
|
|
291
|
+
jobs:
|
|
292
|
+
load-test:
|
|
293
|
+
runs-on: ubuntu-latest
|
|
294
|
+
steps:
|
|
295
|
+
- uses: actions/checkout@v3
|
|
296
|
+
|
|
297
|
+
- name: Run k6
|
|
298
|
+
uses: grafana/k6-action@v0.3.0
|
|
299
|
+
with:
|
|
300
|
+
filename: tests/load/basic.js
|
|
301
|
+
env:
|
|
302
|
+
K6_CLOUD_TOKEN: ${{ secrets.K6_TOKEN }}
|
|
303
|
+
|
|
304
|
+
- name: Check thresholds
|
|
305
|
+
run: |
|
|
306
|
+
# Fail if p95 > 500ms
|
|
307
|
+
if [ $(cat results.json | jq '.metrics.http_req_duration.values["p(95)"]') -gt 500 ]; then
|
|
308
|
+
echo "Performance regression detected"
|
|
309
|
+
exit 1
|
|
310
|
+
fi
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Performance Budgets
|
|
314
|
+
```
|
|
315
|
+
Define and enforce budgets:
|
|
316
|
+
|
|
317
|
+
Frontend:
|
|
318
|
+
- First Contentful Paint: < 1.5s
|
|
319
|
+
- Largest Contentful Paint: < 2.5s
|
|
320
|
+
- Time to Interactive: < 3.5s
|
|
321
|
+
- Cumulative Layout Shift: < 0.1
|
|
322
|
+
|
|
323
|
+
API:
|
|
324
|
+
- p95 latency: < 200ms
|
|
325
|
+
- p99 latency: < 500ms
|
|
326
|
+
- Error rate: < 0.1%
|
|
327
|
+
|
|
328
|
+
Database:
|
|
329
|
+
- Query time p95: < 50ms
|
|
330
|
+
- Connection pool usage: < 80%
|
|
331
|
+
|
|
332
|
+
Enforcement:
|
|
333
|
+
- Build fails if budget exceeded
|
|
334
|
+
- PR checks for performance
|
|
335
|
+
- Automated alerts
|
|
336
|
+
```
|
package/.claude/skills/domain/architecture/performance-engineering/references/caching-strategies.md
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# Caching Strategies
|
|
2
|
+
|
|
3
|
+
## Cache Types
|
|
4
|
+
|
|
5
|
+
### 1. Browser Cache
|
|
6
|
+
```
|
|
7
|
+
HTTP Headers:
|
|
8
|
+
Cache-Control: max-age=31536000 // 1 year for static
|
|
9
|
+
Cache-Control: no-cache // Revalidate
|
|
10
|
+
Cache-Control: private // Browser only
|
|
11
|
+
|
|
12
|
+
ETag: "abc123" // Validation
|
|
13
|
+
Last-Modified: Wed, 21 Oct 2015 // Validation
|
|
14
|
+
|
|
15
|
+
Use for: Static assets, immutable content
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### 2. CDN Cache
|
|
19
|
+
```
|
|
20
|
+
┌──────────┐ ┌──────────────────────────────┐
|
|
21
|
+
│ Origin │ │ CDN │
|
|
22
|
+
│ Server │────▶│ ┌─────┐ ┌─────┐ ┌─────┐ │
|
|
23
|
+
│ │ │ │Edge1│ │Edge2│ │Edge3│ │
|
|
24
|
+
└──────────┘ │ └─────┘ └─────┘ └─────┘ │
|
|
25
|
+
└──────────────────────────────┘
|
|
26
|
+
|
|
27
|
+
CDN Features:
|
|
28
|
+
- Geographic distribution
|
|
29
|
+
- DDoS protection
|
|
30
|
+
- SSL termination
|
|
31
|
+
- Compression
|
|
32
|
+
|
|
33
|
+
Providers: Cloudflare, AWS CloudFront, Fastly, Akamai
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 3. Application Cache
|
|
37
|
+
```
|
|
38
|
+
In-Memory Cache (Redis, Memcached):
|
|
39
|
+
|
|
40
|
+
┌─────────┐ ┌─────────┐ ┌─────────┐
|
|
41
|
+
│ App │────▶│ Redis │ │ DB │
|
|
42
|
+
│ Server │ │ Cluster │ │ │
|
|
43
|
+
└─────────┘ └─────────┘ └─────────┘
|
|
44
|
+
|
|
45
|
+
Use for:
|
|
46
|
+
- Session data
|
|
47
|
+
- API response caching
|
|
48
|
+
- Rate limiting counters
|
|
49
|
+
- Leaderboards
|
|
50
|
+
- Real-time analytics
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 4. Database Cache
|
|
54
|
+
```
|
|
55
|
+
Query Cache:
|
|
56
|
+
- Cache query results
|
|
57
|
+
- Invalidate on write
|
|
58
|
+
|
|
59
|
+
Buffer Pool (InnoDB):
|
|
60
|
+
- Cache table data
|
|
61
|
+
- Cache indexes
|
|
62
|
+
|
|
63
|
+
Read Replicas:
|
|
64
|
+
- Offload read traffic
|
|
65
|
+
- Geographic distribution
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Caching Patterns
|
|
69
|
+
|
|
70
|
+
### Cache-Aside (Lazy Loading)
|
|
71
|
+
```
|
|
72
|
+
def get_user(user_id):
|
|
73
|
+
# 1. Check cache
|
|
74
|
+
cached = cache.get(f"user:{user_id}")
|
|
75
|
+
if cached:
|
|
76
|
+
return cached
|
|
77
|
+
|
|
78
|
+
# 2. Load from DB
|
|
79
|
+
user = db.query("SELECT * FROM users WHERE id = ?", user_id)
|
|
80
|
+
|
|
81
|
+
# 3. Populate cache
|
|
82
|
+
cache.set(f"user:{user_id}", user, ttl=3600)
|
|
83
|
+
|
|
84
|
+
return user
|
|
85
|
+
|
|
86
|
+
Pros:
|
|
87
|
+
- Only caches what's requested
|
|
88
|
+
- Cache failure doesn't break app
|
|
89
|
+
|
|
90
|
+
Cons:
|
|
91
|
+
- Cache miss penalty
|
|
92
|
+
- Stale data possible
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Write-Through
|
|
96
|
+
```
|
|
97
|
+
def update_user(user_id, data):
|
|
98
|
+
# 1. Update cache
|
|
99
|
+
cache.set(f"user:{user_id}", data, ttl=3600)
|
|
100
|
+
|
|
101
|
+
# 2. Update database
|
|
102
|
+
db.query("UPDATE users SET ... WHERE id = ?", user_id)
|
|
103
|
+
|
|
104
|
+
return data
|
|
105
|
+
|
|
106
|
+
Pros:
|
|
107
|
+
- Cache always fresh
|
|
108
|
+
- Read performance optimal
|
|
109
|
+
|
|
110
|
+
Cons:
|
|
111
|
+
- Write latency higher
|
|
112
|
+
- May cache unused data
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Write-Behind (Write-Back)
|
|
116
|
+
```
|
|
117
|
+
Write Queue: [update1, update2, update3]
|
|
118
|
+
|
|
119
|
+
def update_user(user_id, data):
|
|
120
|
+
# 1. Update cache immediately
|
|
121
|
+
cache.set(f"user:{user_id}", data)
|
|
122
|
+
|
|
123
|
+
# 2. Queue for async DB write
|
|
124
|
+
write_queue.push({user_id, data})
|
|
125
|
+
|
|
126
|
+
return data
|
|
127
|
+
|
|
128
|
+
# Background worker:
|
|
129
|
+
def write_worker():
|
|
130
|
+
while True:
|
|
131
|
+
batch = write_queue.pop_batch(100)
|
|
132
|
+
db.batch_update(batch)
|
|
133
|
+
|
|
134
|
+
Pros:
|
|
135
|
+
- Very fast writes
|
|
136
|
+
- Batch DB operations
|
|
137
|
+
|
|
138
|
+
Cons:
|
|
139
|
+
- Risk of data loss
|
|
140
|
+
- Complexity
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Refresh-Ahead
|
|
144
|
+
```
|
|
145
|
+
def get_user(user_id):
|
|
146
|
+
cached = cache.get(f"user:{user_id}")
|
|
147
|
+
|
|
148
|
+
# Check if nearing expiry
|
|
149
|
+
ttl = cache.ttl(f"user:{user_id}")
|
|
150
|
+
if ttl < 300: # Less than 5 min
|
|
151
|
+
# Async refresh
|
|
152
|
+
refresh_queue.push(user_id)
|
|
153
|
+
|
|
154
|
+
return cached or load_from_db(user_id)
|
|
155
|
+
|
|
156
|
+
# Background refresh
|
|
157
|
+
def refresh_worker():
|
|
158
|
+
while True:
|
|
159
|
+
user_id = refresh_queue.pop()
|
|
160
|
+
user = db.query("SELECT * FROM users WHERE id = ?", user_id)
|
|
161
|
+
cache.set(f"user:{user_id}", user, ttl=3600)
|
|
162
|
+
|
|
163
|
+
Pros:
|
|
164
|
+
- No cache misses
|
|
165
|
+
- Optimal read performance
|
|
166
|
+
|
|
167
|
+
Cons:
|
|
168
|
+
- May refresh unused data
|
|
169
|
+
- Complexity
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Cache Invalidation
|
|
173
|
+
|
|
174
|
+
### Strategies
|
|
175
|
+
```
|
|
176
|
+
1. Time-Based (TTL)
|
|
177
|
+
cache.set(key, value, ttl=3600)
|
|
178
|
+
Simple but may serve stale data
|
|
179
|
+
|
|
180
|
+
2. Event-Based
|
|
181
|
+
On data change: cache.delete(key)
|
|
182
|
+
Fresh but requires tracking
|
|
183
|
+
|
|
184
|
+
3. Version-Based
|
|
185
|
+
key = f"user:{user_id}:v{version}"
|
|
186
|
+
Increment version on change
|
|
187
|
+
|
|
188
|
+
4. Tag-Based
|
|
189
|
+
cache.set(key, value, tags=["user:123", "posts"])
|
|
190
|
+
Invalidate by tag
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Cache Stampede Prevention
|
|
194
|
+
```
|
|
195
|
+
Problem: Multiple requests miss cache simultaneously
|
|
196
|
+
Result: All hit database at once
|
|
197
|
+
|
|
198
|
+
Solutions:
|
|
199
|
+
1. Locking
|
|
200
|
+
if cache.get(key) is None:
|
|
201
|
+
if lock.acquire(key, timeout=5):
|
|
202
|
+
value = db.query(...)
|
|
203
|
+
cache.set(key, value)
|
|
204
|
+
lock.release(key)
|
|
205
|
+
else:
|
|
206
|
+
time.sleep(0.1)
|
|
207
|
+
return get_with_cache(key)
|
|
208
|
+
|
|
209
|
+
2. Probabilistic Early Refresh
|
|
210
|
+
if random() < (current_time - expiry) / ttl:
|
|
211
|
+
async_refresh(key)
|
|
212
|
+
|
|
213
|
+
3. Request Coalescing
|
|
214
|
+
pending_requests[key].add(request_id)
|
|
215
|
+
# Single DB query, respond to all waiters
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Cache Configuration
|
|
219
|
+
|
|
220
|
+
### Redis Best Practices
|
|
221
|
+
```
|
|
222
|
+
Memory Management:
|
|
223
|
+
maxmemory 4gb
|
|
224
|
+
maxmemory-policy allkeys-lru
|
|
225
|
+
|
|
226
|
+
Persistence (choose based on needs):
|
|
227
|
+
appendonly yes # AOF for durability
|
|
228
|
+
save 900 1 # RDB snapshots
|
|
229
|
+
|
|
230
|
+
Replication:
|
|
231
|
+
replicaof master-host 6379
|
|
232
|
+
|
|
233
|
+
Keys Design:
|
|
234
|
+
- Use consistent prefixes
|
|
235
|
+
- Include TTL in key when relevant
|
|
236
|
+
- Keep keys short but meaningful
|
|
237
|
+
|
|
238
|
+
Examples:
|
|
239
|
+
user:123:profile # User profile cache
|
|
240
|
+
session:abc123 # Session data
|
|
241
|
+
ratelimit:api:456 # Rate limit counter
|
|
242
|
+
cache:products:page:1 # Paginated cache
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Cache Warming
|
|
246
|
+
```
|
|
247
|
+
def warm_cache():
|
|
248
|
+
"""Pre-populate cache on startup"""
|
|
249
|
+
|
|
250
|
+
# Popular products
|
|
251
|
+
popular = db.query("SELECT * FROM products ORDER BY views DESC LIMIT 100")
|
|
252
|
+
for product in popular:
|
|
253
|
+
cache.set(f"product:{product.id}", product, ttl=3600)
|
|
254
|
+
|
|
255
|
+
# User sessions
|
|
256
|
+
active_sessions = db.query("SELECT * FROM sessions WHERE active = true")
|
|
257
|
+
for session in active_sessions:
|
|
258
|
+
cache.set(f"session:{session.id}", session, ttl=86400)
|
|
259
|
+
|
|
260
|
+
# Run on:
|
|
261
|
+
- Application startup
|
|
262
|
+
- Scheduled (hourly)
|
|
263
|
+
- After cache clear
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Monitoring
|
|
267
|
+
|
|
268
|
+
### Key Metrics
|
|
269
|
+
```
|
|
270
|
+
- Hit rate: cache_hits / (cache_hits + cache_misses)
|
|
271
|
+
- Latency: p50, p95, p99
|
|
272
|
+
- Memory usage: used_memory / maxmemory
|
|
273
|
+
- Evictions: keys evicted due to memory pressure
|
|
274
|
+
- Connections: current connections vs max
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Alerts
|
|
278
|
+
```
|
|
279
|
+
- Hit rate < 80%
|
|
280
|
+
- Memory usage > 90%
|
|
281
|
+
- Latency p99 > 10ms
|
|
282
|
+
- Evictions increasing
|
|
283
|
+
- Connection pool exhausted
|
|
284
|
+
```
|