Skip to main content

A minimal, reusable graph runtime for Python with bounded edges, fairness, and observability.

Project description

Meridian Runtime — A Minimal, Reusable Graph Runtime for Python

Owner: GhostWeasel (Lead: doubletap-dave)

CI Docs Docs Deploy

Meridian Runtime is a lightweight, framework-agnostic graph runtime for building real‑time dataflows in Python. Model your application as small, single‑responsibility nodes connected by typed edges with bounded queues. Meridian’s scheduler enforces backpressure, supports control‑plane priorities (e.g., kill switch), and emits rich observability signals by design.

Key features

  • Nodes, edges, subgraphs, scheduler — simple, composable primitives
  • Bounded edges with configurable overflow policies (block, drop, latest, coalesce)
  • Control‑plane priority for critical flows (kill switch, admin, rate‑limit signals)
  • First‑class observability (structured logs, metrics, trace hooks)
  • Small‑file, SRP/DRY‑friendly codebase (aim for ~200 lines per file)
  • uv‑native development workflow (fast, reproducible)

Use cases

  • Real‑time trading systems (market data, execution, risk)
  • Event processing pipelines and enrichment
  • Streaming ETL and log processing
  • Control planes with prioritized signals

Versioning & Deprecation Policy

Documentation

Quick start

Prereqs

  • Python 3.11+
  • uv (modern Python package manager)

Initialize environment

uv lock
uv sync
  1. Dev loop
# Lint
uv run ruff check .

# Format check
uv run black --check .

# Type-check
uv run mypy src

# Tests with coverage
uv run pytest
  1. Run an example
uv run python -m examples.hello_graph.main
  1. Try interactive notebooks
# Install notebook dependencies
uv sync --extra notebooks

# Start Jupyter
uv run jupyter lab

# Navigate to notebooks/ directory and try:
# - tutorials/01-getting-started.ipynb
# - examples/hello-graph-interactive.ipynb
  1. Project layout (M1 scaffold)
src/meridian/
  __init__.py
  core/
    __init__.py
  observability/
    __init__.py
  utils/
    __init__.py
examples/
  __init__.py
tests/
  unit/
    test_smoke.py
  integration/
    test_examples_smoke.py
pyproject.toml
ruff.toml
mypy.ini
.editorconfig
.github/workflows/ci.yml

Core Concepts

Node

  • Single‑responsibility processing unit with typed input/output ports
  • Lifecycle hooks: on_start, on_message, on_tick, on_stop
  • Emits Messages on output ports

Edge

  • Typed, bounded queue connecting node ports
  • Overflow policies: block (default), drop, latest, coalesce(fn)
  • Exposes queue depth, throughput, and backpressure metrics

Subgraph

  • Composition of nodes into a reusable unit
  • Exposes its own typed inputs/outputs
  • Validates internal wiring and contracts

Scheduler

  • Advances nodes based on readiness, priorities, and capacity
  • Drives ticks (timers/housekeeping), supports graceful shutdown
  • Prioritizes control‑plane edges/messages

Message

  • payload: Any (type tracked by PortSpec)
  • headers: {trace_id, timestamp, schema_version, content_type, ...}

PortSpec

  • name: str
  • schema/type: Python types, TypedDict, or Pydantic models (pluggable)
  • policy: overflow handling per edge (block/drop/latest/coalesce)

Observability

  • Structured logs (JSON) with correlation IDs
  • Metrics (Prometheus) for nodes/edges/scheduler
  • Optional tracing (OpenTelemetry hooks)

Minimal Example

producer.py

from meridian.core import Node, Message, MessageType, Port, PortDirection, PortSpec

class Producer(Node):
    def __init__(self, n=5):
        super().__init__(
            name="producer",
            inputs=[],
            outputs=[Port("out", PortDirection.OUTPUT, spec=PortSpec("out", int))]
        )
        self._n = n
        self._i = 0

    def on_start(self):
        self._i = 0

    def _handle_tick(self):
        if self._i < self._n:
            self.emit("out", Message(type=MessageType.DATA, payload=self._i))
            self._i += 1

consumer.py

from meridian.core import Node, Port, PortDirection, PortSpec

class Consumer(Node):
    def __init__(self):
        super().__init__(
            name="consumer",
            inputs=[Port("in", PortDirection.INPUT, spec=PortSpec("in", int))],
            outputs=[]
        )

    def _handle_message(self, port, msg):
        print(f"got: {msg.payload}")

main.py

from meridian.core import Subgraph, Scheduler, SchedulerConfig
from producer import Producer
from consumer import Consumer

g = Subgraph(name="hello_world")
g.add_node(Producer(n=3))
g.add_node(Consumer())
g.connect(("producer", "out"), ("consumer", "in"), capacity=16)

sch = Scheduler(SchedulerConfig())
sch.register(g)
sch.run()

Run:

uv run python -m examples.hello_graph.main

Patterns and Guidance

File size and modularity

  • Target ~200 lines per file. Split responsibilities into multiple nodes or utilities.
  • SRP and DRY: nodes do one thing; share common helpers in utils/.
  • Prefer small subgraphs over monolith graphs for composition and reuse.

Backpressure and overflow

  • Default policy: block (applies backpressure upstream).
  • For sporadic spikes: latest policy can drop stale data in favor of the newest.
  • For aggregations: coalesce can compress bursts (e.g., merge updates).

Priorities

  • Assign higher priority to control‑plane edges (e.g., kill switch, cancel_all).
  • Keep control messages small and fast; avoid heavy work in control nodes.

Message schemas

  • Use precise Python types or TypedDicts for ports.
  • Optionally integrate Pydantic for richer validation without coupling the runtime.

Error handling

  • Prefer local handling in nodes; escalate via dead‑letter subgraph if needed.
  • Use retries with jitter and circuit‑breaker patterns for external IO nodes.

Observability

Logs

  • JSON‑structured logs with timestamps and correlation IDs (trace_id)
  • Node lifecycle events, exceptions, tick durations

Metrics (Prometheus)

  • Node: tick latency, messages processed, errors
  • Edge: queue depth, enqueue/dequeue rate, drops, backpressure time
  • Scheduler: runnable nodes, loop latency, priority applications

Tracing (optional)

  • Hook into OpenTelemetry: annotate message paths and node spans
  • Keep tracing optional to avoid overhead where unnecessary

Dashboards and alerts

  • Track queue depths and backpressure saturation
  • Alert on sustained scheduler latency or starved nodes
  • Monitor error rates per node and dropped messages per edge

Roadmap

v1 (initial release)

  • In‑process runtime, asyncio‑friendly
  • Nodes, edges (bounded queues), subgraphs, scheduler (fair scheduling)
  • Observability: logs, metrics, basic trace hooks
  • Examples and scaffolding scripts

v1.x

  • Schema adapters (Pydantic), richer overflow policies
  • More node templates and utilities
  • Improved testing harness and fixtures

v2+

  • Multi‑process edges (shared memory/IPC)
  • Distributed graphs (brokers + codecs)
  • Visual tooling and hot‑reload for graphs

Development (with uv)

Install and sync

uv init
uv lock
uv sync

Run tests

uv run pytest

Lint and type‑check (example)

uv run ruff check .
uv run mypy src

Run an example

uv run python -m examples.hello_graph.main

Contributing

  • Keep files small (~200 lines) and responsibilities focused.
  • Include unit tests for core changes; add integration tests for subgraph behavior.
  • Update examples and docs for user‑facing features.
  • Follow SemVer and add entries to CHANGELOG for notable changes.

License

  • BSD 3-Clause (recommended) or your organization’s standard OSS license.

FAQ

See our FAQ page for answers to common questions about Meridian Runtime.


Happy building with Meridian Runtime.

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

meridian_runtime-1.1.2.tar.gz (44.3 kB view details)

Uploaded Source

Built Distribution

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

meridian_runtime-1.1.2-py3-none-any.whl (59.7 kB view details)

Uploaded Python 3

File details

Details for the file meridian_runtime-1.1.2.tar.gz.

File metadata

  • Download URL: meridian_runtime-1.1.2.tar.gz
  • Upload date:
  • Size: 44.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for meridian_runtime-1.1.2.tar.gz
Algorithm Hash digest
SHA256 eaaf1cb3be74324a314dda3d93a06a698a9374b57483e858cb5e493c09f90f98
MD5 e105506bc6bbe4892ecfc924ffa7c04d
BLAKE2b-256 8f13d17cfb3afbcfd1ec407a89ac3e07bd217c6b02a5c51f97fe7838d79a3634

See more details on using hashes here.

Provenance

The following attestation bundles were made for meridian_runtime-1.1.2.tar.gz:

Publisher: release.yml on ghostweasellabs/meridian-runtime

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file meridian_runtime-1.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for meridian_runtime-1.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 91d77033ba2edb65831b783cfaf5d4b2d609dc915ec04fa3c0b24bf1c145d43b
MD5 dd93afa3a3b84405048cd5427073eec4
BLAKE2b-256 bb95b7a2c4f2d4ba19a0ff8ab371797cd279d184347516c349536874d5afc793

See more details on using hashes here.

Provenance

The following attestation bundles were made for meridian_runtime-1.1.2-py3-none-any.whl:

Publisher: release.yml on ghostweasellabs/meridian-runtime

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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