A Python client for the Jolt in-memory messaging broker
Project description
Features
✅ Native Jolt broker protocol support
✅ Thread-safe message sending
✅ Background message receiving
✅ Simple pub/sub messaging
✅ No external dependencies (standard library only)
Protocol
The Jolt broker uses NDJSON (newline-delimited JSON) over TCP:
Commands (Client → Broker)
{"op": "auth", "user": "username", "pass": "password"}
{"op": "sub", "topic": "channel.name"}
{"op": "unsub", "topic": "channel.name"}
{"op": "pub", "topic": "channel.name", "data": "message"}
{"op": "ping"}
Responses (Broker → Client)
{"ok": true}
{"ok": false, "error": "error_message"}
{"topic": "channel.name", "data": "message"}
Installation
# From source
git clone https://github.com/DevArqf/jolt-python-api.git
cd jolt-python-api
pip install -e .
Quick Start
from jolt import JoltClient, JoltConfig, JoltMessageHandler
from jolt.response import JoltErrorResponse, JoltTopicMessage
from typing import Optional
import time
# 1. Create handler
class MyHandler(JoltMessageHandler):
def on_ok(self, raw_line: str):
print("✓ OK")
def on_error(self, error: JoltErrorResponse, raw_line: str):
print(f"✗ Error: {error.get_error()}")
def on_topic_message(self, msg: JoltTopicMessage, raw_line: str):
print(f"📩 [{msg.get_topic()}] {msg.get_data()}")
def on_disconnected(self, cause: Optional[Exception]):
print(f"👋 Disconnected: {cause if cause else 'clean shutdown'}")
# 2. Configure and connect
config = JoltConfig.new_builder() \
.host("127.0.0.1") \
.port(8080) \
.build()
handler = MyHandler()
client = JoltClient(config, handler)
client.connect()
# 3. Use the client
client.subscribe("chat.general")
client.publish("chat.general", "Hello, Jolt!")
client.ping()
time.sleep(1)
client.close()
API Reference
JoltClient
Main client for interacting with the Jolt broker.
client = JoltClient(config, handler)
# Connection
client.connect()
client.close()
client.is_connected() -> bool
# Operations
client.auth(username, password)
client.subscribe(topic)
client.unsubscribe(topic)
client.publish(topic, data)
client.ping()
JoltMessageHandler
Abstract handler for broker messages. Implement all methods:
class MyHandler(JoltMessageHandler):
def on_ok(self, raw_line: str):
"""Called when broker sends {"ok": true}"""
pass
def on_error(self, error: JoltErrorResponse, raw_line: str):
"""Called when broker sends {"ok": false, "error": "..."}"""
pass
def on_topic_message(self, msg: JoltTopicMessage, raw_line: str):
"""Called when receiving a message on subscribed topic"""
pass
def on_disconnected(self, cause: Optional[Exception]):
"""Called when connection is lost"""
pass
Response Objects
# JoltOkResponse
response.is_ok() -> bool
# JoltErrorResponse
error.get_error() -> str
error.is_ok() -> bool # Always False
# JoltTopicMessage
message.get_topic() -> str
message.get_data() -> str
Examples
Simple Chat
import time
from jolt import JoltClient, JoltConfig, JoltMessageHandler
from jolt.response import JoltErrorResponse, JoltTopicMessage
from typing import Optional
class ChatHandler(JoltMessageHandler):
def on_ok(self, raw_line: str):
pass # Silent
def on_error(self, error: JoltErrorResponse, raw_line: str):
print(f"Error: {error.get_error()}")
def on_topic_message(self, msg: JoltTopicMessage, raw_line: str):
print(f"[{msg.get_topic()}] {msg.get_data()}")
def on_disconnected(self, cause: Optional[Exception]):
print("Disconnected")
# Setup
config = JoltConfig.new_builder().host("127.0.0.1").port(8080).build()
client = JoltClient(config, ChatHandler())
client.connect()
# Subscribe and chat
client.subscribe("chat.room1")
client.publish("chat.room1", "Hello everyone!")
# Keep alive
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
client.close()
Multiple Topics
topics = ["news", "sports", "weather"]
# Subscribe to all
for topic in topics:
client.subscribe(topic)
# Publish to each
client.publish("news", "Breaking: Python API released!")
client.publish("sports", "Score: 3-2")
client.publish("weather", "Sunny, 25°C")
Error Handling
class RobustHandler(JoltMessageHandler):
def on_error(self, error: JoltErrorResponse, raw_line: str):
error_msg = error.get_error()
if "auth" in error_msg.lower():
print("Authentication failed!")
elif "unknown_topic" in error_msg:
print("Topic doesn't exist!")
else:
print(f"Error: {error_msg}")
def on_disconnected(self, cause: Optional[Exception]):
if cause:
print(f"Connection lost: {cause}")
# Implement reconnection logic here
Testing
# Run unit tests (no broker required)
pytest src/tests/test_config.py -v
pytest src/tests/test_request.py -v
pytest src/tests/test_response.py -v
# Run all tests
pytest src/tests/ -v
Running the Jolt Broker
You need the actual Jolt broker to use this client:
# Get the broker
git clone https://github.com/Jolt-Database/Jolt.git
cd Jolt
# Build (requires Go)
go build -o jolt-broker
# Run
./jolt-broker -port 8080
Protocol Differences from Java API
This Python API is designed to work with the actual Jolt broker, not the jolt-java-api. Key differences:
| Feature | This API | Java API Assumption |
|---|---|---|
| Command key | "op" |
"op" |
| Subscribe | "sub" |
"subscribe" |
| Unsubscribe | "unsub" |
"unsubscribe" |
| Publish | "pub" |
"publish" |
This implementation has been tested against the actual Jolt broker and follows its protocol exactly.
Troubleshooting
Connection Refused
- Ensure broker is running:
./jolt-broker -port 8080 - Check host and port in config
- Verify no firewall blocking port 8080
No Messages Received
- Ensure you're subscribed before publishing
- Check handler's
on_topic_messageis implemented - Verify broker is relaying messages (check broker logs)
Authentication Errors
- Check if broker requires authentication
- Verify username/password are correct
- Call
client.auth()before other operations
Contributing
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new features
- Submit a pull request
License
MIT License - see LICENSE file for details
Credits
Created for use with the Jolt Database project.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jolt_python_api-2.3.1.tar.gz.
File metadata
- Download URL: jolt_python_api-2.3.1.tar.gz
- Upload date:
- Size: 7.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f142751da9b32c979b0457c0d83587ae71d07aaa4acd8e369e7a4cebbe0a52f6
|
|
| MD5 |
7580530940a06340301c1db11081c5bb
|
|
| BLAKE2b-256 |
c80030ec3170840a62d5b91c329d629f36f8c2f03eca8a9b6e2a54f4ac6fc202
|
File details
Details for the file jolt_python_api-2.3.1-py3-none-any.whl.
File metadata
- Download URL: jolt_python_api-2.3.1-py3-none-any.whl
- Upload date:
- Size: 8.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
41dbe8fd24aadf2ab61fffc654efc1a41d5c60c6e37b6309bab6b7f51353f962
|
|
| MD5 |
d2c847609a2d7f166cbdf205ea36ebc5
|
|
| BLAKE2b-256 |
d0f64c8d4b4b9d5d6380db3266f00d2ca638c5148e33f4493fb34b53372effd1
|