feat: rate limiting, shared DB instance, TCP_NODELAY fix

- Add rate limiter to TCP and HTTP servers
- Share single LSMTree between TCP and HTTP servers
- Replace unsafe cast[string]/cast[seq[byte]] with safe helpers
- Stabilize gossip UDP socket with exponential backoff
- Fix TCP_NODELAY via low-level setSockOptInt(IPPROTO_TCP)
  (asyncnet.setSockOpt(OptNoDelay) uses SOL_SOCKET and fails)
- Apply TCP_NODELAY to server and websocket sockets
This commit is contained in:
2026-05-18 19:33:40 +03:00
parent 7e6a45e6b7
commit 8afa998516
13 changed files with 240 additions and 47 deletions
+17 -3
View File
@@ -19,6 +19,7 @@ import ../protocol/wire
import ../core/websocket
import jwt as jwtlib
import ../protocol/auth
import ../protocol/ratelimit
type
HttpServer* = ref object
@@ -29,6 +30,7 @@ type
metrics*: Metrics
secretKey*: string
authManager*: AuthManager
rateLimiter*: RateLimiter
ws*: WsServer
Metrics* = ref object
@@ -38,13 +40,12 @@ type
selectCount*: int
activeConnections*: int
proc newHttpServer*(config: BaraConfig): HttpServer =
let dataDir = config.dataDir / "server"
let db = newLSMTree(dataDir)
proc newHttpServerWithDb*(config: BaraConfig, db: LSMTree): HttpServer =
let ctx = newExecutionContext(db)
ctx.txnManager = newTxnManager()
let secret = config.getEffectiveJwtSecret()
let ws = newWsServer(config, secret)
let rl = newRateLimiter(rlaTokenBucket, config.rateLimitGlobal, config.rateLimitPerClient)
ctx.onChange = proc(ev: ChangeEvent) =
let msg = $ev.kind & " " & ev.table
asyncCheck ws.broadcastToTable(ev.table, msg)
@@ -52,8 +53,14 @@ proc newHttpServer*(config: BaraConfig): HttpServer =
HttpServer(config: config, running: false, db: db, ctx: ctx,
secretKey: secret,
authManager: am,
rateLimiter: rl,
metrics: Metrics(), ws: ws)
proc newHttpServer*(config: BaraConfig): HttpServer =
let dataDir = config.dataDir / "server"
let db = newLSMTree(dataDir)
return newHttpServerWithDb(config, db)
# ----------------------------------------------------------------------
# JWT helpers
# ----------------------------------------------------------------------
@@ -124,6 +131,13 @@ proc queryHandler(server: HttpServer): RequestHandler =
userId = uid
role = r
# Rate limiting
let clientKey = request.headers["X-Forwarded-For"]
let rateLimitKey = if clientKey.len > 0: clientKey else: "http-global"
if not server.rateLimiter.allowRequest(rateLimitKey):
ctx.json(%*{"error": "Rate limit exceeded"}, 429)
return
let body = parseJson(request.body)
if body == nil or "query" notin body:
ctx.json(%*{"error": "Missing 'query' in request body"}, 400)