Skip to main content

triggr

CI PyPI Python Coverage License

Composable async trigger framework for Python.

Provides building blocks for polling loops, parallel task execution, stream-based processing, and long-running service management.

Installation

pip install triggr

Quick start

Implement Source and Worker, wire them into a trigger:

from triggr import PollingTrigger, PollingConfig, Outcome

class PendingOrderSource:
    async def retrieve(self) -> list[Order]:
        return await db.fetch_pending_orders(limit=50)

class FulfillmentWorker:
    async def complete(self, order: Order) -> Outcome:
        if await warehouse.ship(order):
            return Outcome.SUCCESS
        return Outcome.FAILED

    async def is_stale(self, order: Order) -> bool:
        return await db.is_cancelled(order.id)

config = PollingConfig(polling_interval=30.0, parallelism=4)
trigger = PollingTrigger(PendingOrderSource(), FulfillmentWorker(), config)
trigger.run()

Trigger types

Type Use when
PollingTrigger Tasks live in a store; poll on an interval
StreamTrigger Tasks arrive via an AsyncIterator
PeriodicTrigger Run a task on a fixed interval
ScheduledSource Adapt a time-ready lister into a PollingTrigger source

Managing triggers together

TriggerService registers, starts, and monitors a named collection:

from triggr import TriggerService, PollingTrigger, PeriodicTrigger, PollingConfig

config = PollingConfig(polling_interval=30.0, parallelism=4)

svc = TriggerService(expected={"orders", "inventory-sync"})
svc.register("orders", PollingTrigger(PendingOrderSource(), FulfillmentWorker(), config))
svc.register("inventory-sync", PeriodicTrigger(InventorySyncWorker(), interval=60.0))
svc.start_all()

svc.is_healthy()        # True if all triggers are healthy
svc.trigger_health()    # {"orders": True, "inventory-sync": True}
svc.close_all()

When expected is provided, start_all() raises if the registered set doesn't match exactly.

Readiness gates

Gates block work until a condition is met. Pass one to any trigger via ready_gate:

from triggr import EventGate, CompositeGate, PollingTrigger

db_gate = EventGate()
warehouse_gate = EventGate()
gate = CompositeGate(db_gate, warehouse_gate)

trigger = PollingTrigger(source, worker, config, ready_gate=gate)
trigger.run()

# From another coroutine, block until ready:
db_gate.set_not_ready()
await db.reconnect()
db_gate.set_ready()     # trigger resumes only when both gates are ready

Long-running services

RetryingService keeps a ManagedService alive with two-level retry:

from triggr import RetryingService, LONG_RUNNING

async def create_shipment_stream() -> ShipmentStreamService:
    client = await warehouse.connect()
    return ShipmentStreamService(client)

svc = RetryingService(factory=create_shipment_stream, retry_policy=LONG_RUNNING)
svc.run()

Error classification

Implement ErrorClassifier to distinguish transient from fatal errors:

from triggr import ErrorClassifier, ErrorKind

class PaymentGatewayClassifier:
    def classify(self, error: Exception) -> ErrorKind:
        if isinstance(error, GatewayTimeoutError):
            return ErrorKind.TRANSIENT
        return ErrorKind.FATAL

Pass it to any trigger or RetryingService via error_classifier.

API reference

Full module documentation is in the module docstrings. Generated API docs coming soon.

Development

Requires Nix and direnv:

direnv allow   # activates the nix shell
pytest         # runs the full test suite

Metadata

Release files for triggr 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for triggr 0.1.0
File Size Uploaded
triggr-0.1.0.tar.gz 23.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for triggr 0.1.0
File Interpreter ABI Platform
triggr-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 45.3 kB

Release files / triggr-0.1.0.tar.gz

Download URL triggr-0.1.0.tar.gz
Size 23.9 kB
Tags Source
SHA-256 checksum
How to use checksums
119e968b38f2362d5f4ce859a762d3ae07549f23d0d8c23d686345aaee314b66
BLAKE2b-256 checksum
How to use checksums
77f0790ee27825b2b91ef1a9fd9b699ac6707806deb729427b46ad5fd0cff8e1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / triggr-0.1.0-py3-none-any.whl

Download URL triggr-0.1.0-py3-none-any.whl
Size 21.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d00141b832f869d9ab0941334500da7ba16700dfe9675fe9cfe53e56ebf663b7
BLAKE2b-256 checksum
How to use checksums
4e540eca813cca4e53016ae881c66b7f04e19c476e9a09b665766ea7980cbffa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page