Skip to main content

A flexible package for implementing transactional notifications

Project description

VintaSend

A flexible package for implementing transactional notifications in Python projects.

Features

  • Storing notifications in a Database: This package relies on a data store to record all the notifications that will be sent. It also keeps it's state column up to date.
  • Scheduling notifications: Storing notifications to be send in the future. The notification's context for rendering the template is only evaluated at the moment the notification is sent due to the lib's context generation registry.
  • Notification context fetched at send time: On scheduled notifications, we only get the notification context at the send time, so we always get the most up-to-date information.
  • AsyncIO Support: We have two different versions of our service, one that only supports sync backends/adapters, and the other that only supports AsyncIO backends/adapters.
  • Flexible backend: Your projects database is getting slow after you created the first milion notifications? You can migrate to a faster no-sql database with a blink of an eye without affecting how you send the notifications.
  • Flexible adapters: Your project probably will need to change how it sends notifications overtime. This package allows to change the adapter without having to change how notifications templates are rendered or how the notification themselves are stored.
  • Flexible template renderers: Wanna start managing your templates with a third party tool (so non-technical people can help maintaining them)? Or even choose a more powerful rendering engine? You can do it independetly of how you send the notifications or store them in the database.

Installation

To install vintasend you just need to run

pip install vintasend

Disclaimer: Although the VintaSend package is selfsufficient and can be used alone, you'd have to implement at lease one Backend, one Adapter, and one Template Renderer. We have a bunch of additional packages that implement these and need to be installed seprately depending on your needs. Please check Officially supported packages section.

Getting Started

To start using VintaSend you just need to import the notification service and start using it to manage your notifications.

from vintasend.services.notification_service import NotificationService, register_context
from vintasend.constants import NotificationTypes


notification_backend = MyNotificationBackend() 
notifications_service = NotificationService(
    notification_adapters=[MyAdapter(MyTemplateRenderer(), notification_backend)], 
    notification_backend=notification_backend,
)


@register_context("my_context_generator")
def my_context_generator(user_id: str):
    user = get_user_by_id(user_id)
    
    return {
        "first_name": user.first_name,
        "last_name": user.last_name,
        "joined_at": user.joined_at,
    }


notifications_service.create_notification(
    user_id=user.id,
    notification_type=NotificationTypes.EMAIL,
    title="My Notification", # this is just for auditing purposes
    body_template="my/notification/template/path.html",
    context_name="my_context_generator",
    context_kwargs={
        "user_id": user.id,
    },
    send_after=datetime.datetime.now(),
    subject_template="my/notification/subject/template/path.txt",
    preheader_template="my/notification/preheader/template/path.html",
)

Scheduled notifications

VintaSend schedules notifications by creating them on the database for sending when the send_after value has passed. The sending isn't done automatically but we have a service method called send_pending_notifications to send all pending notifications found in the database.

You need to call the send_pending_notifications service method in a cron job or a tool like Celery Beat.

Glossary

  • Notification Backend: It is a class that implements the methods necessary for VintaSend services to create, update, and retrieve Notifications from da database.
  • Notification Adapter: It is a class that implements the methods necessary for VintaSend services to send Notifications through email, SMS or even push/in-app notifications.
  • Template Renderer: It is a class that implements the methods necessary for VintaSend adapter to render the notification body.
  • Notification Context: It's the data passed to the templates to render the notification correctly. It's generated when the notification is sent, not on creation time
  • Context generator: It's a function registered with a name that, when called, generates the data necessary to render a notification.
  • Context name: The registered name of a context generator. It's stored in the notification so the context generator is called at the moment the notification will be sent.
  • Context registry: We store all registered context generators on a Singleton class, we call it context registry.

Community

VintaSend has many backend, adapter, and template renderer implementations. If you can't find something that fulfills your needs, the package has very clear interfaces you can implement and achieve the exact behavior you expect without loosing VintaSend's friendly API.

Officially supported packages

Backends

  • vintasend-django: Uses Django ORM to manage the notifications in the database.
  • vintasend-sqlalchemy: Uses SQLAlchemy to manage the notifications in the database. It supports both sync and async engines/sessions.

Adapters

Template Renderers

Advacted Usage

AsyncIO Notification Service

To use the AsyncIO Notification Service your backend and adapters must all support AsyncIO as well.

from vintasend.services.notification_service import AsyncIONotificationService, register_context
from vintasend.constants import NotificationTypes


notification_backend = MyAsyncIONotificationBackend() 
notifications_service = AsyncIONotificationService(
    notification_adapters=[MyAsyncIOAdapter(MyTemplateRenderer(), notification_backend)], 
    notification_backend=notification_backend,
)


@register_context("my_context_generator")
async def my_context_generator(user_id: str):
    user = await get_user_by_id(user_id)
    
    return {
        "first_name": user.first_name,
        "last_name": user.last_name,
        "joined_at": user.joined_at,
    }


await notifications_service.create_notification(
    user_id=user.id,
    notification_type=NotificationTypes.EMAIL,
    title="My Notification", # this is just for auditing purposes
    body_template="my/notification/template/path.html",
    context_name="my_context_generator",
    context_kwargs={
        "user_id": user.id,
    },
    send_after=datetime.datetime.now(),
    subject_template="my/notification/subject/template/path.txt",
    preheader_template="my/notification/preheader/template/path.html",
)

Using frameworks that don't use a globally-available configuration

Frameworks like FastAPI don't have a centralized configuration object that's globally accessible by default. Because of that, we need to manually pass the configuration object to the service in order to initialize VintaSend configuration.

from vintasend.services.notification_service import AsyncIONotificationService, register_context
from vintasend.constants import NotificationTypes
from fastapi import FastAPI
from pydantic_settings import BaseSettings


class Settings(BaseSettings):
    app_name: str = "Awesome API"
    admin_email: str
    items_per_user: int = 50

settings = Settings()
app = FastAPI()

notification_backend = MyAsyncIONotificationBackend() 
notifications_service = AsyncIONotificationService(
    notification_adapters=[MyAsyncIOAdapter(MyTemplateRenderer(), notification_backend)], 
    notification_backend=notification_backend,
    config=settings,
)

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

vintasend-0.1.0.tar.gz (26.3 kB view details)

Uploaded Source

Built Distribution

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

vintasend-0.1.0-py3-none-any.whl (35.7 kB view details)

Uploaded Python 3

File details

Details for the file vintasend-0.1.0.tar.gz.

File metadata

  • Download URL: vintasend-0.1.0.tar.gz
  • Upload date:
  • Size: 26.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.0 CPython/3.12.2 Darwin/24.4.0

File hashes

Hashes for vintasend-0.1.0.tar.gz
Algorithm Hash digest
SHA256 babaeeb962b3b108bdd10651ac6d95b663804f5c674dae71e55dab9e65b05238
MD5 1752fce7777dd58321442985ebc8c484
BLAKE2b-256 325b96a34e19e5e735974c805d9a2dc69c67b9441ae1367a30b803545a135300

See more details on using hashes here.

File details

Details for the file vintasend-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: vintasend-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 35.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.0 CPython/3.12.2 Darwin/24.4.0

File hashes

Hashes for vintasend-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 13e72ace2ce712177814cd395d97bdcaa2590d09b84c784bbcc958954e278225
MD5 fe2d10d6620fdddbd8b99aee5a098694
BLAKE2b-256 8e6aab3d744c0742e145b769186364385e5e0bcbcdcbccb71d4a33edce20945a

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