refactor: remove outdated server design documentation
Remove 557-line server-design.md from _go-learning/architecture - content is now covered in updated architecture documentation with real implementation examples and test coverage.
This commit is contained in:
@@ -0,0 +1,389 @@
|
||||
# Handler Organization Diagram
|
||||
|
||||
## Handler File Structure
|
||||
|
||||
```
|
||||
internal/handlers/
|
||||
├── cv.go Constructor, shared state
|
||||
├── cv_pages.go Full page renders (Home, CVContent)
|
||||
├── cv_htmx.go HTMX partial updates (4 toggles)
|
||||
├── cv_pdf.go PDF export endpoint
|
||||
├── cv_helpers.go Shared utilities (prepareTemplateData, etc.)
|
||||
├── types.go Request/response types, validation
|
||||
├── errors.go Error handling, domain errors
|
||||
├── cv_pages_test.go Tests for page handlers
|
||||
├── cv_htmx_test.go Tests for HTMX handlers
|
||||
└── benchmarks_test.go Benchmark tests
|
||||
```
|
||||
|
||||
## File Responsibilities
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ cv.go │
|
||||
│ (Constructor & State) │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ type CVHandler struct { │
|
||||
│ tmpl *templates.Manager // Template renderer │
|
||||
│ host string // For absolute URLs │
|
||||
│ } │
|
||||
│ │
|
||||
│ func NewCVHandler(tmpl, host) *CVHandler │
|
||||
│ └─→ Constructor for handler initialization │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ cv_pages.go │
|
||||
│ (Full Page Renders) │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ func (h *CVHandler) Home(w, r) │
|
||||
│ └─→ GET / │
|
||||
│ ├─ Get preferences from context │
|
||||
│ ├─ Validate language parameter │
|
||||
│ ├─ Prepare full template data │
|
||||
│ └─ Render: index.html (full page) │
|
||||
│ │
|
||||
│ func (h *CVHandler) CVContent(w, r) │
|
||||
│ └─→ GET /cv │
|
||||
│ ├─ Get preferences from context │
|
||||
│ ├─ Prepare template data │
|
||||
│ └─ Render: partials/cv_content.html │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ cv_htmx.go │
|
||||
│ (HTMX Partial Updates) │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ func (h *CVHandler) ToggleCVLength(w, r) │
|
||||
│ └─→ GET /toggle/length?current=short │
|
||||
│ ├─ Get current preferences │
|
||||
│ ├─ Toggle: short ↔ long │
|
||||
│ ├─ Save cookie: cv-length │
|
||||
│ └─ Render: partials/cv_content.html │
|
||||
│ │
|
||||
│ func (h *CVHandler) ToggleCVIcons(w, r) │
|
||||
│ └─→ GET /toggle/icons?current=show │
|
||||
│ ├─ Toggle: show ↔ hide │
|
||||
│ ├─ Save cookie: cv-icons │
|
||||
│ └─ Render: partials/cv_content.html │
|
||||
│ │
|
||||
│ func (h *CVHandler) ToggleCVTheme(w, r) │
|
||||
│ └─→ GET /toggle/theme?current=default │
|
||||
│ ├─ Toggle: default ↔ minimal │
|
||||
│ ├─ Save cookie: cv-theme │
|
||||
│ └─ Render: partials/cv_content.html │
|
||||
│ │
|
||||
│ func (h *CVHandler) ToggleLanguage(w, r) │
|
||||
│ └─→ GET /toggle/language?current=en │
|
||||
│ ├─ Toggle: en ↔ es │
|
||||
│ ├─ Save cookie: cv-language │
|
||||
│ └─ Render: index.html (full page for i18n) │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ cv_pdf.go │
|
||||
│ (PDF Export) │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ func (h *CVHandler) ExportPDF(w, r) │
|
||||
│ └─→ POST /export/pdf │
|
||||
│ ├─ Parse JSON request body │
|
||||
│ ├─ Validate: lang, length, icons, version │
|
||||
│ ├─ Render HTML to buffer │
|
||||
│ ├─ Generate PDF via chromedp │
|
||||
│ └─ Send PDF response with download header │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ cv_helpers.go │
|
||||
│ (Shared Utilities) │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ func (h *CVHandler) prepareTemplateData(lang) map │
|
||||
│ └─→ Shared data preparation for all handlers │
|
||||
│ ├─ Load CV data: cvmodel.LoadCV(lang) │
|
||||
│ ├─ Load UI strings: uimodel.LoadUI(lang) │
|
||||
│ ├─ Calculate durations for experiences │
|
||||
│ ├─ Split skills into columns │
|
||||
│ ├─ Add SEO metadata │
|
||||
│ └─ Return: complete data map │
|
||||
│ │
|
||||
│ func (h *CVHandler) getFullURL(path) string │
|
||||
│ └─→ Build absolute URLs for SEO/PDF │
|
||||
│ └─ Return: http://host/path │
|
||||
│ │
|
||||
│ func validateLanguage(lang) error │
|
||||
│ └─→ Validate language parameter │
|
||||
│ └─ Check: lang in ["en", "es"] │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ types.go │
|
||||
│ (Request/Response Types) │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ // Request Types │
|
||||
│ type PDFExportRequest struct { │
|
||||
│ Lang string `json:"lang" validate:"required,oneof=en es"` │
|
||||
│ Length string `json:"length" validate:"required,oneof=short long"` │
|
||||
│ Icons string `json:"icons" validate:"required,oneof=show hide"` │
|
||||
│ Version string `json:"version" validate:"required,oneof=with_skills clean"` │
|
||||
│ } │
|
||||
│ │
|
||||
│ // Response Types │
|
||||
│ type APIResponse struct { │
|
||||
│ Success bool `json:"success"` │
|
||||
│ Data interface{} `json:"data,omitempty"` │
|
||||
│ Error *ErrorInfo `json:"error,omitempty"` │
|
||||
│ Meta *MetaInfo `json:"meta,omitempty"` │
|
||||
│ } │
|
||||
│ │
|
||||
│ type ErrorInfo struct { │
|
||||
│ Code string `json:"code"` │
|
||||
│ Message string `json:"message"` │
|
||||
│ Field string `json:"field,omitempty"` │
|
||||
│ } │
|
||||
│ │
|
||||
│ type MetaInfo struct { │
|
||||
│ Timestamp time.Time `json:"timestamp"` │
|
||||
│ RequestID string `json:"request_id,omitempty"` │
|
||||
│ } │
|
||||
│ │
|
||||
│ // Constructor Functions │
|
||||
│ func NewAPIResponse(data interface{}) *APIResponse │
|
||||
│ func NewErrorResponse(code, message string) *APIResponse │
|
||||
│ func NewPDFExportRequest() *PDFExportRequest │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ errors.go │
|
||||
│ (Error Handling) │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ // Error Codes │
|
||||
│ type ErrorCode string │
|
||||
│ const ( │
|
||||
│ ErrCodeInvalidLanguage = "INVALID_LANGUAGE" │
|
||||
│ ErrCodeInvalidLength = "INVALID_LENGTH" │
|
||||
│ ErrCodeInvalidIcons = "INVALID_ICONS" │
|
||||
│ ErrCodePDFGeneration = "PDF_GENERATION" │
|
||||
│ ErrCodeRateLimitExceeded = "RATE_LIMIT_EXCEEDED" │
|
||||
│ // ... 8 more error codes │
|
||||
│ ) │
|
||||
│ │
|
||||
│ // Domain Error Type │
|
||||
│ type DomainError struct { │
|
||||
│ Code ErrorCode │
|
||||
│ Message string │
|
||||
│ Err error │
|
||||
│ StatusCode int │
|
||||
│ Field string │
|
||||
│ } │
|
||||
│ │
|
||||
│ // Error Constructors │
|
||||
│ func InvalidLanguageError(lang) *DomainError │
|
||||
│ func InvalidLengthError(length) *DomainError │
|
||||
│ func PDFGenerationError(err) *DomainError │
|
||||
│ // ... 10 more constructors │
|
||||
│ │
|
||||
│ // Error Handler │
|
||||
│ func (h *CVHandler) HandleError(w, r, err) │
|
||||
│ └─→ Centralized error handling │
|
||||
│ ├─ Log error with code │
|
||||
│ ├─ Build error response │
|
||||
│ └─ Send JSON error │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Handler Dependencies
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────┐
|
||||
│ Handler Dependencies │
|
||||
└────────────────────────────────────────────────────────────┘
|
||||
|
||||
CVHandler
|
||||
├─→ internal/templates (template rendering)
|
||||
│ └─→ Manager.Render(w, name, data)
|
||||
│
|
||||
├─→ internal/models/cv (CV data)
|
||||
│ └─→ LoadCV(lang) (*CV, error)
|
||||
│
|
||||
├─→ internal/models/ui (UI strings)
|
||||
│ └─→ LoadUI(lang) (*UI, error)
|
||||
│
|
||||
├─→ internal/middleware (preferences)
|
||||
│ ├─→ GetPreferences(r) *Preferences
|
||||
│ ├─→ GetLanguage(r) string
|
||||
│ ├─→ IsLongCV(r) bool
|
||||
│ └─→ SetPreferenceCookie(w, name, value)
|
||||
│
|
||||
├─→ internal/pdf (PDF generation)
|
||||
│ └─→ GeneratePDF(html, options) ([]byte, error)
|
||||
│
|
||||
└─→ encoding/json (JSON parsing)
|
||||
└─→ json.NewDecoder(r.Body).Decode(&req)
|
||||
```
|
||||
|
||||
## Handler Call Flow
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────┐
|
||||
│ Typical Handler Call Flow │
|
||||
└────────────────────────────────────────────────────────────┘
|
||||
|
||||
Request arrives
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ Middleware Chain │
|
||||
│ (preferences set) │
|
||||
└─────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ Handler Method │
|
||||
│ (cv_pages.go) │
|
||||
└─────────────────────┘
|
||||
│
|
||||
├─→ middleware.GetPreferences(r)
|
||||
│ └─→ Extract from request context
|
||||
│
|
||||
├─→ validateLanguage(lang)
|
||||
│ └─→ Check valid language
|
||||
│
|
||||
├─→ h.prepareTemplateData(lang)
|
||||
│ │ (cv_helpers.go)
|
||||
│ │
|
||||
│ ├─→ cvmodel.LoadCV(lang)
|
||||
│ │ └─→ Read data/cv-{lang}.json
|
||||
│ │
|
||||
│ ├─→ uimodel.LoadUI(lang)
|
||||
│ │ └─→ Read data/ui-{lang}.json
|
||||
│ │
|
||||
│ ├─→ calculateDurations()
|
||||
│ │ └─→ For each experience
|
||||
│ │
|
||||
│ └─→ splitSkillsIntoColumns()
|
||||
│ └─→ Distribute evenly
|
||||
│
|
||||
└─→ h.tmpl.Render(w, "index.html", data)
|
||||
└─→ Execute template with data
|
||||
```
|
||||
|
||||
## Handler Testing Structure
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────┐
|
||||
│ Handler Tests │
|
||||
└────────────────────────────────────────────────────────────┘
|
||||
|
||||
cv_pages_test.go
|
||||
├─ TestHome
|
||||
│ ├─ Valid requests (en, es)
|
||||
│ ├─ Invalid language
|
||||
│ ├─ With preferences
|
||||
│ └─ Default fallback
|
||||
│
|
||||
└─ TestCVContent
|
||||
├─ Valid language
|
||||
├─ With preferences
|
||||
└─ Error handling
|
||||
|
||||
cv_htmx_test.go
|
||||
├─ TestToggleCVLength
|
||||
│ ├─ short → long
|
||||
│ ├─ long → short
|
||||
│ └─ Cookie setting
|
||||
│
|
||||
├─ TestToggleCVIcons
|
||||
│ ├─ show → hide
|
||||
│ └─ hide → show
|
||||
│
|
||||
├─ TestToggleCVTheme
|
||||
│ └─ default ↔ minimal
|
||||
│
|
||||
└─ TestToggleLanguage
|
||||
└─ en ↔ es
|
||||
|
||||
benchmarks_test.go
|
||||
├─ BenchmarkHome
|
||||
├─ BenchmarkCVContent
|
||||
├─ BenchmarkToggleCVLength
|
||||
├─ BenchmarkToggleCVIcons
|
||||
├─ BenchmarkToggleCVTheme
|
||||
├─ BenchmarkToggleLanguage
|
||||
├─ BenchmarkExportPDF
|
||||
├─ BenchmarkPrepareTemplateData
|
||||
├─ BenchmarkValidateLanguage
|
||||
├─ BenchmarkErrorResponse
|
||||
└─ BenchmarkNewAPIResponse
|
||||
```
|
||||
|
||||
## Handler Pattern Summary
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────┐
|
||||
│ Handler Organization Principles │
|
||||
└────────────────────────────────────────────────────────────┘
|
||||
|
||||
1. SEPARATION BY RESPONSIBILITY
|
||||
├─ Pages: Full page renders
|
||||
├─ HTMX: Partial updates
|
||||
├─ PDF: Export functionality
|
||||
└─ Helpers: Shared utilities
|
||||
|
||||
2. TYPE SAFETY
|
||||
├─ Structured request types
|
||||
├─ Structured response types
|
||||
└─ Validation tags
|
||||
|
||||
3. ERROR HANDLING
|
||||
├─ Domain-specific errors
|
||||
├─ Error codes
|
||||
└─ Centralized error handler
|
||||
|
||||
4. TESTABILITY
|
||||
├─ Unit tests per file
|
||||
├─ Integration tests
|
||||
└─ Benchmark tests
|
||||
|
||||
5. DEPENDENCY INJECTION
|
||||
├─ Template manager injected
|
||||
├─ No global state
|
||||
└─ Easy to mock
|
||||
|
||||
6. MIDDLEWARE INTEGRATION
|
||||
├─ Preferences from context
|
||||
├─ Helper functions
|
||||
└─ Clean separation
|
||||
```
|
||||
|
||||
## Performance Profile
|
||||
|
||||
```
|
||||
Handler Performance Characteristics:
|
||||
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Handler Time Allocations │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ Home() ~50 ms ~1200 allocs │
|
||||
│ CVContent() ~45 ms ~1100 allocs │
|
||||
│ ToggleCVLength() ~45 ms ~1100 allocs │
|
||||
│ ToggleCVIcons() ~45 ms ~1100 allocs │
|
||||
│ ToggleCVTheme() ~45 ms ~1100 allocs │
|
||||
│ ToggleLanguage() ~50 ms ~1200 allocs │
|
||||
│ ExportPDF() ~1000 ms ~5000 allocs │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ prepareTemplateData() ~2 ms ~50 allocs │
|
||||
│ validateLanguage() ~10 ns 0 allocs │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
|
||||
Memory Profile:
|
||||
- Most allocations in template rendering (~90%)
|
||||
- JSON parsing minimal (<1%)
|
||||
- Helper functions optimized (zero-alloc where possible)
|
||||
```
|
||||
|
||||
## Related Diagrams
|
||||
|
||||
- [System Architecture](./01-system-architecture.md) - Overall system design
|
||||
- [Request Flow](./02-request-flow.md) - HTTP request lifecycle
|
||||
- [Middleware Chain](./03-middleware-chain.md) - Middleware execution
|
||||
- [Error Handling Flow](./06-error-handling-flow.md) - Error propagation
|
||||
Reference in New Issue
Block a user