Skip to main content

A Multi-Transport Peer-to-Peer bidirectional RPC System and Protocol Engine

Project description

Sparrow RPC

Sparrow PRC is a language independent, lightweight Event Based Multi-Transport Peer-to-Peer bidirectional RPC System and Protocol Engine.

The purpose of Sparrow is to not just be a RPC system, but to also be a high level api for the creation of sophisticated protocols without worrying about 'bytes on the wire'.

Core Features

  • Transport Agnostic including TCP sockets, Websockets, Stdin/Stdout and Unix Domain Sockets.
  • Serialisation Agnostic. Currently supports Json, MessagePack and CBOR out of the box.
  • Fully Peer-to-Peer - both sides of any connection are equal.
  • RPC requests can flow both directions, and can be interleaved with each other.
  • RPC calls support multipart responses (ie, can return an iterable).
  • RPC calls can include remote callbacks.
  • Pub / Sub style of calls is also supported.
  • Low network overhead when paired with a compact serialisation library like MessagePack or CBOR.
  • Efficient binary data transfer even when using a serialisation library that does not support binary data.

Platforms

The Python version of Sparrow RPC runs on Python 3.8+, including PyPy and GraalPy. It also runs on MicroPython (currently only tested on the unix port of MicroPython) and under PyScript.

Status

Sparrow RPC is in heavy development and is currently ALPHA.

Most of the core features are done but expect breaking changes at this stage, and a lot of error handling is not yet in place.

Example usages

Keeping in mind that both sides can export functions, with the only difference being that one side listens for incoming connections and the other side initiates the connection, here we refer to the 'listening' side as the 'server' and the initating side as the 'client'.

Server code:

#!/usr/bin/env python3

from random import randint
from time import sleep
from typing import Iterator

from sparrowrpc import export
from sparrowrpc.engine import ProtocolEngine
from sparrowrpc.threaded import ThreadedDispatcher, ThreadedCallbackProxy
from sparrowrpc.threaded.transports import ThreadedTcpListener


@export
def hello_world(name: str = 'world'):
    return f'Hello {name}!'


@export
def demo_progress_update(data: list, progress: ThreadedCallbackProxy):
    progress.set_to_notification()
    item_count = 0
    for item in data:
        time_to_process = randint(5, 20) / 10
        sleep(time_to_process)  # do some work
        progress(message=f'Processed item {item} in {time_to_process} seconds.')
        item_count += 1
    return f'Processed {item_count} items'


@export(multipart_response=True)
def demo_multipart_response(up_to: int):
    for x in range(1, up_to + 1):
        yield (x, x**2 + 1)


@export
def demo_multipart_param(data: Iterator[int]):
    total = 0
    for x in data:
        total += x
    return total


def main():
    engine = ProtocolEngine()
    dispatcher = ThreadedDispatcher(num_threads=5)
    print('Running tcp server on 5000')
    tcp_server = ThreadedTcpListener(engine, dispatcher)
    tcp_server.run_server('0.0.0.0', 5000)
    dispatcher.shutdown()


if __name__ == '__main__':
    main()

Client side, run in the python REPL, you have:

from sparrowrpc.engine import ProtocolEngine
from sparrowrpc.threaded import ThreadedDispatcher
from sparrowrpc.threaded.transports import ThreadedTcpConnector


def show_progress(message):
    print(message)


engine = ProtocolEngine()
dispatcher = ThreadedDispatcher(num_threads=5)
connector = ThreadedTcpConnector(engine, dispatcher)
channel = connector.connect('127.0.0.1', 5000)
channel.start_channel()

result = channel.request(namespace='#sys').ping()
print(result)
# result = 'pong'

result = channel.request.hello_world()
print(result)
# result = 'Hello world!'

result = channel.request.hello_world(name='Bill')
print(result)
# result = 'Hello Bill!'

data = ['apple', 'pear', 'banana']
result = channel.request.demo_progress_update(data=data, progress=show_progress)
# displays:
# Processed item apple in 1.7 seconds.
# Processed item pear in 1.0 seconds.
# Processed item banana in 0.8 seconds.
print(result)
# result = 'Processed 3 items'

result = list()
for x in channel.request(multipart_response=True).demo_multipart_response(up_to=10):
    result.append(x)
print(result)
# result = [[1, 2], [2, 5], [3, 10], [4, 17], [5, 26], [6, 37], [7, 50], [8, 65], [9, 82], [10, 101]]

print('Iterable param (IterableCallback) - Pull')
iter_data = iter([1, 10, 30, 3])
result = channel.request.demo_multipart_param(data=iter_data)
print(result)
# result = 44

channel.shutdown_channel()
dispatcher.shutdown()

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

sparrowrpc-0.1.2.tar.gz (57.0 kB view details)

Uploaded Source

Built Distribution

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

sparrowrpc-0.1.2-py3-none-any.whl (60.9 kB view details)

Uploaded Python 3

File details

Details for the file sparrowrpc-0.1.2.tar.gz.

File metadata

  • Download URL: sparrowrpc-0.1.2.tar.gz
  • Upload date:
  • Size: 57.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for sparrowrpc-0.1.2.tar.gz
Algorithm Hash digest
SHA256 d6e9dc0c8f23c5a435f9114a6cf4a30c874cb6b4485119da886f3b87d74b36a1
MD5 7916e4d87824859da52fff47f687dd48
BLAKE2b-256 8974dcd0334ef71fb0c232e5912be76d9d598fdbcab9d9098b6a1bab07910abf

See more details on using hashes here.

File details

Details for the file sparrowrpc-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: sparrowrpc-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 60.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for sparrowrpc-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 821407c8b5c3b1fef2f084ea6d34633355a471668bbc867fdfea0aab78cc9450
MD5 98742ae615f7e16c1a439455505dbe38
BLAKE2b-256 4d48909fb7534fff20071ecba8f04f5628570baeda46b5c921592afa49c1bcb6

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