v0.1.8 rate limiter added, improved http router, config templates added, docs updated
This commit is contained in:
@ -5,6 +5,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
@ -13,12 +15,19 @@ type HTTPRouter struct {
|
||||
service *Service
|
||||
servers map[int]*routerServer // port -> server
|
||||
mu sync.RWMutex
|
||||
|
||||
// Statistics
|
||||
startTime time.Time
|
||||
totalRequests atomic.Uint64
|
||||
routedRequests atomic.Uint64
|
||||
failedRequests atomic.Uint64
|
||||
}
|
||||
|
||||
func NewHTTPRouter(service *Service) *HTTPRouter {
|
||||
return &HTTPRouter{
|
||||
service: service,
|
||||
servers: make(map[int]*routerServer),
|
||||
service: service,
|
||||
servers: make(map[int]*routerServer),
|
||||
startTime: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,24 +43,31 @@ func (r *HTTPRouter) RegisterStream(stream *LogStream) error {
|
||||
if !exists {
|
||||
// Create new server for this port
|
||||
rs = &routerServer{
|
||||
port: port,
|
||||
routes: make(map[string]*LogStream),
|
||||
port: port,
|
||||
routes: make(map[string]*LogStream),
|
||||
router: r,
|
||||
startTime: time.Now(),
|
||||
}
|
||||
rs.server = &fasthttp.Server{
|
||||
Handler: rs.requestHandler,
|
||||
DisableKeepalive: false,
|
||||
StreamRequestBody: true,
|
||||
CloseOnShutdown: true, // Ensure connections close on shutdown
|
||||
}
|
||||
r.servers[port] = rs
|
||||
|
||||
// Start server in background
|
||||
go func() {
|
||||
addr := fmt.Sprintf(":%d", port)
|
||||
fmt.Printf("[ROUTER] Starting server on port %d\n", port)
|
||||
if err := rs.server.ListenAndServe(addr); err != nil {
|
||||
// Log error but don't crash
|
||||
fmt.Printf("Router server on port %d failed: %v\n", port, err)
|
||||
fmt.Printf("[ROUTER] Server on port %d failed: %v\n", port, err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait briefly to ensure server starts
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
r.mu.Unlock()
|
||||
|
||||
@ -71,6 +87,7 @@ func (r *HTTPRouter) RegisterStream(stream *LogStream) error {
|
||||
}
|
||||
|
||||
rs.routes[pathPrefix] = stream
|
||||
fmt.Printf("[ROUTER] Registered stream '%s' at path '%s' on port %d\n", stream.Name, pathPrefix, port)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -78,18 +95,27 @@ func (r *HTTPRouter) UnregisterStream(streamName string) {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
|
||||
for _, rs := range r.servers {
|
||||
for port, rs := range r.servers {
|
||||
rs.routeMu.Lock()
|
||||
for path, stream := range rs.routes {
|
||||
if stream.Name == streamName {
|
||||
delete(rs.routes, path)
|
||||
fmt.Printf("[ROUTER] Unregistered stream '%s' from path '%s' on port %d\n",
|
||||
streamName, path, port)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if server has no more routes
|
||||
if len(rs.routes) == 0 {
|
||||
fmt.Printf("[ROUTER] No routes left on port %d, considering shutdown\n", port)
|
||||
}
|
||||
rs.routeMu.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *HTTPRouter) Shutdown() {
|
||||
fmt.Println("[ROUTER] Starting router shutdown...")
|
||||
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
@ -98,10 +124,46 @@ func (r *HTTPRouter) Shutdown() {
|
||||
wg.Add(1)
|
||||
go func(p int, s *routerServer) {
|
||||
defer wg.Done()
|
||||
fmt.Printf("[ROUTER] Shutting down server on port %d\n", p)
|
||||
if err := s.server.Shutdown(); err != nil {
|
||||
fmt.Printf("Error shutting down router server on port %d: %v\n", p, err)
|
||||
fmt.Printf("[ROUTER] Error shutting down server on port %d: %v\n", p, err)
|
||||
}
|
||||
}(port, rs)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
fmt.Println("[ROUTER] Router shutdown complete")
|
||||
}
|
||||
|
||||
func (r *HTTPRouter) GetStats() map[string]interface{} {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
|
||||
serverStats := make(map[int]interface{})
|
||||
totalRoutes := 0
|
||||
|
||||
for port, rs := range r.servers {
|
||||
rs.routeMu.RLock()
|
||||
routes := make([]string, 0, len(rs.routes))
|
||||
for path := range rs.routes {
|
||||
routes = append(routes, path)
|
||||
totalRoutes++
|
||||
}
|
||||
rs.routeMu.RUnlock()
|
||||
|
||||
serverStats[port] = map[string]interface{}{
|
||||
"routes": routes,
|
||||
"requests": rs.requests.Load(),
|
||||
"uptime": int(time.Since(rs.startTime).Seconds()),
|
||||
}
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"uptime_seconds": int(time.Since(r.startTime).Seconds()),
|
||||
"total_requests": r.totalRequests.Load(),
|
||||
"routed_requests": r.routedRequests.Load(),
|
||||
"failed_requests": r.failedRequests.Load(),
|
||||
"servers": serverStats,
|
||||
"total_routes": totalRoutes,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user