Skip to main content

3tears-nats

Typed NATS client wrapper, subject builders, and JetStream KV bucket primitives for 3tears applications.

What this package provides

  • NatsClient -- single canonical wrapper around nats-py. Handles connect (with bounded startup-timeout + bounded runtime reconnect ceiling), graceful shutdown/drain, typed publish, kw-only subscribe with optional Pydantic validation, request/reply with timedelta timeouts, and JetStream KV bucket access.
  • Subject + Subjects -- opaque subject dataclass and factory of every canonical subject family used by 3tears applications. Replaces ad-hoc f"{namespace}.tools.call" string-concatenation across the platform.
  • NatsKvBucket -- operations against one JetStream KV bucket (get / put / delete / create / update / get_entry). Bucket name auto-prefixed by the connected client's nats_subject_namespace.
  • nats_distributed_lock -- TTL-based distributed lock primitive built on NatsKvBucket.create (put-if-absent). Atomic acquisition + background heartbeat + automatic cleanup; on holder death the TTL expires the key.
  • forward / serve_owner -- payload-agnostic owner-routed request/reply: send a request to whichever pod currently serves a key and get its reply back. A separate election mechanism decides who owns the key; this only carries the message.
  • attach_pipe / serve_pipe / open_pipe -- a payload-agnostic byte pipe to whichever pod owns a key, for reaching a process that has no inbound network path. Rendezvous rides forward; the stream then moves to its own subjects with a sequenced framing (a lost frame raises rather than being skipped) and a credit window that stops the producer reading its source when the consumer falls behind.
  • StreamTransport -- narrow Protocol used by streaming consumers; lets test fakes substitute for the live client.
  • Errors -- NatsClientError, SubscribeError, PublishError, RequestError, KvError.

Why a separate package

The wrapper is consumed by the platform services (broker, gateway, registry, channel adapters, agent SDK) and any 3tears-based application. Keeping it in 3tears-nats avoids forcing those apps to depend on a host application repo just for a NATS primitive.

Mistake-proofed API

  • Subscribe is keyword-only after self. A common production bug (nc.subscribe(subject, callback) silently treating the callback as a queue group in nats-py 2.10+) is impossible to reproduce against this wrapper.
  • Publish accepts BaseModel instances. Raw bytes go through the explicit escape hatch publish_raw.
  • Subjects are typed Subject objects, not strings. The factory owns subject formatting; callers cannot accidentally interpolate the wrong shape.
  • Default deadletter_on_failure=True. Uncaught subscribe-callback exceptions auto-republish to {ns}.deadletter.{path}.

Usage

from datetime import timedelta

from threetears.nats import NatsClient, Subjects

nc = await NatsClient.connect(
    nats_url="nats://localhost:4222",
    nats_subject_namespace="myapp",
    client_name="my-service",
)

# Typed publish
await nc.publish(
    subject=Subjects.audit_event("workspace.doc_set"),
    message=AuditEvent(...),
)

# Typed request/reply
response = await nc.request(
    subject=Subjects.tools_call(),
    message=ToolCallRequest(...),
    response_type=ToolCallResponse,
    timeout=timedelta(seconds=5),
)

# Subscribe with Pydantic validation
sub = await nc.subscribe_typed(
    subject=Subjects.audit_wildcard(),
    cb=on_audit_event,
    message_type=AuditEvent,
    queue="audit-consumer",
)

# JetStream KV
bucket = await nc.kv_bucket(name="agent_config", ttl=timedelta(hours=2))
await bucket.put(key="agent-1", value=b"config-payload")

await nc.shutdown()

Distributed locks

nats_distributed_lock is a TTL-backed lock for "only one pod should run this body" patterns (scheduled jobs, periodic ticks, exclusive resource access). It is layered on top of NatsKvBucket.create (atomic put-if-absent), with a background heartbeat that refreshes the entry while the body runs and a TTL that bounds the orphan-lock window after a pod death.

from datetime import timedelta

from threetears.nats import LockHeld, nats_distributed_lock

try:
    async with nats_distributed_lock(
        nc,
        "backup-job",
        bucket_name="scheduler-locks",     # default; override per consumer
        ttl=timedelta(seconds=60),         # KV entry TTL
        heartbeat=timedelta(seconds=20),   # heartbeat MUST be < ttl
    ):
        await run_backup()
except LockHeld:
    # another pod owns the lock; skip this run cleanly
    return

client=None is a graceful no-op that yields immediately. Single-pod dev environments without NATS work unchanged. LockHeld is distinct from KvError (transport / bucket failures); callers should treat the former as the expected "another pod is running" branch and surface the latter separately.

Enforcement

Direct from nats import / from nats.aio imports are flagged by the per-repo enforcement walker tests/enforcement/test_nats_wrapper_usage.py. Strict mode by default; exemptions require a # rationale: ... line.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

3tears_nats-0.26.1.tar.gz (237.3 kB view details)

Uploaded Source

Built Distribution

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

3tears_nats-0.26.1-py3-none-any.whl (147.3 kB view details)

Uploaded Python 3

File details

Details for the file 3tears_nats-0.26.1.tar.gz.

File metadata

  • Download URL: 3tears_nats-0.26.1.tar.gz
  • Upload date:
  • Size: 237.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for 3tears_nats-0.26.1.tar.gz
Algorithm Hash digest
SHA256 10db029285befc812fb9807ac1dfe05792ded49f895815d4cf5dab9100c08714
MD5 8622102b188902b849c8714a0c975366
BLAKE2b-256 fb32e9988d84f90675608a58e3f88be0f0c717562afe2c9f0c653876f2a1fd36

See more details on using hashes here.

Provenance

The following attestation bundles were made for 3tears_nats-0.26.1.tar.gz:

Publisher: release.yml on pacepace/3tears

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

File details

Details for the file 3tears_nats-0.26.1-py3-none-any.whl.

File metadata

  • Download URL: 3tears_nats-0.26.1-py3-none-any.whl
  • Upload date:
  • Size: 147.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for 3tears_nats-0.26.1-py3-none-any.whl
Algorithm Hash digest
SHA256 502be5675326bfd5754e30dd28928dc11fce1fb05a19f2dbb19f6797aeaaa486
MD5 25f2e50b361ec9c758d621ee141c277f
BLAKE2b-256 f3418d3a06a965736cb88f3a402e5cfc7182465583800a173f695202fe97bf9e

See more details on using hashes here.

Provenance

The following attestation bundles were made for 3tears_nats-0.26.1-py3-none-any.whl:

Publisher: release.yml on pacepace/3tears

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

Release history Release notifications | RSS feed

0.42.0

2 files

0.41.4

2 files

0.41.3

2 files

0.41.2

2 files

0.41.1

2 files

0.41.0

2 files

0.40.0

2 files

0.39.0

2 files

0.38.0

2 files

0.37.0

2 files

0.36.0

2 files

0.35.1

2 files

0.35.0

2 files

0.34.0

2 files

0.33.0

2 files

0.32.1

2 files

0.32.0

2 files

0.31.0

2 files

0.30.1

2 files

0.30.0

2 files

0.29.0

2 files

0.28.0

2 files

0.27.0

2 files

This release

0.26.1 This release

2 files

0.26.0

2 files

0.25.0

2 files

0.24.7

2 files

0.24.6

2 files

0.24.5

2 files

0.24.4

2 files

0.24.3

2 files

0.24.2

2 files

0.24.1

2 files

0.24.0

2 files

0.23.11

2 files

0.23.10

2 files

0.23.9

2 files

0.23.8

2 files

0.23.7

2 files

0.23.6

2 files

0.23.5

2 files

0.23.3

2 files

0.23.2

2 files

0.23.1

2 files

0.23.0

2 files

0.22.5

2 files

0.22.4

2 files

0.22.3

2 files

0.22.2

2 files

0.22.1

2 files

0.22.0

2 files

0.21.0

2 files

0.20.0

2 files

0.19.4

2 files

0.19.3

2 files

0.19.2

2 files

0.19.1

2 files

0.19.0

2 files

0.18.0

2 files

0.17.9

2 files

0.17.8

2 files

0.17.7

2 files

0.17.6

2 files

0.17.5

2 files

0.17.4

2 files

0.17.3

2 files

0.17.2

2 files

0.17.1

2 files

0.17.0

2 files

0.16.1

2 files

0.16.0

2 files

0.15.0

2 files

0.14.1

2 files

0.14.0

2 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