docs: add Echo v5 migration guide and remove outdated infrastructure plan

- Add comprehensive Echo v5 migration guide (ECHO_V5_MIGRATION.md)
  - Documents all API changes and type signature updates
  - Provides step-by-step fixes for deprecated middleware
  - Includes middleware pattern examples for v5
  - Documents WebSocket fix for v5 compatibility
  - Includes verification and rollback plans
- Remove outdated infrastructure enhancement plan (3488 lines)
  - Legacy plan is no longer relevant after Echo v5 migration
  - Consolidates documentation into single migration guide
This commit is contained in:
2026-03-06 13:59:51 -05:00
parent ef8fedeed7
commit ea5d53a3ad
2 changed files with 338 additions and 3488 deletions
File diff suppressed because it is too large Load Diff
+338
View File
@@ -0,0 +1,338 @@
# Echo v5 Migration Plan
## Overview
This document outlines the steps required to migrate from Echo v4 to Echo v5, including API changes, type signature updates, and middleware modifications.
## Errors Identified
### 1. Deprecated Middleware
**Error:** `echomiddleware.Logger undefined`
**Solution:** Replace `echomiddleware.Logger()` with `echomiddleware.RequestLogger()`
**Files affected:**
- `cmd/server/main.go` (line 142)
- `internal/router/router.go` (line 144)
### 2. Removed API Methods
**Error:** `a.echo.Close undefined (type *echo.Echo has no field or method Close)`
**Solution:** Remove the `echo.Close()` call as v5 uses different graceful shutdown mechanism
**Files affected:**
- `internal/app/app.go` (line 86)
### 3. Type Signature & Response API Changes
**Error:** Multiple type mismatches and Response API changes in Echo v5
**Root Cause:** Echo v5 uses `*echo.Context` (pointer) for handlers but some code uses `echo.Context` (value). Response wrapper API also changed.
**Solution:**
- Update all middleware to use `*echo.Context`
- Update helper functions to accept `*echo.Context`
- Fix Response wrapper usage for Echo v5 API
**Files affected:**
- `internal/middleware/device_auth.go` (lines 38, 170, 212)
- `internal/middleware/error_handler.go` (lines 44, 69, 82, 84, 87, 89)
- `internal/middleware/rate_limiter.go` (line 102)
- `internal/middleware/request_tracing.go` (lines 48, 58, 60)
- `internal/middleware/security.go` (line 14)
---
## Step-by-Step Fixes
### Step 1: Fix Deprecated Logger Middleware
#### File: `cmd/server/main.go`
**Line 142:**
```go
// BEFORE:
e.Use(echomiddleware.Logger())
// AFTER:
e.Use(echomiddleware.RequestLogger())
```
#### File: `internal/router/router.go`
**Line ~144:**
```go
// BEFORE:
e.Use(echomiddleware.Logger())
// AFTER:
e.Use(echomiddleware.RequestLogger())
```
---
### Step 2: Fix Removed API Methods
#### File: `internal/app/app.go`
**Lines 26-32 - Initialize server field:**
```go
// REPLACE lines 26-32 with:
func New(echo *echo.Echo) *App {
return &App{
echo: echo,
server: nil, // Will be set in StartServer()
shutdownTimeout: 30 * time.Second,
shutdownDone: make(chan struct{}),
}
}
```
**Add StartServer method after New() (after line 32):**
```go
// StartServer creates HTTP server and starts listening
func (a *App) StartServer(addr string) error {
a.server = &http.Server{
Addr: addr,
Handler: a.echo,
}
// Start HTTP server in background
go func() {
if err := a.server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("Server failed to start: %v", err)
}
}()
return nil
}
```
**Lines 82-94 - Replace goroutine in Shutdown():**
```go
// REPLACE lines 82-94 with:
// Stop accepting new connections and shutdown HTTP server
log.Println("Stopping HTTP server...")
if a.server != nil {
ctx, cancel := context.WithTimeout(context.Background(), a.shutdownTimeout)
defer cancel()
if err := a.server.Shutdown(ctx); err != nil {
log.Printf("Error stopping HTTP server: %v", err)
}
}
log.Println("All services stopped")
```
#### File: `cmd/server/main.go`
**Lines 197-214 - Replace server startup:**
```go
// REPLACE lines 197-214 with:
// ========================================================================
// START SERVER (managed by app lifecycle)
// ========================================================================
log.Printf("Starting server on port %s", cfg.ServerPort)
// Start HTTP server
if err := application.StartServer(":" + cfg.ServerPort); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
// Start application lifecycle (blocks until shutdown signal)
if err := application.Start(); err != nil {
log.Fatalf("Application error: %v", err)
}
```
---
### Step 3: Fix Middleware Type Signatures
#### Pattern for Echo v5 Middleware
**Echo v5 Middleware Pattern:**
```go
func MiddlewareFunc(next echo.HandlerFunc) echo.HandlerFunc {
return func(c *echo.Context) error { // ← POINTER (required in v5)
// ... middleware logic
return next(c) // ← c is already a pointer, no & needed
}
}
```
#### File: `internal/middleware/device_auth.go`
**Line 38:**
```go
// BEFORE:
return func(c echo.Context) error {
// AFTER:
return func(c *echo.Context) error {
```
**Line 170:**
```go
// BEFORE:
return func(c echo.Context) error {
// AFTER:
return func(c *echo.Context) error {
```
**Line 212:**
```go
// BEFORE:
return func(c echo.Context) error {
// AFTER:
return func(c *echo.Context) error {
```
#### File: `internal/middleware/error_handler.go`
**Line 44:**
```go
// BEFORE:
func RespondWithError(c echo.Context, code int, message string, err error) error {
// AFTER:
func RespondWithError(c *echo.Context, code int, message string, err error) error {
```
**Line 69:**
```go
// BEFORE:
func RespondWithHTTPError(c echo.Context, httpErr *HTTPError) error {
// AFTER:
func RespondWithHTTPError(c *echo.Context, httpErr *HTTPError) error {
```
**Line 82:**
```go
// BEFORE:
func WrapHandler(fn func(c echo.Context) error) echo.HandlerFunc {
return func(c *echo.Context) error {
err := fn(c)
// AFTER:
func WrapHandler(fn func(*echo.Context) error) echo.HandlerFunc {
return func(c *echo.Context) error {
err := fn(c) // c is already *echo.Context
```
**Lines 84, 87, 89:** No change - calls to helpers will now work with updated signatures
#### File: `internal/middleware/rate_limiter.go`
**Line 102:**
```go
// BEFORE:
return func(c echo.Context) error {
// AFTER:
return func(c *echo.Context) error {
```
#### File: `internal/middleware/request_tracing.go`
**Line 48:**
```go
// BEFORE:
return func(c echo.Context) error {
// AFTER:
return func(c *echo.Context) error {
```
**Lines 57-61:**
```go
// BEFORE:
recorder := &responseWriter{
ResponseWriter: c.Response().Writer,
}
c.Response().Writer = recorder
// AFTER:
recorder := &responseWriter{
ResponseWriter: *c.Response(), // Dereference: *echo.Response -> http.ResponseWriter
}
```
**Note:** `c.Response().Status` (line 108) should work - Status field exists in Echo v5
#### File: `internal/middleware/security.go`
**Line 14:**
```go
// BEFORE:
return func(c echo.Context) error {
// AFTER:
return func(c *echo.Context) error {
```
---
## WebSocket Fix
After Echo v5 migration, the WebSocket handler should now work natively:
### File: `internal/handlers/websocket.go`
The existing code should now work:
```go
ws, err := upgrader.Upgrade(c.Response(), c.Request(), nil)
```
This previously failed with "response does not implement http.Hijacker" but Echo v5's Response now supports the `rwUnwrapper` interface needed for WebSocket upgrades.
---
## Verification
After making all changes:
1. **Build the project:**
```bash
go build ./cmd/server
```
2. **Run tests:**
```bash
go test ./cmd/server/tests/... -v
```
3. **Test WebSocket manually:**
- Get JWT token: `curl -X POST http://localhost:8765/api/auth/login -H "Content-Type: application/json" -d '{"login":"testuser@tests.bookhoard.internal","password":"Test@Pass123!"}' | jq -r '.access_token'`
- Connect in browser console: `new WebSocket('ws://localhost:8765/ws/sync?token=YOUR_TOKEN')`
---
## Rollback Plan
If Echo v5 migration fails:
1. Revert go.mod changes:
```go
// Change back to v4:
github.com/labstack/echo/v4 v4.15.1
github.com/labstack/echo-jwt/v4 v4.4.0
```
2. Restore import statements in all modified files
3. Revert all code changes
---
## References
- [Echo v5 Changelog](https://github.com/labstack/echo/blob/master/CHANGELOG.md)
- [Echo v5 Middleware Documentation](https://echo.labstack.com/docs/middleware)
- [Echo WebSocket Cookbook](https://echo.labstack.com/docs/cookbook/websocket)