- Move 8 stray .md (+5 .txt) from ~/Desktop into docs/explorations/from-desktop/ - Reorganize 27 .md/.txt at workspace root: - audit reports -> docs/audits/ - exploration reports -> docs/explorations/ - design system -> docs/design-system/ - Keep only README/CHANGELOG/CONTRIBUTING/CLAUDE at repo root - Refresh docs/README.md as canonical index with links to all groups - Note: pre-existing docs/audits/AUDIT_INDEX.md and AUDIT_SUMMARY.md were overwritten by the newer root-level versions during the move Co-Authored-By: Paperclip <noreply@paperclip.ing>
9.6 KiB
9.6 KiB
GoodGo Analytics Module — Complete Architecture Guide
📚 Overview
This package contains 4 comprehensive guides (2,174 lines, 71 KB) to understand the GoodGo Analytics Module architecture, caching system, and endpoint patterns.
📖 Quick Navigation
| File | Purpose | Read Time | Best For |
|---|---|---|---|
| 00_SUMMARY.md | Overview & key findings | 5 min | Getting oriented |
| 02_quick_reference.md | Visual diagrams & checklists | 10 min | Visual learners |
| 03_file_paths_reference.md | File navigation & structure | 15 min | Finding code |
| 01_analytics_architecture_guide.md | Deep dive with code examples | 30+ min | Full understanding |
🚀 Recommended Reading Path
- Start with 00_SUMMARY.md — understand what you're learning
- Read 02_quick_reference.md — visualize the architecture
- Skim 03_file_paths_reference.md — know where to find things
- Deep dive 01_analytics_architecture_guide.md — master the patterns
Total time: ~60 minutes to fully understand the module
🎯 What You'll Learn
Architecture
- ✅ Domain-Driven Design (DDD) with CQRS pattern
- ✅ 4-layer structure: Presentation → Application → Domain → Infrastructure
- ✅ 24 endpoints across 2 controllers
- ✅ 15+ query handlers with caching
Caching
- ✅ Redis cache-aside pattern
- ✅ Two caching styles: @Cacheable decorator vs manual cache.getOrSet()
- ✅ Cache TTLs for different endpoint types
- ✅ Graceful degradation when Redis is down
- ✅ Cache metadata in responses
Database
- ✅ Prisma schema for Property, Listing, MarketIndex, Valuation
- ✅ PostGIS spatial queries
- ✅ Indexes for query optimization
Implementation
- ✅ How to add a new GET endpoint in 7 steps
- ✅ Query handler patterns with real examples
- ✅ DTO design and validation
- ✅ Error handling conventions
- ✅ Testing patterns
🏗️ Architecture Overview
┌─────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ • AnalyticsController (19 endpoints) │
│ • AvmController (5 endpoints) │
│ • DTOs, Guards, Interceptors │
└──────────────────┬──────────────────────┘
↓ QueryBus.execute()
┌──────────────────────────────────────────┐
│ APPLICATION LAYER (CQRS) │
│ • 15+ Query Handlers (@QueryHandler) │
│ • @Cacheable or cache.getOrSet() │
│ • Try-catch error handling │
└──────────────────┬──────────────────────┘
↓ Injected services
┌──────────────────────────────────────────┐
│ DOMAIN LAYER (Business Logic) │
│ • Entities, Repository Interfaces │
│ • Service Interfaces, Result DTOs │
└──────────────────┬──────────────────────┘
↓ Injected implementation
┌──────────────────────────────────────────┐
│ INFRASTRUCTURE LAYER │
│ • Prisma Repositories │
│ • HTTP Services, External clients │
└──────────────────────────────────────────┘
💾 Caching Pattern
HTTP GET /analytics/market-snapshot?city=Ho Chi Minh
↓
QueryHandler builds key: "cache:analytics:market_snapshot:ho_chi_minh"
↓
cache.getOrSet(key, loader, TTL, resource):
├─ Redis HIT: return cached value
├─ Redis MISS: call loader() → compute → store
└─ Redis DOWN: call loader() directly (graceful degradation)
↓
CacheMetaInterceptor wraps: { data: result, cacheMeta: {...} }
↓
HTTP 200: { data: {...}, cacheMeta: { cachedAt, nextRefreshAt, source } }
🔑 Key Findings
- 24 Endpoints: 19 in AnalyticsController + 5 in AvmController
- 15+ Query Handlers: All with caching (except predictions)
- 2 Caching Patterns: @Cacheable decorator or manual cache.getOrSet()
- Redis Cache-Aside: TTL-based expiry, graceful degradation
- 4 Prisma Models: Property, Listing, MarketIndex, Valuation
- DTOs + Guards: All endpoints secured with JWT, Quota, Rate Limit
📚 Detailed Contents
00_SUMMARY.md
- Overview of all 4 guides
- Key architecture decisions
- 7-step endpoint addition walkthrough
- Architecture decision matrix
- Core conventions checklist
01_analytics_architecture_guide.md ⭐ COMPREHENSIVE
- DDD layer breakdown with code examples
- All 24 endpoints documented
- Query handler patterns (decorator vs manual)
- Complete Redis caching system
- Real code from GetMarketSnapshotHandler, GetDistrictStatsHandler
- Full Prisma schema documentation
- Shared module utilities (CacheService, @Cacheable, CacheMetaInterceptor)
- Complete 7-step guide: adding GET /trending-areas endpoint
- Testing patterns & error handling conventions
02_quick_reference.md ⭐ VISUAL QUICK START
- Architecture layer stack diagram
- Request flow visualization
- Caching strategy matrix
- Decorators & guards cheat sheet
- Prisma schema snapshot
- Response structure examples
- 7-step endpoint addition checklist
03_file_paths_reference.md ⭐ NAVIGATION MAP
- Core module files (analytics.module.ts, index.ts)
- All 24 endpoints mapped to file paths
- DTO files organized by type (request vs response)
- All 15+ query types with descriptions
- Domain, Infrastructure, Shared layer breakdowns
- Database schema models with fields & indexes
- Directory tree with line counts
- Import patterns reference
- Key metrics & numbers
🎯 Quick Start: Adding New Endpoint
7 Steps to Add GET /analytics/trending-areas
- Request DTO →
presentation/dto/get-trending-areas.dto.ts - Query Class →
application/queries/get-trending-areas/query.ts - Handler →
application/queries/get-trending-areas/handler.ts(with @Cacheable) - Register → Add to QueryHandlers array in analytics.module.ts
- Controller → Add method to analytics.controller.ts
- Export → Add to presentation/dto/index.ts
- Test → Create handler spec
Full walkthrough with code in guides!
✅ Core Conventions
// Cache with TTL
Dashboard tiles: 300s (5 min)
Aggregations: 300s (5 min)
Reports: 900s (15 min)
Trends: 1800s (30 min)
Predictions: NO_CACHE (always fresh)
// Build cache keys deterministically
CacheService.buildKey(CachePrefix.MARKET_DISTRICT, city, period)
// Result: "cache:market:district:ho_chi_minh:2024_q1"
// Always wrap handlers in try-catch
try { ... } catch(error) {
if (error instanceof DomainException) throw error;
logger.error(...);
throw new InternalServerErrorException('...');
}
// Always return DTOs with null metadata
return { city, data, cachedAt: null, nextRefreshAt: null };
// Always use guards
@UseGuards(JwtAuthGuard, QuotaGuard)
@RequireQuota('analytics_queries')
📊 Key Metrics
| Metric | Value |
|---|---|
| Controllers | 2 |
| Endpoints | 24 |
| Query Handlers | 15+ |
| DTOs | 15+ |
| Caching Patterns | 2 |
| Cache Prefixes | 10+ |
| Cache TTLs | 20+ |
| Prisma Models | 4 |
| Repository Interfaces | 2 |
| Services (interfaces) | 2 |
| Services (implementations) | 6+ |
| Module LOC | ~2,000 |
| Shared Cache LOC | ~250 |
🧠 Test Your Understanding
After reading all guides, you should be able to:
- Explain the 4 DDD layers and what goes in each
- Describe how cache-aside pattern works
- Distinguish @Cacheable from cache.getOrSet()
- Explain why response DTOs have null metadata
- Build deterministic cache keys
- Choose appropriate TTLs for endpoints
- List required guards for endpoints
- Add a new endpoint in 7 steps
- Explain CacheMetaInterceptor purpose
- Describe graceful degradation behavior
📁 Prisma Schema Models
Property — Real estate property details
- Type, location (PostGIS), area, rooms, condition
- Indexes: [propertyType], [district, city], [location (Gist)]
Listing — Property listings on platform
- Price (BigInt), status, AVM estimates
- Indexes: [status], [sellerId, status], [publishedAt]
MarketIndex — Aggregated market data by period
- District, city, propertyType, period
- Median price, average price/m², statistics
- Unique: [district, city, propertyType, period]
Valuation — AI valuation estimates
- Property, estimated price, confidence, method
- Features, comparables, explainers (Json)
- Index: [propertyId, valuationDate DESC]
🚀 Next Steps
- Read all 4 guides in recommended order (60 min)
- Review the 7-step endpoint addition guide
- Study real handler code examples in guide
- Explore actual files in codebase:
apps/api/src/modules/analytics/apps/api/src/modules/shared/
- Add your first new endpoint following patterns
📞 Questions & Understanding
If you have questions after reading:
- Refer back to specific sections in guides
- Check code examples in guide vs actual code
- Review the 10 validation questions
- Study the architecture decision matrix
Total package: 2,174 lines, 71 KB of comprehensive documentation
Start with 00_SUMMARY.md and follow the reading path. You'll understand the entire architecture in about 60 minutes!