Skip to main content

A Python client for the Jolt in-memory messaging broker

Project description

image

PyPI version PyPI downloads

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)

{"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_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.3.1.tar.gz (7.5 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.3.1-py3-none-any.whl (8.8 kB view details)

Uploaded Python 3

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

Hashes for jolt_python_api-2.3.1.tar.gz
Algorithm Hash digest
SHA256 f142751da9b32c979b0457c0d83587ae71d07aaa4acd8e369e7a4cebbe0a52f6
MD5 7580530940a06340301c1db11081c5bb
BLAKE2b-256 c80030ec3170840a62d5b91c329d629f36f8c2f03eca8a9b6e2a54f4ac6fc202

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for jolt_python_api-2.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 41dbe8fd24aadf2ab61fffc654efc1a41d5c60c6e37b6309bab6b7f51353f962
MD5 d2c847609a2d7f166cbdf205ea36ebc5
BLAKE2b-256 d0f64c8d4b4b9d5d6380db3266f00d2ca638c5148e33f4493fb34b53372effd1

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