Skip to main content

Typed Python Kafka Manager - easy publish/listen to kafka topics embraced with strong types

Project description

Kavari

Easy, automated Kafka publish/subscribe with strong typing


This tool aims to make Kafka usage extremely simple and safe,
leveraging best practices and the power of confluent_kafka.

While using weak typing in Python may be quick and fun for rapid development, exposing any data outside your app requires a predictable and structured format. Providing a stable contract for external consumers ensures maintainability and safety.

Additionally, since modern applications are usually hosted in the cloud, there’s often a need to handle scenarios like host migration or failover. For instance:

  • Kafka may become temporarily unavailable
  • Consumers may shut down in the middle of message processing
  • Partition rebalancing may occur

These situations typically require a lot of extra code in a production-ready setup.

This small library handles those concerns for you — while also simplifying the developer experience.

📨 Publishing messages

Create a message type that defines the payload (our strongly typed message format):

class TestKafkaMessage(KafkaMessage):
    topic = "test_topic"

    def __init__(self, payload: str):
        super().__init__()
        self.payload: str = payload

    def get_partition_key(self) -> str:
        """
        The message key in the produce method is important for determining how messages are
        distributed across partitions in a Kafka topic. By using a key, all messages with the same
        key will go to the same partition and kafka will ensure the order of them. Think about it in 
        terms of aggregate ID 

        :return: str
        """
        return "1"

Then publish it to the topic simply by calling:

msg = TestKafkaMessage("test_message")
kafka_manager.publish_message(msg, lambda msg, ex: print("Message published"))

📥 Consuming messages

Define the handler class:

@kafka_message_handler(message_cls=TestKafkaMessage)
class TestKafkaMessageConsumer(KafkaMessageConsumer):

    def __init__(self):
        self.received_message: str | None = None

    def handle(self, message_data: str) -> None:
        self.received_message = message_data

Once the consumer is available via a provider (e.g. a DI container), each message will be handled in a separate thread,
which keeps Kafka background processing isolated from other parts of your app (e.g. REST API).

⚙️ Configuration

Install using:

  • pip: pip install kavari
  • Poetry: poetry add kavari

Create a kafka_manager (example below uses a DI container, but Kavari works without one as well):

from kavari import kavari_create, FibonacciRetryPolicy, KafkaManager

class Container(DeclarativeContainer):
    kafka_manager: Singleton[KafkaManager] = Singleton(
        lambda: kavari_create(
            bootstrap_servers="bootstrap_location:2973",
            group_id="unique_group_identifier",
            publishing_retry_policy=FibonacciRetryPolicy(max_attempts=10),
            logger=logger,
            auto_commit=False,
            auto_offset_reset="earliest"
        )
    )

✅ Configuration steps

  1. Configure the message consumer provider:
def consumer_provider(key: typing.Any) -> kavari.KafkaMessageConsumer:
    if key == MyFirstMessageConsumer.__class__:
        return MyFirstMessageConsumer()
  1. Start the consumer loop at application startup.
  2. Stop the consumer loop during application shutdown.

Example (FastAPI + Dependency Injector)

@asynccontextmanager
async def lifespan(app: FastAPI):
    container.logger().info("Starting background jobs...")
    container.kafka_manager().set_consumer_provider(container.resolve)
    container.kafka_manager().start_consumer_loop()
    yield
    container.logger().info("Stopping background jobs...")
    container.kafka_manager().stop_consumer_loop()

🔍 Want to contribute?

Contributions, issues and feature requests are welcome!
Feel free to check issues page.

If you love this project, leave a ⭐ on GitHub!


📃 License

This project is licensed under the Apache 2.0 License.

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

kavari-0.2.2.1.tar.gz (13.6 kB view details)

Uploaded Source

Built Distribution

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

kavari-0.2.2.1-py3-none-any.whl (16.6 kB view details)

Uploaded Python 3

File details

Details for the file kavari-0.2.2.1.tar.gz.

File metadata

  • Download URL: kavari-0.2.2.1.tar.gz
  • Upload date:
  • Size: 13.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for kavari-0.2.2.1.tar.gz
Algorithm Hash digest
SHA256 f42a384992bb09221bd73f3f36ea00f2a02d46c30c5a1fa08a10395d48ce9fe4
MD5 df796fd2df48daa7237ea7f3b8be0c4e
BLAKE2b-256 2f5afbb6bfe76f5193edd2744af369f9761cdee167685c02b14353f24d0fc046

See more details on using hashes here.

File details

Details for the file kavari-0.2.2.1-py3-none-any.whl.

File metadata

  • Download URL: kavari-0.2.2.1-py3-none-any.whl
  • Upload date:
  • Size: 16.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for kavari-0.2.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0dbce0e56458429323b78ef3aa18a2c8610f51b362247e93dc80e8b70e00d431
MD5 e7180e54451a51da7b8d467f3350780f
BLAKE2b-256 d1e92a1b2fb14898e1e37605563e2a241c482e886766e26748b976abf77af3e0

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