Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9de26cc
feat(protocol): implemented binary protocol
yourarj Nov 22, 2025
a3bd260
Merge pull request #1 from yourarj/core_protocol
yourarj Nov 24, 2025
4d36745
feat(chat): functional requirements of chat met
yourarj Nov 25, 2025
5cd6eab
fix(notification): user leave
yourarj Nov 25, 2025
7383dd1
feat(client): graceful shutdown
yourarj Nov 25, 2025
faaaf6b
fix(handle): tokio task abortion
yourarj Nov 25, 2025
5cd8566
feat(server): graceful shutdown
yourarj Nov 25, 2025
7aae371
feat(message): clear separation of concerns
yourarj Nov 25, 2025
859be5b
feat(test): wrote units
yourarj Nov 26, 2025
bb85d4e
feat(git-workflow): github workflow
yourarj Nov 26, 2025
f559973
fix(ci): fixed ci
yourarj Nov 26, 2025
39cd55e
Merge pull request #3 from yourarj/github-actions
yourarj Nov 26, 2025
df6e96d
fix(ci): added clippy and format
yourarj Nov 26, 2025
26e9b60
feat(test): integ and units
yourarj Nov 26, 2025
3e3a2e3
feat(ci): test, fmt and clipp for all features
yourarj Nov 26, 2025
a592221
feat(integration): removed flawed integ test
yourarj Nov 27, 2025
9c66fa8
fix(test): closing writers
yourarj Nov 27, 2025
5f821fe
fix(big-bang): the big bang release
yourarj Nov 28, 2025
bb425df
style(format): formats
yourarj Nov 28, 2025
9339cba
fix(clippy): clippy issues in integration test
yourarj Nov 28, 2025
23f47e8
Merge pull request #2 from yourarj/chat-server
yourarj Nov 28, 2025
07516c6
docs(readme): updated readme
yourarj Nov 28, 2025
860c207
docs(scope): video link added
yourarj Nov 28, 2025
afad10e
Merge pull request #4 from yourarj/demo-video
yourarj Nov 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# High-performance Rust clippy configuration
cognitive-complexity-threshold = 25
type-complexity-threshold = 600
too-many-arguments-threshold = 10
11 changes: 11 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# EditorConfig is awesome: https://editorconfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
136 changes: 136 additions & 0 deletions .github/workflows/chat-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
name: chat ci

on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]

env:
CARGO_TERM_COLOR: always
RUST_VERSION: 1.91.1

jobs:
test-chat:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.RUST_VERSION }}
components: rustfmt, clippy

- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-

- name: Check formatting
run: |
cargo fmt --all -- --check

- name: Check for clippy
run: |
cargo clippy --workspace --all-targets --all-features -- -D warnings

- name: Run all tests
run: |
cargo test --all

- name: Build the project
run: |
cargo build --workspace

- name: Verify binaries can be executed
run: |
./target/debug/chat-server --help
./target/debug/chat-client --help

- name: Start chat server
run: |
nohup cargo run --bin chat-server -- --host 127.0.0.1 --port 8080 --max-connections 100 > server.log 2>&1 &
SERVER_PID=$!

# save the server PID for cleanup in later phase
echo "SERVER_PID=$SERVER_PID" >> $GITHUB_ENV

# Wait a moment for the server to start (technically not required as it's rust 😉)
sleep 3

# Check if server is running and listening on the port
if kill -0 $SERVER_PID 2>/dev/null; then
echo "Server started successfully with PID $SERVER_PID"
if lsof -i :8080 >/dev/null 2>&1; then
echo "Server is listening on port 8080"
else
echo "Server is not listening on port 8080"
cat server.log
exit 1
fi
else
echo "Server failed to start"
cat server.log
exit 1
fi

- name: Test client connection and message sending
run: |
echo "Testing first client connection..."
{
echo "send Hello from test client"
echo "leave"
} | cargo run --bin chat-client -- --host 127.0.0.1 --port 8080 --username testuser1

echo "Testing second client connection..."
{
echo "send Hello from second client"
echo "leave"
} | cargo run --bin chat-client -- --host 127.0.0.1 --port 8080 --username testuser2

# Test 3: Test username collision detection
echo "Testing username collision..."
{
echo "send Message from duplicate user"
echo "leave"
} | cargo run --bin chat-client -- --host 127.0.0.1 --port 8080 --username testuser1 &

sleep 1
wait

echo "Everything is fine"

- name: Stop chat server
run: |
if [ ! -z "$SERVER_PID" ]; then
kill $SERVER_PID
wait $SERVER_PID 2>/dev/null || true
echo "server stopped"

echo "=== Server Logs ==="
cat server.log
echo "=== End Server Logs ==="
fi

- name: Verify no processes left running
run: |
if command -v lsof >/dev/null 2>&1; then
if lsof -i :8080 >/dev/null 2>&1; then
echo "Warning: Port 8080 still in use after server shutdown"
lsof -i :8080
exit 1
else
echo "Port 8080 is free"
fi
else
echo "lsof not available, skipping port check"
fi
14 changes: 14 additions & 0 deletions .rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# High-performance Rust formatting configuration
tab_spaces = 2
hard_tabs = false

# Code organization
reorder_imports = true
reorder_modules = true

# Performance-oriented settings
force_explicit_abi = false

# Readability
use_field_init_shorthand = true
use_try_shorthand = true
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"editor.tabSize": 2
}
27 changes: 27 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[workspace]
resolver = "3"
members = ["chat-client", "chat-core", "chat-server"]
default-members = ["chat-client", "chat-core", "chat-server"]
exclude = ["developer-tools"]

[workspace.package]
version = "0.1.0"
edition = "2024"
rust-version = "1.91.1"

[workspace.dependencies]
tokio = { version = "1", features = ["full"] }
bincode = "2"
uuid = { version = "1", features = ["v4"] }
serde = { version = "1" }
dashmap = "6"
anyhow = "1"
thiserror = "2"
tracing = "0.1"
clap = "4"
tracing-subscriber = "0.3"
bytes = "1"

# Testing and benchmarking
criterion = "0.7"
tokio-test = "0.4"
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
# Simple Chat
## 🎥 Demo Video
[Watch Demo (vimeo)](https://vimeo.com/1141420619?fl=pl&fe=sh)

## 🪶 Features
- **Protocol**: Custom binary protocol over TCP for effciency and throghput avoided json over websockets
- **Least Cloning**: efficient broadcasting, optimized for least message cloning regardless of scale
- **Least Serialization effort**: O(1) effort for message serialization regardless of amount of receivers with smart caching
- **Resource efficient**: Easy on memory and cpu
- **Graceful shutdowns**: graceful shutdowns for server and client

## 🫣 Out of Scope

- Encryption in transit
- State machines implemented at protocol levels


## Summary

Expand Down
13 changes: 13 additions & 0 deletions chat-client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "chat-client"
version.workspace = true
edition.workspace = true
rust-version.workspace = true

[dependencies]
chat-core = { path = "../chat-core" }
clap = { workspace = true, features = ["derive"] }
anyhow = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
Loading