https://github.com/lishank0119/fibril
Fibril is a fast and modular WebSocket server framework for Go, with sharding, pub/sub, and full client control.
https://github.com/lishank0119/fibril
backend distributed-systems fiber fibril framework go go-websocket gofiber golang hub pubsub realtime websocket websocket-server
Last synced: 3 months ago
JSON representation
Fibril is a fast and modular WebSocket server framework for Go, with sharding, pub/sub, and full client control.
- Host: GitHub
- URL: https://github.com/lishank0119/fibril
- Owner: lishank0119
- License: mit
- Created: 2025-02-06T16:17:36.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-05-16T15:35:39.000Z (11 months ago)
- Last Synced: 2025-05-16T16:27:30.512Z (11 months ago)
- Topics: backend, distributed-systems, fiber, fibril, framework, go, go-websocket, gofiber, golang, hub, pubsub, realtime, websocket, websocket-server
- Language: Go
- Homepage:
- Size: 72.3 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://pkg.go.dev/github.com/lishank0119/fibril)
[](go.mod)
[](https://goreportcard.com/report/github.com/lishank0119/fibril)
# Fibril - A WebSocket Library for Go
[δΈζ](README.zh-TW.md)
Fibril is a Go-based WebSocket library built on top of [GoFiber](https://github.com/gofiber/fiber) that provides a
robust and efficient way to handle WebSocket connections, messaging, and subscriptions. It supports features like
message broadcasting, client management, and publishing messages to subscribed topics.
## Table of Contents
- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
- [Basic Example](#basic-example)
- [Fibril Function Examples](#fibril-function-examples)
- [Client Function Example](#client-function-example)
- [Configuration Options](#configuration-options)
- [Monitoring Topic State](#monitoring-topic-state)
- [Contributions](#contributions)
- [License](#license)
## Features
- π High-performance WebSocket server
- π Built-in Pub/Sub system
- β‘ Sharding support for better scalability
- π Client management with UUIDs
- ποΈ Custom key-value storage per client
- π§ͺ Monitoring: `ListTopics()` and `SubscriberCount(topic)` let you introspect pub/sub usage in real-time
## Installation
```bash
go get -u github.com/lishank0119/fibril
```
## Usage
### Basic Example
```go
package main
import (
"github.com/gofiber/contrib/websocket"
"github.com/gofiber/fiber/v2"
"github.com/lishank0119/fibril"
"log"
)
func main() {
app := fiber.New()
app.Use("/ws", func(c *fiber.Ctx) error {
if websocket.IsWebSocketUpgrade(c) {
return c.Next()
}
return fiber.ErrUpgradeRequired
})
f := fibril.New(
fibril.WithShardCount(4),
fibril.WithMaxMessageSize(1024),
)
f.TextMessageHandler(func(client *fibril.Client, msg string) {
log.Printf("Received message from %s: %s", client.GetUUID(), msg)
f.BroadcastText("Echo: " + msg)
})
app.Get("/ws", websocket.New(func(c *websocket.Conn) {
f.RegisterClient(c)
}))
log.Fatal(app.Listen(":3000"))
}
```
### Fibril Function Examples
### ForEachClient
Iterates over all active WebSocket clients and applies the given callback.
```go
f.ForEachClient(func(uuid string, client *fibril.Client) {
// handle each client
})
```
### ForEachClientWithContext
Iterates over all active clients and cancels early if the context is done.
```go
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
f.ForEachClientWithContext(ctx, func(uuid string, client *fibril.Client) {
// handle each client
})
````
### GetClient
Retrieves a connected WebSocket client by UUID.
```go
client, ok := f.GetClient("your-client-uuid")
if ok {
client.SendText("Hello!")
}
```
### ClientLen
The number of active WebSocket clients connected to the hub.
```go
f.ClientLen()
```
#### Publish
Publishes a message to a specific topic.
```go
err := f.Publish("server-time", []byte("2024-02-09T15:04:05Z"))
if err != nil {
log.Println("Publish error:", err)
}
```
#### SendTextToClient
Sends a text message to a specific client.
```go
err := f.SendTextToClient("client-uuid", "Hello, Client!")
if err != nil {
log.Println("Send error:", err)
}
```
#### SendBinaryToClient
Sends binary data to a specific client.
```go
err := f.SendBinaryToClient("client-uuid", []byte{0x01, 0x02, 0x03})
if err != nil {
log.Println("Send error:", err)
}
```
#### BroadcastText
Broadcasts a text message to all connected clients.
```go
f.BroadcastText("Hello, everyone!")
```
#### BroadcastBinary
Broadcasts binary data to all connected clients.
```go
f.BroadcastBinary([]byte{0x10, 0x20, 0x30})
```
#### RegisterClient
Registers a new WebSocket client.
```go
app.Get("/ws", websocket.New(func(c *websocket.Conn) {
f.RegisterClient(c)
}))
```
#### RegisterClientWithKeys
Registers a new WebSocket client with custom key-value pairs.
```go
app.Get("/ws/:id", websocket.New(func(c *websocket.Conn) {
f.RegisterClientWithKeys(c, map[any]any{"id": c.Params("id")})
}))
```
### DisconnectAll
Disconnects all connected WebSocket clients with a given close message.
```go
f.DisconnectAll("Server restarting")
```
#### DisconnectClient
Disconnects a specific client by UUID.
```go
err := f.DisconnectClient("Goodbye!", "client-uuid")
if err != nil {
log.Println("Disconnect error:", err)
}
```
#### DisconnectClientFilter
Disconnects clients based on a filter function.
```go
f.DisconnectClientFilter("Maintenance", func(c *fibril.Client) bool {
return c.GetKey("role") == "guest"
})
```
#### Available Handlers
- **ConnectHandler**: Handles client connection.
```go
f.ConnectHandler(func(client *fibril.Client) {
log.Println("Client connected:", client.GetUUID())
})
```
- **DisconnectHandler**: Handles client disconnection.
```go
f.DisconnectHandler(func(client *fibril.Client) {
log.Println("Client disconnected:", client.GetUUID())
})
```
- **ErrorHandler**: Handles errors that occur within a client connection.
```go
f.ErrorHandler(func(client *fibril.Client, err error) {
log.Println("Error for client", client.GetUUID(), ":", err)
})
```
- **TextMessageHandler**: Handles text messages.
```go
f.TextMessageHandler(func(client *fibril.Client, msg string) {
log.Println("Received text message:", msg)
})
```
- **BinaryMessageHandler**: Handles binary messages.
```go
f.BinaryMessageHandler(func(client *fibril.Client, msg []byte) {
log.Println("Received binary message:", msg)
})
```
- **PongHandler**: Handles pong responses from clients.
```go
f.PongHandler(func(client *fibril.Client) {
log.Println("Pong received from:", client.GetUUID())
})
```
### Client Function Example
#### GetUUID
Gets the unique identifier (UUID) of the client.
```go
uuid := client.GetUUID()
log.Printf("Client UUID: %s", uuid)
```
#### Subscribe
Subscribes the client to a specific topic with a handler function.
```go
client.Subscribe("topic-name", func(msg []byte) {
log.Printf("Received message for topic: %s", string(msg))
})
```
#### SendText
Sends a text message to the client.
```go
err := client.SendText("Hello, Client!")
if err != nil {
log.Println("Send error:", err)
}
```
#### SendBinary
Sends binary data to the client.
```go
err := client.SendBinary([]byte{0x01, 0x02, 0x03})
if err != nil {
log.Println("Send error:", err)
}
```
#### Disconnect
Disconnects the client with a custom message.
```go
client.Disconnect("Goodbye!")
```
#### StoreKey
Stores a custom key-value pair associated with the client.
```go
client.StoreKey("role", "admin")
```
#### DeleteKey
Deletes a custom key-value pair associated with the client.
```go
client.DeleteKey("role")
```
#### GetKey
Retrieves the value of a key associated with the client.
```go
role, ok := client.GetKey("role")
if ok {
log.Printf("Client role: %v", role)
}
```
## Configuration Options
You can customize the following options when initializing `Fibril`:
- **ShardCount**: The number of shards for managing clients (default: 16).
- **MaxMessageSize**: The maximum size of incoming messages in bytes (default: 512).
- **MessageBufferSize**: The size of the message buffer (default: 256).
- **WriteWait**: The duration to wait before closing the write connection (default: 10 seconds).
- **PongWait**: The duration to wait for a pong response from the client (default: 60 seconds).
- **PingPeriod**: The interval to send ping messages (default: 54 seconds).
### Example:
```go
f := fibril.New(
fibril.WithShardCount(20),
fibril.WithMaxMessageSize(1024),
fibril.WithMessageBufferSize(512),
fibril.WithWriteWait(15 * time.Second),
fibril.WithPongWait(30 * time.Second),
fibril.WithPingPeriod(25 * time.Second),
)
```
## Monitoring Topic State
Fibril exposes methods to monitor internal pub/sub state:
```go
fibril.ListTopics() // returns []string
fibril.SubscriberCount("X") // returns int
```
## Contributions
Feel free to contribute to the project by forking it, making improvements, or submitting bug fixes via pull requests.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.