Since I don't have direct access to your codebase, I'll provide general recommendations based on Go best practices and the architectural guidelines in your cursor rules. These suggestions focus on SSE connections, server initialization, and applicable design patterns.
For persistent SSE connections:
-
Context Management
func handleSSE(w http.ResponseWriter, r *http.Request) { // Set headers for SSE w.Header().Set("Content-Type", "text/event-stream") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") // Create a context that doesn't automatically cancel ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Handle client disconnection notify := r.Context().Done() go func() { <-notify cancel() }() // Keep-alive mechanism ticker := time.NewTicker(30 * time.Second) defer ticker.Stop() flusher, ok := w.(http.Flusher) if !ok { http.Error(w, "Streaming not supported", http.StatusInternalServerError) return } for { select { case <-ctx.Done(): return case <-ticker.C: // Send keep-alive message fmt.Fprintf(w, "event: ping\ndata: %s\n\n", time.Now().String()) flusher.Flush() case event := <-eventChannel: // Send actual event data fmt.Fprintf(w, "event: message\ndata: %s\n\n", event) flusher.Flush() } } }
-
Connection Pool Pattern
- Implement a registry for active SSE connections
- Allows graceful shutdown and broadcasting to all clients
Apply these design patterns for easier server initialization:
-
Builder Pattern
type MCPServerBuilder struct { server *MCPServer } func NewMCPServerBuilder() *MCPServerBuilder { return &MCPServerBuilder{ server: &MCPServer{ // Default values port: 8080, }, } } func (b *MCPServerBuilder) WithPort(port int) *MCPServerBuilder { b.server.port = port return b } func (b *MCPServerBuilder) WithDatabase(db *Database) *MCPServerBuilder { b.server.db = db return b } func (b *MCPServerBuilder) WithLogger(logger Logger) *MCPServerBuilder { b.server.logger = logger return b } func (b *MCPServerBuilder) Build() (*MCPServer, error) { // Validate configurations if b.server.db == nil { return nil, errors.New("database is required") } // Additional setup/initialization return b.server, nil }
-
Functional Options Pattern
type MCPServerOption func(*MCPServer) func WithPort(port int) MCPServerOption { return func(s *MCPServer) { s.port = port } } func WithLogger(logger Logger) MCPServerOption { return func(s *MCPServer) { s.logger = logger } } func NewMCPServer(options ...MCPServerOption) *MCPServer { server := &MCPServer{ // Default values port: 8080, logger: DefaultLogger{}, } // Apply all options for _, option := range options { option(server) } return server } // Usage // server := NewMCPServer(WithPort(9000), WithLogger(customLogger))
-
Dependency Injection
- Use constructor injection for dependencies
- Define interfaces at the point of use, not implementation
-
Repository Pattern Improvements
- Abstract database operations behind repository interfaces
- Use factory methods to create repositories
type UserRepositoryFactory interface { CreateRepository(ctx context.Context) (UserRepository, error) }
-
Use Context Propagation
- Ensure contexts are properly passed through all layers
- Add timeouts at appropriate boundaries
-
Circuit Breaker Pattern for External Services
type CircuitBreaker struct { failureThreshold int resetTimeout time.Duration failures int lastFailure time.Time state string // "closed", "open", "half-open" mu sync.Mutex }
-
Command Pattern for Operations
- Encapsulate operations as command objects
- Enables undo/redo, logging, and queuing
-
Implement Graceful Shutdown
func (s *Server) Start() error { // Server configuration srv := &http.Server{ Addr: fmt.Sprintf(":%d", s.port), Handler: s.router, } // Channel to listen for errors coming from the listener serverErrors := make(chan error, 1) // Start the server go func() { serverErrors <- srv.ListenAndServe() }() // Channel for listening to OS signals osSignals := make(chan os.Signal, 1) signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM) // Block until an OS signal or an error is received select { case err := <-serverErrors: return fmt.Errorf("server error: %w", err) case <-osSignals: // Graceful shutdown ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { // If shutdown times out, force close if err := srv.Close(); err != nil { return fmt.Errorf("could not stop server: %w", err) } return fmt.Errorf("could not gracefully stop server: %w", err) } } return nil }
For more specific advice, I'd need to see your actual code. Consider using agent mode to allow me to analyze your specific codebase and provide more targeted recommendations.