Metadata-Version: 2.1
Name: eventiq
Version: 0.2.4
Summary: Cloud native framework for building event driven applications in Python.
Home-page: https://github.com/performancemedia/eventiq
License: Apache-2.0
Keywords: framework,asyncio,microservice,event-driven
Author: Radzim Kowalow
Author-email: radzim.kowalow@performance-media.pl
Requires-Python: >=3.9,<4.0
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Provides-Extra: cli
Provides-Extra: cloudpickle
Provides-Extra: common
Provides-Extra: commons
Provides-Extra: default
Provides-Extra: fastapi
Provides-Extra: kafka
Provides-Extra: nats
Provides-Extra: opentelemetry
Provides-Extra: orjson
Provides-Extra: ormsgpack
Provides-Extra: prometheus
Provides-Extra: pubsub
Provides-Extra: rabbitmq
Provides-Extra: redis
Provides-Extra: watch
Provides-Extra: yaml
Requires-Dist: aio-pika (>=9.0.4) ; extra == "rabbitmq"
Requires-Dist: aiokafka (>=0.8,<1.0) ; extra == "kafka"
Requires-Dist: anyio (>4.0,<5.0)
Requires-Dist: cloudpickle (>=3.0.0,<4.0.0) ; extra == "cloudpickle"
Requires-Dist: fastapi ; extra == "fastapi"
Requires-Dist: gcloud-aio-pubsub (>=5.2.0,<7.0) ; extra == "pubsub"
Requires-Dist: nats-py (>=2.2,<3.0) ; extra == "nats"
Requires-Dist: opentelemetry-api (>=1.0,<2.0) ; extra == "default" or extra == "opentelemetry"
Requires-Dist: opentelemetry-sdk (>=1.0,<2.0) ; extra == "default" or extra == "opentelemetry"
Requires-Dist: opentelemetry-semantic-conventions (<1.0) ; extra == "default" or extra == "opentelemetry"
Requires-Dist: orjson (>=3.9.10,<4.0.0) ; extra == "common" or extra == "commons" or extra == "default" or extra == "orjson"
Requires-Dist: ormsgpack (>=1.2.5,<2.0) ; extra == "ormsgpack"
Requires-Dist: prometheus-client (>=0.17.0,<1.0) ; extra == "common" or extra == "commons" or extra == "default" or extra == "prometheus"
Requires-Dist: pydantic (>=2.0)
Requires-Dist: pydantic-settings (>=2.0.3,<3.0.0)
Requires-Dist: pyyaml (>=6.0.1,<7.0.0) ; extra == "yaml"
Requires-Dist: redis (>=5.0,<6.0) ; extra == "redis"
Requires-Dist: typer (>=0.9.0,<0.10.0) ; extra == "common" or extra == "commons" or extra == "default" or extra == "cli"
Requires-Dist: watchfiles (>=0.21.0,<0.22.0) ; extra == "watch"
Project-URL: Documentation, https://performancemedia.github.io/eventiq/
Project-URL: Repository, https://github.com/performancemedia/eventiq
Description-Content-Type: text/markdown

<p align="center">
<img src="https://performancemedia.github.io/eventiq/assets/logo.svg" style="width: 250px">

</p>
<p align="center">
<em>Cloud native framework for building event driven applications in Python</em>
</p>

![Tests](https://github.com/performancemedia/eventiq/workflows/Test/badge.svg)
![Build](https://github.com/performancemedia/eventiq/workflows/Publish/badge.svg)
![License](https://img.shields.io/github/license/performancemedia/eventiq)
![Python](https://img.shields.io/pypi/pyversions/eventiq)
![Format](https://img.shields.io/pypi/format/eventiq)
![PyPi](https://img.shields.io/pypi/v/eventiq)
[![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v1.json)](https://github.com/charliermarsh/ruff)

*Note: This package is under active development and is not recommended for production use*

---
Version: 0.2.4

Documentation: https://performancemedia.github.io/eventiq/

Repository: https://github.com/performancemedia/eventiq

---
## About

The package utilizes `anyio` and `pydantic` as the only required dependencies.
For messages [Cloud Events](https://cloudevents.io/) format is used.
Service can be run as standalone processes, or included into starlette (e.g. FastAPI) applications.

## Installation

```shell
pip install eventiq
```

## Multiple broker support (in progress)

- Stub (in memory using `asyncio.Queue` for PoC, local development and testing)
- NATS (with JetStream)
- Redis Pub/Sub
- Kafka
- Rabbitmq
- Google Cloud PubSub
- And more coming

## Optional Dependencies
  - `cli` - `typer`
  - broker of choice: `nats`, `kafka`, `rabbitmq`, `redis`, `pubsub`
  - custom message serializers: `msgpack`, `orjson`
  - `prometheus` - Metric exposure via `PrometheusMiddleware`
  - `opentelemetry` - tracing support

## Motivation

Python has many "worker-queue" libraries and frameworks, such as:

- [Celery](https://docs.celeryq.dev/en/stable/getting-started/introduction.html)
- [Dramatiq](https://dramatiq.io/)
- [Huey](https://huey.readthedocs.io/en/latest/)
- [arq](https://arq-docs.helpmanual.io/)

However, those libraries don't provide a pub/sub pattern, useful for creating
event driven and loosely coupled systems. Furthermore, the majority of those libraries
do not support `asyncio`. This is why this project was born.

## Basic usage


```python
# main.py
import asyncio
from eventiq import Service, CloudEvent, Middleware
from eventiq.backends.nats.broker import JetStreamBroker


class SendMessageMiddleware(Middleware):
    async def after_broker_connect(self, broker: "Broker") -> None:
        print(f"After service start, running with {broker}")
        await asyncio.sleep(10)
        for i in range(100):
            await broker.publish("test.topic", data={"counter": i})
        print("Published event(s)")

broker = JetStreamBroker(url="nats://localhost:4222")
broker.add_middleware(SendMessageMiddleware())

service = Service(name="example-service", broker=broker)

@service.subscribe("test.topic")
async def example_run(message: CloudEvent):
    print(f"Received Message {message.id} with data: {message.data}")

```
## Running the service

```shell
eventiq run main:service
```

## Scaling

Each message is load-balanced (depending on broker) between all service instances with the same `name`.
To scale number of processes you can use containers (docker/k8s), [supervisor](http://supervisord.org/),
or web server like gunicorn.

## Features

- Modern, `asyncio` based python 3.8+ syntax
- Minimal dependencies, only `anyio` and `pydantic` are required
- Automatic message parsing based on type annotations (like FastAPI)
- Code hot-reload
- Highly scalable: each service can process hundreds of tasks concurrently,
    all messages are load balanced between all instances by default
- Resilient - at least once delivery for all messages by default
- Customizable & pluggable message encoders (json, msgpack, custom)
- Multiple broker support (Nats, Kafka, Rabbitmq, Redis, PubSub, and more coming)
- Easily extensible via Middlewares and Plugins
- Cloud Events standard as base message structure (no more python specific `*args` and `**kwargs` in messages)
- AsyncAPI documentation generation from code
- Twelve factor app approach - stdout logging, configuration through environment variables
- Out-of-the-box integration with Prometheus (metrics) and OpenTelemetry (tracing)
- Application bootstrap via `.yaml` file (see examples/configuration)

