Skip to main content

Retry policies, backoff execution, and idempotency gates for AI execution systems

Project description

nodus-retry

Retry policies, backoff execution, and idempotency gates for AI execution systems.

Named retry policies for each execution type, sync and async execution with exponential backoff, non-retryable error classification, and an EXACTLY_ONCE idempotency gate via EffectStore. No required external dependencies — pure stdlib.

Note: nodus-retry is a required dependency of nodus-lang>=4.1.0. The EffectStore and InMemoryEffectStore are also available from nodus-lang scripts via std:effects.

Status: v0.1.0 — prepared, not yet published.


Install

pip install nodus-retry

What it provides

Component Purpose
RetryPolicy Immutable retry configuration (max_attempts, backoff, exponential, guarantee)
Named policies FLOW_NODE_DEFAULT, AGENT_LOW_MEDIUM, AGENT_HIGH_RISK, ASYNC_JOB_DEFAULT, NODUS_SCHEDULED_DEFAULT, NO_RETRY
resolve_retry_policy Look up policy by execution_type + risk_level string
execute_with_retry Run a sync callable under a RetryPolicy
execute_with_retry_async Run an async callable under a RetryPolicy
is_retryable_error Classify error strings as retryable or not
InMemoryEffectStore Thread-safe EXACTLY_ONCE idempotency gate
compute_action_id SHA-256 hash of (action_type, payload, scope)

RetryPolicy

from nodus_retry import RetryPolicy

policy = RetryPolicy(
    max_attempts=3,
    backoff_ms=200,
    exponential_backoff=True,   # 200ms, 400ms, 800ms
    high_risk_immediate_fail=False,
    execution_guarantee="AT_LEAST_ONCE",  # or "EXACTLY_ONCE"
)

Named policies

from nodus_retry import (
    FLOW_NODE_DEFAULT,       # 3 attempts, 500ms exponential, AT_LEAST_ONCE
    AGENT_LOW_MEDIUM,        # 3 attempts, 200ms exponential, AT_LEAST_ONCE
    AGENT_HIGH_RISK,         # 1 attempt, high_risk_immediate_fail=True
    ASYNC_JOB_DEFAULT,       # 5 attempts, 1000ms exponential
    NODUS_SCHEDULED_DEFAULT, # 3 attempts, 300ms exponential
    NO_RETRY,                # max_attempts=1
)

Resolve by name

from nodus_retry import resolve_retry_policy

policy = resolve_retry_policy("FLOW_NODE_DEFAULT")
policy = resolve_retry_policy("AGENT_LOW_MEDIUM")

Execution

from nodus_retry import execute_with_retry, execute_with_retry_async, FLOW_NODE_DEFAULT

# Sync
result = execute_with_retry(
    lambda: call_external_api(),
    policy=FLOW_NODE_DEFAULT,
)

# Async
result = await execute_with_retry_async(
    my_async_fn,
    policy=AGENT_LOW_MEDIUM,
)

Retries on any exception unless is_retryable_error classifies the error string as non-retryable (e.g. auth errors, validation errors).


Error classification

from nodus_retry import is_retryable_error

is_retryable_error("connection timeout")    # True
is_retryable_error("rate limit exceeded")   # True
is_retryable_error("unauthorized")          # False
is_retryable_error("invalid input")         # False

EffectStore — EXACTLY_ONCE idempotency

from nodus_retry import InMemoryEffectStore, compute_action_id

store = InMemoryEffectStore()

# Compute a deterministic action ID
action_id = compute_action_id("memory.write", {"key": "k", "value": "v"}, scope="run-001")

# Check before executing
already_done, cached = store.resolve(action_id)
if already_done:
    return cached   # idempotent return

store.pending(action_id, input_hash="h")
try:
    result = do_the_work()
    store.complete(action_id, "success", result)
    return result
except Exception:
    store.complete(action_id, "failed", None)
    raise

EffectStore is a @runtime_checkable Protocol — any class with resolve, pending, and complete methods satisfies it.


Design

  • No required dependencies. Pure stdlib (hashlib, json, threading, asyncio, dataclasses).
  • nodus-lang>=4.1.0 requires this package. InMemoryEffectStore is wired into the VM as self.effect_store and exposed via std:effects.

Development

pip install -e ".[dev]"
pytest tests/ -q

License

MIT — see 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

nodus_retry-0.1.0.tar.gz (10.0 kB view details)

Uploaded Source

Built Distribution

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

nodus_retry-0.1.0-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: nodus_retry-0.1.0.tar.gz
  • Upload date:
  • Size: 10.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for nodus_retry-0.1.0.tar.gz
Algorithm Hash digest
SHA256 76ddcf6ae36d85ba177f907b0cab3252815b81d999eed5b9d63900b3d9f2cd5d
MD5 a4d7dcf46526e6fd606da178f7d8f90d
BLAKE2b-256 121741639518016b6d9cacdbc6eb17669a38a87f89995dd0580a19ba2eb13b5d

See more details on using hashes here.

File details

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

File metadata

  • Download URL: nodus_retry-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for nodus_retry-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d0aed693d13fc43c9f4d0f298a27665d895b69f24e8546f1acfea1711649e47a
MD5 82452a92c20634977733962d3e6db40e
BLAKE2b-256 6ff8710b5d330001749a1ad6fa0dd1ebac9221f168f38d40b7107362662c45a4

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