Skip to content

Commit 2e7c771

Browse files
ritunjaymclaude
andcommitted
fix: resolve 5 pre-submission audit issues
1. prometheus.yml: scrape target api:8081 → api:8080 (metrics always served on the HTTP port via MapPrometheusScrapingEndpoint) 2. docker-compose.yml: env var prefix VectorCatalogOptions__ → VectorCatalog__ to match SectionName constant; fix property names (TopK→DefaultTopK, AccessKey→MinioAccessKey, etc.) and remove dead port 8081 mapping 3. src/VectorCatalog.Api/Dockerfile: remove EXPOSE 8081 (nothing serves there) 4. Add .dockerignore for API and sidecar (reduces build-context noise) 5. README.md: fix stale benchmark numbers, wrong load-test script name, wrong CI job count (7→8), Helm path, and Roadmap completed items Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ca3cd7d commit 2e7c771

7 files changed

Lines changed: 122 additions & 38 deletions

File tree

README.md

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,9 @@ graph TB
190190

191191
| Component | Technology | Purpose |
192192
|-----------|-----------|---------|
193-
| **CI/CD** | GitHub Actions | 7-job pipeline (build, test, security scan) |
193+
| **CI/CD** | GitHub Actions | 8-job pipeline (build, test, security scan, GHCR push) |
194194
| **Containers** | Docker + Compose | Multi-stage builds, non-root users |
195-
| **IaC** | docker-compose.yml | Local orchestration (7 services) |
195+
| **IaC** | docker-compose.yml | Local orchestration (6 services) |
196196

197197
---
198198

@@ -390,10 +390,10 @@ dotnet run --project src/VectorCatalog.Api/VectorCatalog.Api.csproj
390390
### Unit Tests
391391

392392
```bash
393-
# C# tests (8 tests)
393+
# C# unit tests (7 tests)
394394
dotnet test tests/VectorCatalog.Api.Tests/
395395

396-
# Python tests (16 tests)
396+
# Python tests
397397
cd sidecar && pytest tests/ -v
398398
```
399399

@@ -407,21 +407,24 @@ dotnet test tests/VectorCatalog.Integration.Tests/
407407
### Load Testing (k6)
408408

409409
```bash
410-
k6 run tests/load/search_load_test.js --vus 50 --duration 30s
410+
k6 run tests/load/health_load.js
411+
k6 run tests/load/search_load.js --out json=tests/load/results/search_results.json
411412
```
412413

413414
---
414415

415416
## 📊 Performance Benchmarks
416417

417-
| Metric | Value | Configuration |
418-
|--------|-------|---------------|
419-
| **Query Latency (p50)** | 45ms | Redis cache miss, nprobe=10 |
420-
| **Query Latency (p99)** | 120ms | Cold cache, complex query |
421-
| **Throughput** | 500 QPS | 4 CPU, 8GB RAM, local |
422-
| **Cache Hit Rate** | 78% | After 10K queries |
423-
| **Index Build Time** | 15 min | 1M vectors, nlist=100 |
424-
| **Index Size** | 150 MB | 1M vectors (100x compression) |
418+
Measured with k6 v1.6.1 on Apple M2 / Docker Compose. See [`docs/BENCHMARKS.md`](docs/BENCHMARKS.md) for full results.
419+
420+
| Metric | Value | Scenario |
421+
|--------|-------|----------|
422+
| **Health P95** | 31ms | GET /health/live, 200 VUs |
423+
| **Health Throughput** | 17,396 req/s | ASP.NET Core baseline |
424+
| **Search P50** | 152ms | Warm Redis cache, synthetic FAISS index |
425+
| **Search P99** | 425ms | Warm Redis cache, synthetic FAISS index |
426+
| **Cache Hit Rate** | 85.3% | 6,674 hits / 7,823 requests |
427+
| **Avg Cache Hit Latency** | 48ms | Redis round-trip |
425428

426429
---
427430

@@ -430,13 +433,14 @@ k6 run tests/load/search_load_test.js --vus 50 --duration 30s
430433
### Docker
431434

432435
```bash
433-
docker compose -f docker-compose.prod.yml up -d
436+
docker compose up -d
434437
```
435438

436-
### Kubernetes (Helm Chart - Coming Soon)
439+
### Kubernetes (Helm)
437440

438441
```bash
439-
helm install vector-catalog ./charts/vector-catalog
442+
helm install vector-catalog ./helm/vector-catalog \
443+
--set image.tag=$(git rev-parse --short HEAD)
440444
```
441445

442446
---
@@ -486,8 +490,8 @@ rate(redis_commands_total{command="get",status="hit"}[5m]) / rate(redis_commands
486490
- [ ] Kubernetes Helm chart
487491

488492
### Week 3: Production Hardening
489-
- [ ] Integration tests with Testcontainers
490-
- [ ] Load testing with k6
493+
- [x] Integration tests with Testcontainers (12/12 passing)
494+
- [x] Load testing with k6 (17,396 req/s baseline; Polly behavior documented)
491495
- [ ] APM (Application Performance Monitoring)
492496
- [ ] Alert rules (Prometheus + Alertmanager)
493497

docker-compose.yml

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -104,23 +104,22 @@ services:
104104
dockerfile: src/VectorCatalog.Api/Dockerfile
105105
container_name: vector-catalog-api
106106
ports:
107-
- "8080:8080" # HTTP API
108-
- "8081:8081" # Prometheus metrics
107+
- "8080:8080" # HTTP API + Prometheus /metrics
109108
environment:
110109
ASPNETCORE_ENVIRONMENT: Production
111110
ASPNETCORE_URLS: http://+:8080
112-
VectorCatalogOptions__Sidecar__GrpcAddress: http://sidecar:50051
113-
VectorCatalogOptions__Redis__ConnectionString: redis:6379
114-
VectorCatalogOptions__Redis__KeyPrefix: "vc:"
115-
VectorCatalogOptions__Redis__DefaultCacheTtlSeconds: 300
116-
VectorCatalogOptions__Faiss__TopK: 10
117-
VectorCatalogOptions__Faiss__Nprobe: 10
118-
VectorCatalogOptions__Faiss__DefaultShardKey: nyc_taxi_2023
119-
VectorCatalogOptions__Storage__MinioEndpoint: minio:9000
120-
VectorCatalogOptions__Storage__AccessKey: minioadmin
121-
VectorCatalogOptions__Storage__SecretKey: minioadmin
122-
VectorCatalogOptions__RateLimit__PermitLimit: 100
123-
VectorCatalogOptions__RateLimit__WindowSeconds: 10
111+
VectorCatalog__SidecarGrpcAddress: http://sidecar:50051
112+
VectorCatalog__Redis__ConnectionString: redis:6379
113+
VectorCatalog__Redis__KeyPrefix: "vc:"
114+
VectorCatalog__Redis__DefaultCacheTtlSeconds: 300
115+
VectorCatalog__Faiss__DefaultTopK: 10
116+
VectorCatalog__Faiss__DefaultNprobe: 10
117+
VectorCatalog__Faiss__DefaultShardKey: nyc_taxi_2023
118+
VectorCatalog__Storage__MinioEndpoint: http://minio:9000
119+
VectorCatalog__Storage__MinioAccessKey: minioadmin
120+
VectorCatalog__Storage__MinioSecretKey: minioadmin
121+
VectorCatalog__RateLimit__PermitLimit: 100
122+
VectorCatalog__RateLimit__WindowSeconds: 10
124123
depends_on:
125124
redis:
126125
condition: service_healthy

docs/BENCHMARKS.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,7 @@ check: `GET /health/ready` → 200 OK (Redis dependency healthy).
124124
- `error_type="Grpc.Core.RpcException"` label on 500 responses confirms gRPC error
125125
propagation is instrumented ✅
126126
- Jaeger traces confirm parent-child span relationships (API → gRPC sidecar) ✅
127-
- Note: `prometheus.yml` scrape target points to port 8081 (incorrect); fix pending.
128-
Direct scrape via `curl localhost:8080/metrics` works correctly.
127+
- `prometheus.yml` scrape target: `api:8080` ✅ (fixed — was incorrectly `api:8081`)
129128

130129
---
131130

@@ -217,7 +216,7 @@ check: `GET /health/ready` → 200 OK (Redis dependency healthy).
217216
## Optimization Opportunities
218217

219218
### Short-term
220-
1. **Fix Prometheus scrape target**: change `api:8081``api:8080` in `prometheus.yml`
219+
1. ~~**Fix Prometheus scrape target**~~: fixed (`api:8080` in `prometheus.yml`) ✅
221220
2. **Embedding caching**: cache embeddings by query hash → −30% P99 on cache misses
222221
3. **gRPC connection pooling**: increase pool from 10 → 50 → +15% throughput under load
223222

infra/docker/prometheus.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ scrape_configs:
1111
# ══════════════════════════════════════════════════════════════════════════
1212
- job_name: 'vector-catalog-api'
1313
static_configs:
14-
- targets: ['api:8081']
14+
- targets: ['api:8080']
1515
labels:
1616
service: 'vector-catalog-api'
1717
version: 'v0.1.0'

sidecar/.dockerignore

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# .dockerignore for Python gRPC sidecar
2+
# Only .py files, requirements.txt, and proto stubs are needed
3+
4+
# Python cache
5+
__pycache__/
6+
*.pyc
7+
*.pyo
8+
*.pyd
9+
*.so
10+
11+
# Virtual environments
12+
.venv/
13+
venv/
14+
env/
15+
16+
# Test artefacts
17+
.pytest_cache/
18+
.mypy_cache/
19+
htmlcov/
20+
.coverage
21+
tests/
22+
23+
# Data / FAISS indices (large — never bake into image)
24+
data/
25+
*.index
26+
*.faiss
27+
*.parquet
28+
29+
# IDE / OS
30+
.idea/
31+
.vscode/
32+
.DS_Store
33+
Thumbs.db
34+
35+
# Git
36+
.git/
37+
.gitignore
38+
39+
# Secrets
40+
*.env
41+
.env
42+
secrets/
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# .dockerignore for VectorCatalog.Api
2+
# Keep the build context small — only C# source/config is needed
3+
4+
# Build artifacts
5+
**/bin/
6+
**/obj/
7+
**/publish/
8+
9+
# Test projects
10+
**/tests/
11+
12+
# IDE / OS
13+
.vs/
14+
.vscode/
15+
.idea/
16+
*.suo
17+
*.user
18+
.DS_Store
19+
Thumbs.db
20+
21+
# Git
22+
.git/
23+
.gitignore
24+
.gitattributes
25+
26+
# Docs / scripts (not needed at build time)
27+
docs/
28+
scripts/
29+
infra/
30+
sidecar/
31+
32+
# Secrets
33+
*.env
34+
.env
35+
secrets/
36+
37+
# Node / Python artefacts (shouldn't be here, but be safe)
38+
node_modules/
39+
__pycache__/
40+
*.pyc

src/VectorCatalog.Api/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ RUN chown -R appuser:appuser /app
3939
# Switch to non-root user
4040
USER appuser
4141

42-
# Expose ports
43-
EXPOSE 8080 8081
42+
# Expose HTTP port (API + /metrics endpoint)
43+
EXPOSE 8080
4444

4545
# Environment variables (can be overridden at runtime)
4646
ENV ASPNETCORE_URLS=http://+:8080 \

0 commit comments

Comments
 (0)