Skip to main content

Daffi is fast, simple and lightweight library for inter process communication

Project description

Daffi

test and validate publish docs coverage License: MIT Code style: black Linux macOS Downloads

Daffi facilitates remote computing and enables remote procedure calls between multiple endpoints. It supports many-to-many relationships between endpoints, allowing for seamless communication between distributed systems. The library abstracts the complexities of remote computing and provides a user-friendly interface for initiating and managing remote procedure calls. It also offers various features such as fault tolerance, load balancing, streaming and security, to ensure reliable and secure communication between endpoints.

Daffi comprises three primary classes:

  • Global - Initialization entrypoint. Once Global object is initialized application can respond on remote requests and trigger remote callbacks itself.
  • Callback - Represents a collection of methods encapsulated in a class inherited from Callback or a standalone function decorated with the callback decorator. These functions/methods can be triggered from another process.
  • Fetcher - Represents a collection of methods encapsulated in a class inherited from Fetcher or a standalone function decorated with the fetcher decorator. These functions/methods serve as triggers for the corresponding callbacks defined in another process.

Documentation

View full documentation at: https://600apples.github.io/dafi/

Basic example

You need to create two files shopping_service.py and shopper.py

shopping_service.py - represents a set of remote callbacks that can be triggered by a client application.

shopper.py - represents shopping_service client (fetcher)

Class based approach

shopping_service.py:

import logging
from daffi import Global
from daffi.registry import Callback

logging.basicConfig(level=logging.INFO)


class ShoppingService(Callback):
    auto_init = True # class is automatically initialized, eliminating the need to manually create an object.

    def __post_init__(self):
        self.shopping_list = []

    def get_items(self):
        """Return all items that are currently present in shopping list"""
        return self.shopping_list

    def add_item(self, item):
        """Add new item to shopping list"""
        self.shopping_list.append(item)

    def clear_items(self):
        """Clear shopping list"""
        self.shopping_list.clear()


if __name__ == '__main__':
    Global(init_controller=True, host="localhost", port=8888).join()

(This script is complete, it should run "as is")

shopper.py:

import logging
from daffi import Global
from daffi.decorators import alias
from daffi.registry import Fetcher

logging.basicConfig(level=logging.INFO)


class Shopper(Fetcher):
    """
    Note: Functions without a body are treated as proxies for remote callbacks.
    All arguments provided to this function will be sent to the remote service as-is.
    """

    def get_items(self):
        """Return all items that are currently present in shopping list."""
        pass

    def add_item(self, item):
        """Add new item to shopping list."""
        pass

    def clear_items(self):
        """Clear shopping list"""
        pass

    @alias("add_item")
    def add_many_items(self, *items):
        """
        Alias for `add_item` callback.
        This function shows streaming capabilities for transferring data from one service to another.
        """
        for item in items:
            yield item


if __name__ == '__main__':
    g = Global(host="localhost", port=8888)

    shopper = Shopper()
    items = shopper.get_items()
    print(items)

    shopper.add_item("orange")
    items = shopper.get_items()
    print(items)

    shopper.add_many_items("bread", "cheese")
    items = shopper.get_items()
    print(items)

    shopper.clear_items()
    items = shopper.get_items()
    print(items)

    g.stop()

(This script is complete, it should run "as is")

To check the full example, you need to execute two scripts in separate terminals

python3 shopping_service.py

...
INFO 2023-03-27 19:49:45 | controller[0x91adb83e] | Controller has been started successfully. Process identificator: '0x91adb83e'. Connection info: tcp: [ host '[::]', port: 8888 ]
INFO 2023-03-27 19:49:45 | node[0x91adb83e] | Node has been started successfully. Process identificator: '0x91adb83e'. Connection info: tcp: [ host '[::]', port: 8888 ]
python3 shopper.py

...
INFO 2023-03-27 19:53:15 | node[0xd7e5d488] | Node has been started successfully. Process identificator: '0xd7e5d488'. Connection info: tcp: [ host '[::]', port: 8888 ]
[]
['orange']
['orange', 'bread', 'cheese']
[]
INFO 2023-03-27 19:53:15 | node[0xd7e5d488] | Node stopped.

Decorators base approach

shopping_service.py:

import logging
from daffi import Global
from daffi.decorators import callback

logging.basicConfig(level=logging.INFO)

shopping_list = []


@callback
def get_items():
    """Return all items that are currently present in shopping list"""
    return shopping_list


@callback
def add_item(item):
    """Add new item to shopping list"""
    shopping_list.append(item)


@callback
def clear_items():
    """Clear shopping list"""
    shopping_list.clear()


if __name__ == '__main__':
    Global(init_controller=True, host="localhost", port=8888).join()

(This script is complete, it should run "as is")

shopper.py:

"""
Note: Functions without a body are treated as proxies for remote callbacks.
    All arguments provided to this function will be sent to the remote service as-is.
"""
import logging
from daffi import Global
from daffi.decorators import alias, fetcher

logging.basicConfig(level=logging.INFO)


@fetcher
def get_items():
    """Return all items that are currently present in shopping list."""
    pass


@fetcher
def add_item(item):
    """Add new item to shopping list."""
    pass


@fetcher
def clear_items():
    """Add new item to shopping list."""
    pass


@alias("add_item")
@fetcher
def add_many_items(*items):
    """
    Alias for `add_item` callback.
    This function shows streaming capabilities for transferring data from one service to another.
    """
    for item in items:
        yield item


if __name__ == '__main__':
    g = Global(host="localhost", port=8888)

    items = get_items()
    print(items)

    add_item("orange")
    items = get_items()
    print(items)

    add_many_items("bread", "cheese")
    items = get_items()
    print(items)

    clear_items()
    items = get_items()
    print(items)

    g.stop()

(This script is complete, it should run "as is")

To check the full example, you need to execute two scripts in separate terminals

python3 shopping_service.py

...
INFO 2023-03-27 20:31:27 | controller[0xbac16ef4] | Controller has been started successfully. Process identificator: '0xbac16ef4'. Connection info: tcp: [ host '[::]', port: 8888 ]
INFO 2023-03-27 20:31:27 | node[0xbac16ef4] | Node has been started successfully. Process identificator: '0xbac16ef4'. Connection info: tcp: [ host '[::]', port: 8888 ]
python3 shopper.py

...
INFO 2023-03-27 20:31:43 | node[0xb9e10444] | Node has been started successfully. Process identificator: '0xb9e10444'. Connection info: tcp: [ host '[::]', port: 8888 ]
[]
['orange']
['orange', 'bread', 'cheese']
[]
INFO 2023-03-27 20:31:44 | node[0xb9e10444] | Node stopped.

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

daffi-2.2.1.tar.gz (447.0 kB view details)

Uploaded Source

Built Distribution

daffi-2.2.1-py3-none-any.whl (74.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: daffi-2.2.1.tar.gz
  • Upload date:
  • Size: 447.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.23.1

File hashes

Hashes for daffi-2.2.1.tar.gz
Algorithm Hash digest
SHA256 106bc20da31eb6da91710f26ece0de76dc091c19ddc89635539c84088d533ff4
MD5 93ed7e0b722e093e99d82e71b68f0c01
BLAKE2b-256 dd823db855fb0e78d66a9166b01877dd0c16f4bf13d93758590a36f7b369f371

See more details on using hashes here.

File details

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

File metadata

  • Download URL: daffi-2.2.1-py3-none-any.whl
  • Upload date:
  • Size: 74.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.23.1

File hashes

Hashes for daffi-2.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d2d6855a681fd72f4755a0c75592e71c9f5fdbac40d875af0aeb0002dc6f1420
MD5 f595b271eeee76f0275732a62ac6bd43
BLAKE2b-256 7a4b43d245b8075283d8d08035e27d706a5d5d8cf3e26ad222b6570a78dc95a9

See more details on using hashes here.

Supported by

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