Files
Baradb/docs/bg/protocol.md
T
dimgigov cd46edcb67
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled
Bump version to 1.1.6; fix storage bugs, tests, CI pipeline and Docker config
Storage fixes:
- Fix bloom filter hash2 OverflowDefect (uint64 instead of int Hash)
- Fix MemTable.put size calculation on overwrite (was leaking size)
- Fix fuzz_test duplicate-key issues in LSM delete and SSTable tests

Test fixes:
- Fix stress_test.nim: replace deprecated threadpool with std/threads
- Fix fuzz_test.nim: add missing imports (tables, algorithm, sets)
- Fix fuzz_test.nim: var sst for close() compatibility
- Remove unused imports from test_all.nim and bench_all.nim

Docker / CI fixes:
- Fix Dockerfile.source: invalid nimlang/nim:2.2.10-alpine tag → 2.2.10 + ubuntu:24.04 runtime
- Fix Dockerfile.source healthcheck (--spider → -qO- for 200 OK)
- Fix Dockerfile run comment ports (9470/9471 → 9912/9913)
- Fix scripts/docker-run.sh healthcheck port (9470 → 9912)
- Add ARG BUILD_DATE/VCS_REF to Dockerfile for docker-build.sh
- Update all version strings 1.1.4 → 1.1.6 across nimble/docker/source/docs
2026-05-19 12:13:33 +03:00

12 KiB
Raw Blame History

Протоколна Референция

BaraDB поддържа множество протоколи за клиентска комуникация:

  • Бинарен Wire Протокол — високопроизводителен, ниска латентност
  • HTTP/REST API — езиково-независим, лесен за дебъгване
  • WebSocket — стрийминг и pub/sub

Бинарен Wire Протокол

Бинарният протокол използва big-endian кодиране за всички многобайтови стойности.

Оптимизации на Връзката

  • TCP_NODELAY — Включен както на сървърните, така и на клиентските сокети за минимизиране на латентността при малки съобщения (заявки, acks). Това деактивира алгоритъма на Nagle, гарантирайки че пакетите се изпращат незабавно без буфериране.
  • Rate Limiting — Token-bucket rate limiter е интегриран на ниво протокол. Заявки надвишаващи лимита получават код за грешка 429.

Жизнен Цикъл на Връзката

Клиент                          Сървър
  |                               |
  |─── TCP свързване ───────────>|
  |<── TLS ръкостискане (опц.) ──|
  |─── Auth съобщение ──────────>|
  |<── Auth_OK / Грешка ─────────|
  |─── Query съобщение ─────────>|
  |<── Data / Complete / Error ──|
  |─── Close съобщение ─────────>|
  |<── TCP затваряне ────────────|

Формат на Съобщенията

Всяко съобщение започва с 12-байтов хедър:

┌─────────────┬─────────────┬─────────────┬─────────────────────┐
│  Kind        │  Length     │  RequestId  │  Payload            │
│  (4 bytes)   │  (4 bytes)  │  (4 bytes)  │                     │
│  uint32 BE   │  uint32 BE  │  uint32 BE  │  (Length bytes)     │
└─────────────┴─────────────┴─────────────┴─────────────────────┘

Типове Съобщения

Тип ID Посока Описание
Query 0x01 К→С Изпълни заявка
QueryParams 0x02 К→С Параметризирана заявка
Auth 0x07 К→С Заявка за автентикация
Ping 0x09 К→С Keepalive ping
Close 0x0A К→С Затваряне на връзка
Data 0x81 С→К Резултат от заявка
Complete 0x82 С→К Заявката е завършена
Auth_OK 0x83 С→К Успешна автентикация
Pong 0x84 С→К Keepalive отговор
Error 0x06 С→К Грешка

Query Съобщение Payload

┌───────────────────┬────────────────────────────┐
│ Query String      │                            │
│ (променлива)      │                            │
│ UTF-8             │                            │
└───────────────────┴────────────────────────────┘

Data Съобщение Payload

┌──────────────┬─────────────────────────────────────────────┐
│ Брой Колони  │ Дефиниции на Колони + Данни от Редове        │
│ (4 bytes)    │                                             │
│ uint32 BE    │                                             │
└──────────────┴─────────────────────────────────────────────┘

Типове Полета

Тип ID Размер Описание
NULL 0x00 0 NULL стойност
BOOL 0x01 1 true/false
INT8 0x02 1 Signed 8-bit integer
INT16 0x03 2 Signed 16-bit integer
INT32 0x04 4 Signed 32-bit integer
INT64 0x05 8 Signed 64-bit integer
FLOAT32 0x06 4 IEEE 754 единична точност (big-endian)
FLOAT64 0x07 8 IEEE 754 двойна точност (big-endian)
STRING 0x08 променлив UTF-8 низ (4-байтов префикс за дължина)
BYTES 0x09 променлив Сурови байтове (4-байтов префикс за дължина)
ARRAY 0x0A променлив Масив от стойности
OBJECT 0x0B променлив Ключ-стойност обект
VECTOR 0x0C променлив Float32 масив (4-байтов префикс, big-endian floats)

Error Съобщение Payload

┌──────────────┬──────────────┬────────────────────────────┐
│ Код Грешка   │ Дълж. Съобщ. │ Съобщение за Грешка        │
│ (4 bytes)    │ (4 bytes)    │ (Дълж. Съобщ. bytes)      │
│ uint32 BE    │ uint32 BE    │ UTF-8                      │
└──────────────┴──────────────┴────────────────────────────┘

HTTP/REST API

Базов URL: http://localhost:9912/api/v1 (HTTP порт = TCP порт + 440)

Rate Limiting

Всички query endpoints (/query, /batch) са защитени от token-bucket rate limiter:

  • Глобален лимит — Конфигурира се чрез BARADB_RATE_LIMIT_GLOBAL (по подразбиране: 10,000 заявки/минута)
  • Per-client лимит — Конфигурира се чрез BARADB_RATE_LIMIT_PER_CLIENT (по подразбиране: 1,000 заявки/минута)
  • Идентификация на клиент — Използва X-Forwarded-For хедър когато е зад прокси, иначе използва глобален ключ

При rate limiting, сървърът връща HTTP 429 с:

{"error": "Rate limit exceeded"}

Endpoints

Health

GET /health

Отговор:

{
  "status": "healthy",
  "version": "1.1.6",
  "uptime_seconds": 86400
}

Ready

GET /ready

Връща 200 когато е готов, 503 при стартиране.

Query

POST /query
Content-Type: application/json
Authorization: Bearer <token>

{
  "query": "SELECT name, age FROM users WHERE age > 18",
  "params": [],
  "format": "json"
}

Отговор:

{
  "columns": ["name", "age"],
  "rows": [
    ["Alice", 30],
    ["Bob", 25]
  ],
  "row_count": 2,
  "duration_ms": 12
}

Batch

POST /batch
Content-Type: application/json

{
  "queries": [
    "INSERT users { name := 'Alice', age := 30 }",
    "INSERT users { name := 'Bob', age := 25 }"
  ]
}

Отговор:

{
  "results": [
    {"status": "ok", "affected_rows": 1},
    {"status": "ok", "affected_rows": 1}
  ]
}

Schema

GET /schema

Metrics

GET /metrics

Prometheus-съвместими метрики. Виж Ръководство за Мониторинг.

Explain

POST /explain
Content-Type: application/json

{
  "query": "SELECT * FROM users WHERE age > 18"
}

Отговор:

{
  "plan": "IndexScan",
  "index": "idx_users_age",
  "estimated_rows": 42,
  "cost": 120
}

Backup

POST /backup
Content-Type: application/json

{
  "destination": "/backup/snapshot.db"
}

Административни Операции

POST /admin/compact
POST /admin/rebalance
POST /admin/check

HTTP Статус Кодове

Код Значение
200 Успех
400 Лоша заявка (синтактична грешка)
401 Неоторизиран (изисква се auth)
403 Забранен (недостатъчни права)
404 Не е намерен (таблица/тип не съществува)
429 Твърде много заявки (rate limited)
500 Вътрешна сървърна грешка
503 Услугата е недостъпна (стартира)

WebSocket Протокол

URL: ws://localhost:9913 (WebSocket порт = TCP порт + 441)

Формат на Frame

WebSocket текстови frame-ове съдържат JSON съобщения:

{
  "id": 1,
  "type": "query",
  "query": "SELECT * FROM users"
}

Типове Съобщения

Тип Посока Описание
query К→С Изпълни заявка
subscribe К→С Абониране за промени
unsubscribe К→С Отписване
ping К→С Keepalive
result С→К Резултат от заявка
notification С→К Известие за промяна
error С→К Грешка
pong С→К Keepalive отговор

Pub/Sub Пример

const ws = new WebSocket('ws://localhost:9913');

ws.onopen = () => {
  // Абониране за промени в таблица
  ws.send(JSON.stringify({
    id: 1,
    type: 'subscribe',
    table: 'users'
  }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  if (msg.type === 'notification') {
    console.log('Промяна:', msg.operation, msg.data);
  }
};

Стрийминг Заявки

ws.send(JSON.stringify({
  id: 2,
  type: 'query',
  query: 'SELECT * FROM logs ORDER BY timestamp',
  streaming: true
}));

// Сървърът изпраща множество result frame-ове
// Последният frame има {"complete": true}

Nim API Примери

Бинарен Протокол

import barabadb/protocol/wire

let msg = makeQueryMessage(1, "SELECT * FROM users")
let ready = makeReadyMessage(1)
let error = makeErrorMessage(1, 42, "Syntax error")

Connection Pool

import barabadb/protocol/pool

var pool = newConnectionPool(
  minConnections = 5,
  maxConnections = 100,
  idleTimeout = 30000
)
let conn = pool.acquire()
# Използване на връзка...
pool.release(conn)

Автентикация

import barabadb/protocol/auth

var am = newAuthManager("secret-key")
let token = am.createToken(JWTClaims(sub: "user1", role: "admin"))
let result = am.validateCredentials(
  AuthCredentials(authMethod: amToken, payload: token)
)

Rate Limiting

import barabadb/protocol/ratelimit

var rl = newRateLimiter(
  rlaTokenBucket,
  globalRate = 10000,
  perClientRate = 1000
)
if rl.allowRequest("client-123"):
  echo "Заявката е разрешена"