relier 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- relier-0.1.0/.env.example +110 -0
- relier-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +112 -0
- relier-0.1.0/.github/ISSUE_TEMPLATE/config.yml +11 -0
- relier-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +76 -0
- relier-0.1.0/.github/ISSUE_TEMPLATE/question.yml +55 -0
- relier-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +45 -0
- relier-0.1.0/.github/dependabot.yml +12 -0
- relier-0.1.0/.github/workflows/ci.yml +111 -0
- relier-0.1.0/.github/workflows/codeql.yml +30 -0
- relier-0.1.0/.github/workflows/docs.yml +42 -0
- relier-0.1.0/.github/workflows/nightly.yml +139 -0
- relier-0.1.0/.github/workflows/publish.yml +66 -0
- relier-0.1.0/.gitignore +65 -0
- relier-0.1.0/.pre-commit-config.yaml +30 -0
- relier-0.1.0/.python-version +1 -0
- relier-0.1.0/CHANGELOG.md +57 -0
- relier-0.1.0/CONTRIBUTING.md +144 -0
- relier-0.1.0/Dockerfile +47 -0
- relier-0.1.0/Dockerfile.bench +33 -0
- relier-0.1.0/LICENSE +21 -0
- relier-0.1.0/Makefile +103 -0
- relier-0.1.0/PKG-INFO +366 -0
- relier-0.1.0/README.md +341 -0
- relier-0.1.0/SECURITY.md +80 -0
- relier-0.1.0/bench/README.md +129 -0
- relier-0.1.0/bench/__init__.py +1 -0
- relier-0.1.0/bench/bench.py +1201 -0
- relier-0.1.0/bench/config.py +59 -0
- relier-0.1.0/bench/grafana/dashboards/bench-overview.json +260 -0
- relier-0.1.0/bench/grafana/provisioning/dashboards/dashboards.yml +10 -0
- relier-0.1.0/bench/grafana/provisioning/datasources/prometheus.yml +11 -0
- relier-0.1.0/bench/monitor.py +85 -0
- relier-0.1.0/bench/ollama_client.py +82 -0
- relier-0.1.0/bench/prometheus.yml +11 -0
- relier-0.1.0/bench/relier_tasks.py +140 -0
- relier-0.1.0/bench/vanilla_app.py +111 -0
- relier-0.1.0/bench/worker_app.py +16 -0
- relier-0.1.0/docker-compose.bench.yml +144 -0
- relier-0.1.0/docker-compose.prod.yml +344 -0
- relier-0.1.0/docker-compose.yml +171 -0
- relier-0.1.0/docs/api-reference.md +655 -0
- relier-0.1.0/docs/architecture.md +492 -0
- relier-0.1.0/docs/assets/images/favicon.ico +0 -0
- relier-0.1.0/docs/assets/images/logo-plain.png +0 -0
- relier-0.1.0/docs/assets/images/logo-readme.png +0 -0
- relier-0.1.0/docs/assets/images/logo.ico +0 -0
- relier-0.1.0/docs/assets/images/logo.png +0 -0
- relier-0.1.0/docs/assets/images/screenshot-1.png +0 -0
- relier-0.1.0/docs/assets/images/screenshot-2.png +0 -0
- relier-0.1.0/docs/assets/js/mermaid-init.js +22 -0
- relier-0.1.0/docs/benchmarks.md +156 -0
- relier-0.1.0/docs/celery-primer.md +183 -0
- relier-0.1.0/docs/chaos-guide.md +321 -0
- relier-0.1.0/docs/cli-reference.md +929 -0
- relier-0.1.0/docs/concepts.md +538 -0
- relier-0.1.0/docs/configuration.md +210 -0
- relier-0.1.0/docs/deployment.md +638 -0
- relier-0.1.0/docs/durability.md +466 -0
- relier-0.1.0/docs/index.md +175 -0
- relier-0.1.0/docs/integrations.md +327 -0
- relier-0.1.0/docs/landing/app.js +442 -0
- relier-0.1.0/docs/landing/index.html +757 -0
- relier-0.1.0/docs/landing/styles.css +1304 -0
- relier-0.1.0/docs/metrics.md +255 -0
- relier-0.1.0/docs/patterns.md +430 -0
- relier-0.1.0/docs/quickstart.md +213 -0
- relier-0.1.0/docs/rl.md +108 -0
- relier-0.1.0/docs/rolling-deploys.md +213 -0
- relier-0.1.0/docs/running.md +104 -0
- relier-0.1.0/docs/stylesheets/extra.css +199 -0
- relier-0.1.0/docs/troubleshooting.md +429 -0
- relier-0.1.0/man/rl.1 +271 -0
- relier-0.1.0/mkdocs.yml +109 -0
- relier-0.1.0/pyproject.toml +129 -0
- relier-0.1.0/scripts/grafana/provisioning/dashboards/dashboards.yml +9 -0
- relier-0.1.0/scripts/grafana/provisioning/datasources/prometheus.yml +9 -0
- relier-0.1.0/scripts/grafana-dashboards/relier-overview.json +306 -0
- relier-0.1.0/scripts/grafana-dashboards/slo-burnrate.json +252 -0
- relier-0.1.0/scripts/otel-collector-config.yml +48 -0
- relier-0.1.0/scripts/prometheus.yml +8 -0
- relier-0.1.0/scripts/redis/README.md +77 -0
- relier-0.1.0/scripts/redis/backup.sh +86 -0
- relier-0.1.0/scripts/redis/redis.conf +52 -0
- relier-0.1.0/scripts/redis/sentinel.conf +37 -0
- relier-0.1.0/src/relier/__init__.py +111 -0
- relier-0.1.0/src/relier/chaos/__init__.py +19 -0
- relier-0.1.0/src/relier/chaos/engine.py +49 -0
- relier-0.1.0/src/relier/chaos/load_spike.py +92 -0
- relier-0.1.0/src/relier/chaos/network.py +130 -0
- relier-0.1.0/src/relier/chaos/slow_task.py +48 -0
- relier-0.1.0/src/relier/chaos/task_corrupt.py +74 -0
- relier-0.1.0/src/relier/chaos/tasks.py +98 -0
- relier-0.1.0/src/relier/chaos/worker_kill.py +72 -0
- relier-0.1.0/src/relier/cli/__init__.py +5 -0
- relier-0.1.0/src/relier/cli/admin.py +80 -0
- relier-0.1.0/src/relier/cli/admission.py +46 -0
- relier-0.1.0/src/relier/cli/base.py +52 -0
- relier-0.1.0/src/relier/cli/chaos.py +176 -0
- relier-0.1.0/src/relier/cli/cluster.py +145 -0
- relier-0.1.0/src/relier/cli/config.py +117 -0
- relier-0.1.0/src/relier/cli/dlq.py +118 -0
- relier-0.1.0/src/relier/cli/main.py +322 -0
- relier-0.1.0/src/relier/cli/manual.py +255 -0
- relier-0.1.0/src/relier/cli/slo.py +173 -0
- relier-0.1.0/src/relier/cli/tasks.py +562 -0
- relier-0.1.0/src/relier/cli/ui/__init__.py +5 -0
- relier-0.1.0/src/relier/cli/ui/live.py +20 -0
- relier-0.1.0/src/relier/cli/ui/panels.py +39 -0
- relier-0.1.0/src/relier/cli/ui/tables.py +201 -0
- relier-0.1.0/src/relier/cli/utils.py +55 -0
- relier-0.1.0/src/relier/cli/workers.py +209 -0
- relier-0.1.0/src/relier/config.py +490 -0
- relier-0.1.0/src/relier/core/__init__.py +32 -0
- relier-0.1.0/src/relier/core/admission.py +172 -0
- relier-0.1.0/src/relier/core/checkpoint.py +333 -0
- relier-0.1.0/src/relier/core/dlq.py +315 -0
- relier-0.1.0/src/relier/core/exceptions.py +227 -0
- relier-0.1.0/src/relier/core/idempotency.py +243 -0
- relier-0.1.0/src/relier/core/keys.py +199 -0
- relier-0.1.0/src/relier/core/phoenix.py +1052 -0
- relier-0.1.0/src/relier/core/schema.py +205 -0
- relier-0.1.0/src/relier/core/shutdown.py +193 -0
- relier-0.1.0/src/relier/core/slo.py +144 -0
- relier-0.1.0/src/relier/core/timeouts.py +197 -0
- relier-0.1.0/src/relier/core/validation.py +209 -0
- relier-0.1.0/src/relier/py.typed +0 -0
- relier-0.1.0/src/relier/storage/__init__.py +13 -0
- relier-0.1.0/src/relier/storage/lua/__init__.py +5 -0
- relier-0.1.0/src/relier/storage/lua/scripts.py +140 -0
- relier-0.1.0/src/relier/storage/redis.py +335 -0
- relier-0.1.0/src/relier/tasks/__init__.py +16 -0
- relier-0.1.0/src/relier/tasks/app.py +466 -0
- relier-0.1.0/src/relier/tasks/context.py +180 -0
- relier-0.1.0/src/relier/tasks/decorator.py +1121 -0
- relier-0.1.0/src/relier/tasks/signals.py +101 -0
- relier-0.1.0/src/relier/telemetry/__init__.py +16 -0
- relier-0.1.0/src/relier/telemetry/logging.py +98 -0
- relier-0.1.0/src/relier/telemetry/metrics.py +151 -0
- relier-0.1.0/src/relier/telemetry/setup.py +82 -0
- relier-0.1.0/src/relier/telemetry/spans.py +107 -0
- relier-0.1.0/tests/__init__.py +5 -0
- relier-0.1.0/tests/conftest.py +167 -0
- relier-0.1.0/tests/integration/__init__.py +0 -0
- relier-0.1.0/tests/integration/conftest.py +157 -0
- relier-0.1.0/tests/integration/tasks.py +61 -0
- relier-0.1.0/tests/integration/test_admission_concurrency.py +65 -0
- relier-0.1.0/tests/integration/test_core_integration.py +599 -0
- relier-0.1.0/tests/integration/test_dependencies.py +12 -0
- relier-0.1.0/tests/integration/test_fencing.py +164 -0
- relier-0.1.0/tests/integration/test_idempotency_e2e.py +53 -0
- relier-0.1.0/tests/integration/test_resurrection.py +134 -0
- relier-0.1.0/tests/integration/test_resurrection_bounds.py +146 -0
- relier-0.1.0/tests/integration/test_storage.py +31 -0
- relier-0.1.0/tests/integration/test_timeout_e2e.py +22 -0
- relier-0.1.0/tests/integration/test_worker_integration.py +931 -0
- relier-0.1.0/tests/unit/conftest.py +436 -0
- relier-0.1.0/tests/unit/test_admission.py +92 -0
- relier-0.1.0/tests/unit/test_checkpoint.py +270 -0
- relier-0.1.0/tests/unit/test_coverage_gap.py +275 -0
- relier-0.1.0/tests/unit/test_dlq.py +149 -0
- relier-0.1.0/tests/unit/test_exceptions.py +38 -0
- relier-0.1.0/tests/unit/test_idempotency.py +105 -0
- relier-0.1.0/tests/unit/test_phoenix.py +505 -0
- relier-0.1.0/tests/unit/test_redis_ha.py +280 -0
- relier-0.1.0/tests/unit/test_schema.py +214 -0
- relier-0.1.0/tests/unit/test_shutdown.py +148 -0
- relier-0.1.0/tests/unit/test_slo.py +70 -0
- relier-0.1.0/tests/unit/test_tasks_app.py +308 -0
- relier-0.1.0/tests/unit/test_tasks_context.py +29 -0
- relier-0.1.0/tests/unit/test_tasks_debug.py +98 -0
- relier-0.1.0/tests/unit/test_tasks_decorator.py +418 -0
- relier-0.1.0/tests/unit/test_tasks_signals.py +74 -0
- relier-0.1.0/tests/unit/test_telemetry.py +276 -0
- relier-0.1.0/tests/unit/test_timeouts.py +67 -0
- relier-0.1.0/uv.lock +1766 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# Relier configuration — copy to `.env` and customize.
|
|
3
|
+
#
|
|
4
|
+
# Every value below maps to a `RELIER_*` environment variable consumed by
|
|
5
|
+
# `relier.config.Settings`. The defaults shown match the in-code defaults;
|
|
6
|
+
# secrets are left blank.
|
|
7
|
+
#
|
|
8
|
+
# Precedence: real env vars > .env file > built-in defaults.
|
|
9
|
+
# =============================================================================
|
|
10
|
+
|
|
11
|
+
# -----------------------------------------------------------------------------
|
|
12
|
+
# Core
|
|
13
|
+
# -----------------------------------------------------------------------------
|
|
14
|
+
# Minimum log level: DEBUG | INFO | WARNING | ERROR | CRITICAL
|
|
15
|
+
RELIER_LOG_LEVEL=INFO
|
|
16
|
+
|
|
17
|
+
# Secret used for internal signing operations. CHANGE before production.
|
|
18
|
+
RELIER_SECRET_KEY=
|
|
19
|
+
|
|
20
|
+
# -----------------------------------------------------------------------------
|
|
21
|
+
# Redis — direct connection
|
|
22
|
+
# -----------------------------------------------------------------------------
|
|
23
|
+
# Schemes: redis:// | rediss:// (TLS) | redis+unix://
|
|
24
|
+
RELIER_REDIS_URL=redis://localhost:6379/0
|
|
25
|
+
RELIER_REDIS_MAX_CONNECTIONS=20
|
|
26
|
+
RELIER_REDIS_SOCKET_TIMEOUT=5.0
|
|
27
|
+
RELIER_REDIS_CONNECT_TIMEOUT=2.0
|
|
28
|
+
# Set to 0 to disable idle-connection health checks.
|
|
29
|
+
RELIER_REDIS_HEALTH_CHECK_INTERVAL=30
|
|
30
|
+
# Password for data nodes (requirepass / masterauth). Applies to direct AND
|
|
31
|
+
# Sentinel-managed connections.
|
|
32
|
+
RELIER_REDIS_PASSWORD=
|
|
33
|
+
|
|
34
|
+
# -----------------------------------------------------------------------------
|
|
35
|
+
# Redis — Sentinel (high availability)
|
|
36
|
+
# -----------------------------------------------------------------------------
|
|
37
|
+
# When true, ignores RELIER_REDIS_URL and uses Sentinel for master discovery.
|
|
38
|
+
RELIER_REDIS_USE_SENTINEL=false
|
|
39
|
+
# Comma-separated host:port list. Required when USE_SENTINEL=true.
|
|
40
|
+
# Example: sentinel-1:26379,sentinel-2:26379,sentinel-3:26379
|
|
41
|
+
RELIER_REDIS_SENTINEL_NODES=
|
|
42
|
+
RELIER_REDIS_SENTINEL_MASTER_NAME=relier-master
|
|
43
|
+
# Sentinel's own requirepass — distinct from the data-node password above.
|
|
44
|
+
RELIER_REDIS_SENTINEL_PASSWORD=
|
|
45
|
+
|
|
46
|
+
# -----------------------------------------------------------------------------
|
|
47
|
+
# Celery integration
|
|
48
|
+
# -----------------------------------------------------------------------------
|
|
49
|
+
RELIER_CELERY_WORKER_COUNT=8
|
|
50
|
+
RELIER_CELERY_WORKER_CONCURRENCY=8
|
|
51
|
+
|
|
52
|
+
# -----------------------------------------------------------------------------
|
|
53
|
+
# Phoenix — crash detection & resurrection
|
|
54
|
+
# -----------------------------------------------------------------------------
|
|
55
|
+
# Heartbeat TTL in seconds. Worker death is detected after this expires
|
|
56
|
+
# without renewal. Lower = faster detection, more Redis writes.
|
|
57
|
+
RELIER_HEARTBEAT_TTL=10
|
|
58
|
+
# Cap on resurrection attempts before a task is quarantined to the DLQ.
|
|
59
|
+
# Set to 0 to disable resurrection entirely.
|
|
60
|
+
RELIER_MAX_RESURRECTIONS=5
|
|
61
|
+
RELIER_RESURRECTION_CHECK_INTERVAL=2
|
|
62
|
+
RELIER_RESURRECTION_REQUEUE_DELAY=0.05
|
|
63
|
+
RELIER_RESURRECTION_BATCH_SIZE=1000
|
|
64
|
+
# Backpressure: skip resurrector scan when recovery queue is at least this deep.
|
|
65
|
+
RELIER_RESURRECTION_MAX_QUEUE_DEPTH=10000
|
|
66
|
+
|
|
67
|
+
# -----------------------------------------------------------------------------
|
|
68
|
+
# Idempotency
|
|
69
|
+
# -----------------------------------------------------------------------------
|
|
70
|
+
# Default TTL for result-cache keys (seconds).
|
|
71
|
+
RELIER_IDEMPOTENCY_DEFAULT_TTL=3600
|
|
72
|
+
# In-flight lock TTL. MUST be > RELIER_HARD_TIMEOUT to prevent double execution.
|
|
73
|
+
# Recommended: hard_timeout + 10 seconds safety buffer.
|
|
74
|
+
RELIER_IDEMPOTENCY_INFLIGHT_TTL=120
|
|
75
|
+
|
|
76
|
+
# -----------------------------------------------------------------------------
|
|
77
|
+
# Checkpointing — partial-result storage
|
|
78
|
+
# -----------------------------------------------------------------------------
|
|
79
|
+
# Checkpoints <= this many bytes are stored inline in Redis.
|
|
80
|
+
RELIER_CHECKPOINT_MAX_INLINE_BYTES=262144
|
|
81
|
+
# Backend for oversized checkpoints: inline | filesystem
|
|
82
|
+
# 'inline' rejects anything above CHECKPOINT_MAX_INLINE_BYTES.
|
|
83
|
+
# 'filesystem' spills to CHECKPOINT_DIR (which MUST be shared storage
|
|
84
|
+
# accessible by every worker and the resurrector).
|
|
85
|
+
RELIER_CHECKPOINT_BACKEND=inline
|
|
86
|
+
RELIER_CHECKPOINT_DIR=/var/lib/relier/checkpoints
|
|
87
|
+
|
|
88
|
+
# -----------------------------------------------------------------------------
|
|
89
|
+
# Timeouts & graceful shutdown
|
|
90
|
+
# -----------------------------------------------------------------------------
|
|
91
|
+
# SOFT < HARD is enforced at startup.
|
|
92
|
+
RELIER_SOFT_TIMEOUT=25
|
|
93
|
+
RELIER_HARD_TIMEOUT=30
|
|
94
|
+
RELIER_GRACEFUL_SHUTDOWN_TIMEOUT=30
|
|
95
|
+
|
|
96
|
+
# -----------------------------------------------------------------------------
|
|
97
|
+
# Admission control
|
|
98
|
+
# -----------------------------------------------------------------------------
|
|
99
|
+
# Max dispatches per ADMISSION_WINDOW seconds. Excess returns HTTP 429-able
|
|
100
|
+
# AdmissionRejectedError with Retry-After.
|
|
101
|
+
RELIER_ADMISSION_LIMIT=5000
|
|
102
|
+
RELIER_ADMISSION_WINDOW=10
|
|
103
|
+
|
|
104
|
+
# -----------------------------------------------------------------------------
|
|
105
|
+
# OpenTelemetry
|
|
106
|
+
# -----------------------------------------------------------------------------
|
|
107
|
+
# When false (default), no-op providers are used; nothing is exported.
|
|
108
|
+
RELIER_OTEL_ENABLED=false
|
|
109
|
+
# OTLP gRPC collector endpoint. Example: http://otel-collector:4317
|
|
110
|
+
RELIER_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: Something isn't working as documented or expected
|
|
3
|
+
labels: ["bug", "needs-triage"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for taking the time to report a bug. Please fill in as much detail as you can, reproduction steps and env info cut resolution time significantly.
|
|
9
|
+
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: what-happened
|
|
12
|
+
attributes:
|
|
13
|
+
label: What happened?
|
|
14
|
+
description: A clear description of the bug. What did you expect? What actually happened?
|
|
15
|
+
placeholder: |
|
|
16
|
+
I called `task.apush(...)` and expected the Phoenix resurrector to re-queue it
|
|
17
|
+
within ~8s after SIGKILL, but after 60s the task still had not reappeared.
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
|
|
21
|
+
- type: textarea
|
|
22
|
+
id: reproduction
|
|
23
|
+
attributes:
|
|
24
|
+
label: Minimal reproduction
|
|
25
|
+
description: The smallest code snippet or `docker compose` setup that reliably triggers the bug.
|
|
26
|
+
render: python
|
|
27
|
+
placeholder: |
|
|
28
|
+
from relier.tasks.decorator import rl_task
|
|
29
|
+
|
|
30
|
+
@rl_task(hard_timeout=10)
|
|
31
|
+
async def my_task(x: str) -> str:
|
|
32
|
+
return x
|
|
33
|
+
|
|
34
|
+
# Steps to trigger the bug:
|
|
35
|
+
# 1. ...
|
|
36
|
+
validations:
|
|
37
|
+
required: true
|
|
38
|
+
|
|
39
|
+
- type: textarea
|
|
40
|
+
id: error-output
|
|
41
|
+
attributes:
|
|
42
|
+
label: Error output / logs
|
|
43
|
+
description: Paste the full traceback, structured logs, or `rl tasks inflight` output if available.
|
|
44
|
+
render: text
|
|
45
|
+
|
|
46
|
+
- type: dropdown
|
|
47
|
+
id: component
|
|
48
|
+
attributes:
|
|
49
|
+
label: Which component is affected?
|
|
50
|
+
multiple: true
|
|
51
|
+
options:
|
|
52
|
+
- Phoenix resurrector
|
|
53
|
+
- Idempotency
|
|
54
|
+
- Admission control
|
|
55
|
+
- Dead Letter Queue (DLQ)
|
|
56
|
+
- Graceful shutdown
|
|
57
|
+
- Timeouts (soft / hard)
|
|
58
|
+
- Checkpointing
|
|
59
|
+
- Schema versioning
|
|
60
|
+
- CLI (rl)
|
|
61
|
+
- OpenTelemetry / metrics
|
|
62
|
+
- Redis HA / Sentinel
|
|
63
|
+
- Config / settings
|
|
64
|
+
- Other
|
|
65
|
+
|
|
66
|
+
- type: input
|
|
67
|
+
id: relier-version
|
|
68
|
+
attributes:
|
|
69
|
+
label: Relier version
|
|
70
|
+
placeholder: "0.1.0"
|
|
71
|
+
validations:
|
|
72
|
+
required: true
|
|
73
|
+
|
|
74
|
+
- type: input
|
|
75
|
+
id: python-version
|
|
76
|
+
attributes:
|
|
77
|
+
label: Python version
|
|
78
|
+
placeholder: "3.11.9"
|
|
79
|
+
validations:
|
|
80
|
+
required: true
|
|
81
|
+
|
|
82
|
+
- type: input
|
|
83
|
+
id: redis-version
|
|
84
|
+
attributes:
|
|
85
|
+
label: Redis version and config
|
|
86
|
+
description: Version + AOF status (redis-cli INFO server | grep redis_version; redis-cli CONFIG GET appendonly)
|
|
87
|
+
placeholder: "Redis 7.2.4, AOF=yes, maxmemory-policy=noeviction"
|
|
88
|
+
validations:
|
|
89
|
+
required: true
|
|
90
|
+
|
|
91
|
+
- type: input
|
|
92
|
+
id: celery-version
|
|
93
|
+
attributes:
|
|
94
|
+
label: Celery version
|
|
95
|
+
placeholder: "5.3.6"
|
|
96
|
+
|
|
97
|
+
- type: dropdown
|
|
98
|
+
id: deployment
|
|
99
|
+
attributes:
|
|
100
|
+
label: Deployment environment
|
|
101
|
+
options:
|
|
102
|
+
- Bare metal (direct Python processes)
|
|
103
|
+
- Docker (single node)
|
|
104
|
+
- Docker Compose
|
|
105
|
+
- Kubernetes
|
|
106
|
+
- Other
|
|
107
|
+
|
|
108
|
+
- type: textarea
|
|
109
|
+
id: additional
|
|
110
|
+
attributes:
|
|
111
|
+
label: Additional context
|
|
112
|
+
description: Anything else — rl bench output, network topology, load characteristics, etc.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Troubleshooting & FAQ
|
|
4
|
+
url: https://getrelier.github.io/relier/troubleshooting/
|
|
5
|
+
about: Most common issues and their fixes are documented here.
|
|
6
|
+
- name: Documentation
|
|
7
|
+
url: https://getrelier.github.io/relier/
|
|
8
|
+
about: Full docs — configuration, deployment, patterns, API reference.
|
|
9
|
+
- name: GitHub Discussions
|
|
10
|
+
url: https://github.com/getrelier/relier/discussions
|
|
11
|
+
about: General questions, ideas, and show-and-tell.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest a new feature or improvement to an existing one
|
|
3
|
+
labels: ["enhancement", "needs-triage"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Before opening, check [the docs](https://getrelier.github.io/relier/) and existing issues the feature may already exist or be planned. The most useful requests include a concrete use-case from a real system.
|
|
9
|
+
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: problem
|
|
12
|
+
attributes:
|
|
13
|
+
label: What problem does this solve?
|
|
14
|
+
description: Describe the specific situation where this feature would help. Concrete workload beats abstract ask every time.
|
|
15
|
+
placeholder: |
|
|
16
|
+
We dispatch ~10k tasks/minute from multiple FastAPI pods. When one pod is
|
|
17
|
+
doing a rolling deploy, admission control triggers across the cluster, we
|
|
18
|
+
need per-producer quotas, not a single global counter.
|
|
19
|
+
validations:
|
|
20
|
+
required: true
|
|
21
|
+
|
|
22
|
+
- type: textarea
|
|
23
|
+
id: proposed-solution
|
|
24
|
+
attributes:
|
|
25
|
+
label: Proposed solution
|
|
26
|
+
description: What would the API / behaviour look like? A code sketch is worth a thousand words.
|
|
27
|
+
render: python
|
|
28
|
+
placeholder: |
|
|
29
|
+
@rl_task(admission_key="producer:{producer_id}", admission_limit=1000)
|
|
30
|
+
async def process(item: str, producer_id: str) -> None:
|
|
31
|
+
...
|
|
32
|
+
|
|
33
|
+
- type: textarea
|
|
34
|
+
id: alternatives
|
|
35
|
+
attributes:
|
|
36
|
+
label: Alternatives considered
|
|
37
|
+
description: What are you doing today to work around this? What other solutions did you consider?
|
|
38
|
+
|
|
39
|
+
- type: dropdown
|
|
40
|
+
id: area
|
|
41
|
+
attributes:
|
|
42
|
+
label: Area
|
|
43
|
+
multiple: true
|
|
44
|
+
options:
|
|
45
|
+
- Phoenix resurrection
|
|
46
|
+
- Idempotency
|
|
47
|
+
- Admission control
|
|
48
|
+
- Dead Letter Queue
|
|
49
|
+
- Graceful shutdown
|
|
50
|
+
- Timeouts
|
|
51
|
+
- Checkpointing
|
|
52
|
+
- Schema versioning
|
|
53
|
+
- CLI (rl)
|
|
54
|
+
- OpenTelemetry / metrics
|
|
55
|
+
- Redis HA / Sentinel
|
|
56
|
+
- Configuration
|
|
57
|
+
- Documentation
|
|
58
|
+
- Performance
|
|
59
|
+
- New primitive (not listed)
|
|
60
|
+
|
|
61
|
+
- type: dropdown
|
|
62
|
+
id: priority
|
|
63
|
+
attributes:
|
|
64
|
+
label: How blocked are you without this?
|
|
65
|
+
options:
|
|
66
|
+
- Not blocked — nice to have
|
|
67
|
+
- Somewhat blocked — have a workaround
|
|
68
|
+
- Very blocked — can't use Relier without this
|
|
69
|
+
validations:
|
|
70
|
+
required: true
|
|
71
|
+
|
|
72
|
+
- type: textarea
|
|
73
|
+
id: additional
|
|
74
|
+
attributes:
|
|
75
|
+
label: Additional context
|
|
76
|
+
description: Relevant links, prior art (Temporal, Faust, AWS Step Functions equivalent), or architecture diagrams.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: Question / Support
|
|
2
|
+
description: Usage question, integration help, or something the docs didn't answer
|
|
3
|
+
labels: ["question"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Check the [Troubleshooting & FAQ](https://getrelier.github.io/relier/troubleshooting/) first — your question may be answered there. For quick questions, GitHub Discussions is faster than an issue.
|
|
9
|
+
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: question
|
|
12
|
+
attributes:
|
|
13
|
+
label: Your question
|
|
14
|
+
description: Be as specific as you can. What are you trying to do? What did you try?
|
|
15
|
+
placeholder: |
|
|
16
|
+
I'm integrating Relier with a Django app that uses `task.apply_async()` everywhere.
|
|
17
|
+
Should I switch all call sites to `task.push()`, or is there a compatibility shim?
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
|
|
21
|
+
- type: dropdown
|
|
22
|
+
id: area
|
|
23
|
+
attributes:
|
|
24
|
+
label: Area
|
|
25
|
+
options:
|
|
26
|
+
- Getting started / installation
|
|
27
|
+
- FastAPI integration
|
|
28
|
+
- Django integration
|
|
29
|
+
- Flask integration
|
|
30
|
+
- Configuration
|
|
31
|
+
- Phoenix resurrection
|
|
32
|
+
- Idempotency
|
|
33
|
+
- Admission control
|
|
34
|
+
- DLQ / dead letter queue
|
|
35
|
+
- Timeouts
|
|
36
|
+
- Graceful shutdown
|
|
37
|
+
- CLI (rl)
|
|
38
|
+
- Redis HA / Sentinel
|
|
39
|
+
- OpenTelemetry / metrics
|
|
40
|
+
- Performance / benchmarks
|
|
41
|
+
- Deployment
|
|
42
|
+
- Other
|
|
43
|
+
|
|
44
|
+
- type: textarea
|
|
45
|
+
id: what-tried
|
|
46
|
+
attributes:
|
|
47
|
+
label: What have you tried?
|
|
48
|
+
description: Relevant code, config, or docs sections you already looked at.
|
|
49
|
+
render: python
|
|
50
|
+
|
|
51
|
+
- type: input
|
|
52
|
+
id: relier-version
|
|
53
|
+
attributes:
|
|
54
|
+
label: Relier version
|
|
55
|
+
placeholder: "0.1.0"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
## What this PR does
|
|
2
|
+
|
|
3
|
+
<!-- One sentence: the change and its motivation. -->
|
|
4
|
+
|
|
5
|
+
## Type of change
|
|
6
|
+
|
|
7
|
+
- [ ] Bug fix
|
|
8
|
+
- [ ] New feature / primitive
|
|
9
|
+
- [ ] Performance improvement
|
|
10
|
+
- [ ] Refactor (no behaviour change)
|
|
11
|
+
- [ ] Documentation
|
|
12
|
+
- [ ] CI / tooling
|
|
13
|
+
- [ ] Dependency update
|
|
14
|
+
|
|
15
|
+
## Checklist
|
|
16
|
+
|
|
17
|
+
### Code quality
|
|
18
|
+
- [ ] `make check` passes (ruff + mypy)
|
|
19
|
+
- [ ] `pre-commit run --all-files` passes (or `make setup` to install hooks, then commit runs them automatically)
|
|
20
|
+
- [ ] No debug `print()` / `breakpoint()` left in `src/`
|
|
21
|
+
- [ ] New public API has type annotations
|
|
22
|
+
|
|
23
|
+
### Tests
|
|
24
|
+
- [ ] New or updated unit tests cover the change
|
|
25
|
+
- [ ] Integration tests cover the change (if it touches Redis, Celery, or the decorator)
|
|
26
|
+
- [ ] Coverage stays at or above 90% (`make test-integration`)
|
|
27
|
+
|
|
28
|
+
### Reliability (for changes to core primitives)
|
|
29
|
+
- [ ] Considered fence-token correctness (stale worker cannot commit after resurrection)
|
|
30
|
+
- [ ] Considered idempotency invariants (no double-execution window)
|
|
31
|
+
- [ ] Considered Redis AOF + noeviction assumptions
|
|
32
|
+
- [ ] Chaos suite still validates the guarantees (`make bench` or `python -m bench.bench --synthetic`)
|
|
33
|
+
|
|
34
|
+
### Documentation
|
|
35
|
+
- [ ] `docs/` updated if this changes user-visible behaviour
|
|
36
|
+
- [ ] `.env.example` updated if new config fields were added
|
|
37
|
+
- [ ] CLI help text updated if new `rl` commands were added
|
|
38
|
+
|
|
39
|
+
## Testing notes
|
|
40
|
+
|
|
41
|
+
<!-- How did you verify this? Paste relevant test output, bench results, or `rl tasks inflight` screenshots. -->
|
|
42
|
+
|
|
43
|
+
## Breaking changes
|
|
44
|
+
|
|
45
|
+
<!-- If this changes the public API, Redis key layout, Lua scripts, or wire format, describe the impact and migration path. -->
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
name: Relier CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
# Run on every PR targeting main, regardless of source branch name.
|
|
8
|
+
# The previous glob-list silently skipped chore/, docs/, refactor/, etc.
|
|
9
|
+
branches: [main]
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
lint-and-typecheck:
|
|
13
|
+
name: Code Quality
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v7
|
|
20
|
+
with:
|
|
21
|
+
enable-cache: true
|
|
22
|
+
|
|
23
|
+
- name: Set up Python 3.11
|
|
24
|
+
run: uv python install 3.11
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: uv sync --all-groups
|
|
28
|
+
|
|
29
|
+
- name: Run Ruff Linter
|
|
30
|
+
run: uv run ruff check src/
|
|
31
|
+
|
|
32
|
+
- name: Run Ruff Formatter (Check)
|
|
33
|
+
run: uv run ruff format --check src/
|
|
34
|
+
|
|
35
|
+
- name: Run Mypy Type Checker
|
|
36
|
+
run: uv run mypy src/
|
|
37
|
+
|
|
38
|
+
test-unit:
|
|
39
|
+
name: Unit Tests (>=95% coverage)
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v6
|
|
43
|
+
|
|
44
|
+
- name: Install uv
|
|
45
|
+
uses: astral-sh/setup-uv@v7
|
|
46
|
+
with:
|
|
47
|
+
enable-cache: true
|
|
48
|
+
|
|
49
|
+
- name: Set up Python 3.11
|
|
50
|
+
run: uv python install 3.11
|
|
51
|
+
|
|
52
|
+
- name: Install Relier and Dev Dependencies
|
|
53
|
+
run: uv sync --all-groups
|
|
54
|
+
|
|
55
|
+
- name: Run unit suite with 95% coverage gate
|
|
56
|
+
run: |
|
|
57
|
+
uv run pytest tests/unit/ \
|
|
58
|
+
--cov=src/relier \
|
|
59
|
+
--cov-report=term-missing \
|
|
60
|
+
--cov-report=xml \
|
|
61
|
+
--cov-fail-under=95
|
|
62
|
+
|
|
63
|
+
test-integration:
|
|
64
|
+
name: Integration Tests (>=80% coverage)
|
|
65
|
+
runs-on: ubuntu-latest
|
|
66
|
+
services:
|
|
67
|
+
redis:
|
|
68
|
+
image: redis:7.2-alpine
|
|
69
|
+
ports:
|
|
70
|
+
- 6379:6379
|
|
71
|
+
options: >-
|
|
72
|
+
--health-cmd "redis-cli ping"
|
|
73
|
+
--health-interval 10s
|
|
74
|
+
--health-timeout 5s
|
|
75
|
+
--health-retries 5
|
|
76
|
+
|
|
77
|
+
steps:
|
|
78
|
+
- uses: actions/checkout@v6
|
|
79
|
+
|
|
80
|
+
- name: Install uv
|
|
81
|
+
uses: astral-sh/setup-uv@v7
|
|
82
|
+
with:
|
|
83
|
+
enable-cache: true
|
|
84
|
+
|
|
85
|
+
- name: Set up Python 3.11
|
|
86
|
+
run: uv python install 3.11
|
|
87
|
+
|
|
88
|
+
- name: Install Relier and Dev Dependencies
|
|
89
|
+
run: uv sync --all-groups
|
|
90
|
+
|
|
91
|
+
- name: Run integration suite with 80% coverage gate
|
|
92
|
+
env:
|
|
93
|
+
RELIER_REDIS_URL: redis://localhost:6379/0
|
|
94
|
+
run: |
|
|
95
|
+
uv run pytest tests/integration/ \
|
|
96
|
+
--cov=src/relier \
|
|
97
|
+
--cov-report=term-missing \
|
|
98
|
+
--cov-report=xml \
|
|
99
|
+
--cov-fail-under=80 \
|
|
100
|
+
--timeout=120 \
|
|
101
|
+
--reruns 2 \
|
|
102
|
+
--reruns-delay 1
|
|
103
|
+
|
|
104
|
+
build-check:
|
|
105
|
+
name: Validate Build Artifacts
|
|
106
|
+
runs-on: ubuntu-latest
|
|
107
|
+
steps:
|
|
108
|
+
- uses: actions/checkout@v6
|
|
109
|
+
- uses: astral-sh/setup-uv@v7
|
|
110
|
+
- name: Build Package Wheels
|
|
111
|
+
run: uv build
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: "CodeQL Security Scanning"
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ "main" ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ "main" ]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: '30 18 * * 5'
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
analyze:
|
|
13
|
+
name: Analyze Code
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
permissions:
|
|
16
|
+
actions: read
|
|
17
|
+
contents: read
|
|
18
|
+
security-events: write
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- name: Checkout repository
|
|
22
|
+
uses: actions/checkout@v6
|
|
23
|
+
|
|
24
|
+
- name: Initialize CodeQL
|
|
25
|
+
uses: github/codeql-action/init@v4
|
|
26
|
+
with:
|
|
27
|
+
languages: python
|
|
28
|
+
|
|
29
|
+
- name: Perform CodeQL Analysis
|
|
30
|
+
uses: github/codeql-action/analyze@v4
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Relier Docs CI/CD
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- "docs/**"
|
|
8
|
+
- "mkdocs.yml"
|
|
9
|
+
- ".github/workflows/docs.yml"
|
|
10
|
+
pull_request:
|
|
11
|
+
branches: [main]
|
|
12
|
+
paths:
|
|
13
|
+
- "docs/**"
|
|
14
|
+
- "mkdocs.yml"
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: write
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
validate-and-deploy:
|
|
21
|
+
name: Build and Verify Documentation
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v6
|
|
25
|
+
with:
|
|
26
|
+
fetch-depth: 0
|
|
27
|
+
|
|
28
|
+
- name: Install uv
|
|
29
|
+
uses: astral-sh/setup-uv@v7
|
|
30
|
+
with:
|
|
31
|
+
enable-cache: true
|
|
32
|
+
|
|
33
|
+
- name: Strict Build Validation Test
|
|
34
|
+
run: uv run --with mkdocs-material --with pymdown-extensions mkdocs build --strict
|
|
35
|
+
|
|
36
|
+
- name: Deploy to GitHub Pages (Main Branch Only)
|
|
37
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
38
|
+
run: |
|
|
39
|
+
git config user.name "github-actions[bot]"
|
|
40
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
41
|
+
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
|
|
42
|
+
uv run --with mkdocs-material --with pymdown-extensions mkdocs gh-deploy --force
|