Skip to content

ayiskakov/turbine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Turbine

A high-performance real-time pub/sub messaging server written in Rust. Clients connect over WebSocket, authenticate with JWT, subscribe to channels, and receive messages pushed via an HTTP API.

Features

  • WebSocket pub/sub — Clients connect to /ws and use a simple JSON protocol to subscribe/unsubscribe to channels.
  • JWT authentication — HS256 tokens with per-client channel allowlists.
  • HTTP publish APIPOST /api/publish with API key authentication.
  • NATS clustering — Optional NATS broker for multi-node message forwarding.
  • Lock-free registryDashMap-backed session and channel storage for high concurrency.
  • Zero-copy fanout — Messages are serialized once and cloned as Bytes across subscribers.

Quick Start

Prerequisites

  • Rust 1.85+ (uses edition = "2024")
  • (Optional) NATS server for multi-node mode

Build & Run

# Build
cargo build

# Run the server (binds to 0.0.0.0:8080)
cargo run -p turbine-server

# Run tests
cargo test

The server starts in single-node mode if NATS is not available.

Environment Variables

Variable Default Description
NATS_URL nats://127.0.0.1:4222 NATS server connection URL
NATS_PREFIX turbine NATS subject prefix for channels

Note: JWT secret and publish API key are currently hardcoded as devsecret and devkey respectively. Replace these for production use.

Architecture

┌─────────────┐         ┌─────────────────────────────────────┐
│  WS Client  │◄──ws──►│           turbine-server             │
└─────────────┘         │  ┌─────────┐  ┌──────────────────┐  │
                        │  │ handler │  │   HTTP (publish)  │  │
┌─────────────┐         │  └────┬────┘  └────────┬─────────┘  │
│  Publisher   │──POST──►│      │                 │            │
└─────────────┘         │  ┌───▼─────────────────▼──────────┐ │
                        │  │         turbine-core            │ │
                        │  │  Engine → Registry → Fanout     │ │
                        │  └──────────────┬─────────────────┘ │
                        │                 │                    │
                        │          ┌──────▼──────┐            │
                        │          │ NATS Broker │ (optional)  │
                        │          └─────────────┘            │
                        └─────────────────────────────────────┘

Crates

Crate Description
turbine-core Engine, registry, auth, protocol. Pure logic, no I/O.
turbine-server Axum-based HTTP + WebSocket server. Thin adapter.

WebSocket Protocol

Connect to ws://host:8080/ws and exchange JSON messages.

Client → Server

All commands follow this format:

{ "id": 1, "method": "<method>", "params": { ... } }

connect — Authenticate with a JWT token

{ "id": 1, "method": "connect", "params": { "token": "<jwt>" } }

subscribe — Subscribe to a channel

{ "id": 2, "method": "subscribe", "params": { "channel": "chat:lobby" } }

unsubscribe — Unsubscribe from a channel

{ "id": 3, "method": "unsubscribe", "params": { "channel": "chat:lobby" } }

ping — Keep-alive

{ "id": 4, "method": "ping" }

Server → Client

Success response:

{ "id": 1, "result": { "connected": true } }

Error response:

{ "id": 2, "error": { "code": 403, "message": "forbidden" } }

Push message (no request ID):

{ "method": "publication", "params": { "channel": "chat:lobby", "data": { "text": "hello" } } }

Error Codes

Code Meaning
400 Bad command / bad UTF-8
401 Not authenticated
403 Channel not allowed
429 Too many subscriptions
500 Internal error

HTTP API

Health Check

GET /healthz

Returns 200 OK with body ok.

Publish

POST /api/publish
x-api-key: <api-key>
Content-Type: application/json

{
  "channel": "chat:lobby",
  "data": { "text": "hello world" }
}

Response:

{ "ok": true, "delivered": 42 }

delivered is the number of local sessions that received the message.

JWT Token Format

Tokens are signed with HS256. The payload must include:

{
  "sub": "user-123",
  "exp": 1700000000,
  "channels": ["chat:lobby", "notifications:user-123"]
}
Field Type Description
sub string Client identifier
exp number Expiration (Unix timestamp, seconds)
channels string[] Allowed channels. Empty array = unrestricted access.

Configuration Limits

Setting Default Description
Max subs per session 64 Maximum channel subscriptions
Outbound buffer size 256 MPSC channel capacity per session

Messages are silently dropped if a client's outbound buffer is full (try_send).

License

This project is currently unlicensed. Add a LICENSE file to specify terms.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages