Skip to main content

A Python client for the Jolt in-memory messaging broker

Project description

image

A fast, lightweight Python client for the Jolt in-memory messaging broker.

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)

{"cmd": "auth", "user": "username", "pass": "password"}
{"cmd": "sub", "topic": "channel.name"}
{"cmd": "unsub", "topic": "channel.name"}
{"cmd": "pub", "topic": "channel.name", "data": "message"}
{"cmd": "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 "cmd" "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_message is 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:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new features
  4. 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

jolt_python_api-2.2.1.tar.gz (7.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jolt_python_api-2.2.1-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

Details for the file jolt_python_api-2.2.1.tar.gz.

File metadata

  • Download URL: jolt_python_api-2.2.1.tar.gz
  • Upload date:
  • Size: 7.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for jolt_python_api-2.2.1.tar.gz
Algorithm Hash digest
SHA256 7fb13eeb6a3fff9effb2005200ba7f2f669472d0a52224a08dcc89d0c6d87abe
MD5 51b9f29e57fa1905ee92a663e69e1fe9
BLAKE2b-256 3e136da32b2a7d211de675b41b8cb9fabb3a617ff307745400af07cd73b72e52

See more details on using hashes here.

File details

Details for the file jolt_python_api-2.2.1-py3-none-any.whl.

File metadata

File hashes

Hashes for jolt_python_api-2.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 56a4db13b5c3ba225b06a4b41c53836b22494c2a98013f47a019a1d3a8d720ca
MD5 7d7b0085998e9b017f59dacb13a774e6
BLAKE2b-256 ae4c1be9e4896c9bfff04c0e375867fcf638d3cf3a946c04893619e9fa5645d5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page