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.
Files changed (175) hide show
  1. relier-0.1.0/.env.example +110 -0
  2. relier-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +112 -0
  3. relier-0.1.0/.github/ISSUE_TEMPLATE/config.yml +11 -0
  4. relier-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +76 -0
  5. relier-0.1.0/.github/ISSUE_TEMPLATE/question.yml +55 -0
  6. relier-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +45 -0
  7. relier-0.1.0/.github/dependabot.yml +12 -0
  8. relier-0.1.0/.github/workflows/ci.yml +111 -0
  9. relier-0.1.0/.github/workflows/codeql.yml +30 -0
  10. relier-0.1.0/.github/workflows/docs.yml +42 -0
  11. relier-0.1.0/.github/workflows/nightly.yml +139 -0
  12. relier-0.1.0/.github/workflows/publish.yml +66 -0
  13. relier-0.1.0/.gitignore +65 -0
  14. relier-0.1.0/.pre-commit-config.yaml +30 -0
  15. relier-0.1.0/.python-version +1 -0
  16. relier-0.1.0/CHANGELOG.md +57 -0
  17. relier-0.1.0/CONTRIBUTING.md +144 -0
  18. relier-0.1.0/Dockerfile +47 -0
  19. relier-0.1.0/Dockerfile.bench +33 -0
  20. relier-0.1.0/LICENSE +21 -0
  21. relier-0.1.0/Makefile +103 -0
  22. relier-0.1.0/PKG-INFO +366 -0
  23. relier-0.1.0/README.md +341 -0
  24. relier-0.1.0/SECURITY.md +80 -0
  25. relier-0.1.0/bench/README.md +129 -0
  26. relier-0.1.0/bench/__init__.py +1 -0
  27. relier-0.1.0/bench/bench.py +1201 -0
  28. relier-0.1.0/bench/config.py +59 -0
  29. relier-0.1.0/bench/grafana/dashboards/bench-overview.json +260 -0
  30. relier-0.1.0/bench/grafana/provisioning/dashboards/dashboards.yml +10 -0
  31. relier-0.1.0/bench/grafana/provisioning/datasources/prometheus.yml +11 -0
  32. relier-0.1.0/bench/monitor.py +85 -0
  33. relier-0.1.0/bench/ollama_client.py +82 -0
  34. relier-0.1.0/bench/prometheus.yml +11 -0
  35. relier-0.1.0/bench/relier_tasks.py +140 -0
  36. relier-0.1.0/bench/vanilla_app.py +111 -0
  37. relier-0.1.0/bench/worker_app.py +16 -0
  38. relier-0.1.0/docker-compose.bench.yml +144 -0
  39. relier-0.1.0/docker-compose.prod.yml +344 -0
  40. relier-0.1.0/docker-compose.yml +171 -0
  41. relier-0.1.0/docs/api-reference.md +655 -0
  42. relier-0.1.0/docs/architecture.md +492 -0
  43. relier-0.1.0/docs/assets/images/favicon.ico +0 -0
  44. relier-0.1.0/docs/assets/images/logo-plain.png +0 -0
  45. relier-0.1.0/docs/assets/images/logo-readme.png +0 -0
  46. relier-0.1.0/docs/assets/images/logo.ico +0 -0
  47. relier-0.1.0/docs/assets/images/logo.png +0 -0
  48. relier-0.1.0/docs/assets/images/screenshot-1.png +0 -0
  49. relier-0.1.0/docs/assets/images/screenshot-2.png +0 -0
  50. relier-0.1.0/docs/assets/js/mermaid-init.js +22 -0
  51. relier-0.1.0/docs/benchmarks.md +156 -0
  52. relier-0.1.0/docs/celery-primer.md +183 -0
  53. relier-0.1.0/docs/chaos-guide.md +321 -0
  54. relier-0.1.0/docs/cli-reference.md +929 -0
  55. relier-0.1.0/docs/concepts.md +538 -0
  56. relier-0.1.0/docs/configuration.md +210 -0
  57. relier-0.1.0/docs/deployment.md +638 -0
  58. relier-0.1.0/docs/durability.md +466 -0
  59. relier-0.1.0/docs/index.md +175 -0
  60. relier-0.1.0/docs/integrations.md +327 -0
  61. relier-0.1.0/docs/landing/app.js +442 -0
  62. relier-0.1.0/docs/landing/index.html +757 -0
  63. relier-0.1.0/docs/landing/styles.css +1304 -0
  64. relier-0.1.0/docs/metrics.md +255 -0
  65. relier-0.1.0/docs/patterns.md +430 -0
  66. relier-0.1.0/docs/quickstart.md +213 -0
  67. relier-0.1.0/docs/rl.md +108 -0
  68. relier-0.1.0/docs/rolling-deploys.md +213 -0
  69. relier-0.1.0/docs/running.md +104 -0
  70. relier-0.1.0/docs/stylesheets/extra.css +199 -0
  71. relier-0.1.0/docs/troubleshooting.md +429 -0
  72. relier-0.1.0/man/rl.1 +271 -0
  73. relier-0.1.0/mkdocs.yml +109 -0
  74. relier-0.1.0/pyproject.toml +129 -0
  75. relier-0.1.0/scripts/grafana/provisioning/dashboards/dashboards.yml +9 -0
  76. relier-0.1.0/scripts/grafana/provisioning/datasources/prometheus.yml +9 -0
  77. relier-0.1.0/scripts/grafana-dashboards/relier-overview.json +306 -0
  78. relier-0.1.0/scripts/grafana-dashboards/slo-burnrate.json +252 -0
  79. relier-0.1.0/scripts/otel-collector-config.yml +48 -0
  80. relier-0.1.0/scripts/prometheus.yml +8 -0
  81. relier-0.1.0/scripts/redis/README.md +77 -0
  82. relier-0.1.0/scripts/redis/backup.sh +86 -0
  83. relier-0.1.0/scripts/redis/redis.conf +52 -0
  84. relier-0.1.0/scripts/redis/sentinel.conf +37 -0
  85. relier-0.1.0/src/relier/__init__.py +111 -0
  86. relier-0.1.0/src/relier/chaos/__init__.py +19 -0
  87. relier-0.1.0/src/relier/chaos/engine.py +49 -0
  88. relier-0.1.0/src/relier/chaos/load_spike.py +92 -0
  89. relier-0.1.0/src/relier/chaos/network.py +130 -0
  90. relier-0.1.0/src/relier/chaos/slow_task.py +48 -0
  91. relier-0.1.0/src/relier/chaos/task_corrupt.py +74 -0
  92. relier-0.1.0/src/relier/chaos/tasks.py +98 -0
  93. relier-0.1.0/src/relier/chaos/worker_kill.py +72 -0
  94. relier-0.1.0/src/relier/cli/__init__.py +5 -0
  95. relier-0.1.0/src/relier/cli/admin.py +80 -0
  96. relier-0.1.0/src/relier/cli/admission.py +46 -0
  97. relier-0.1.0/src/relier/cli/base.py +52 -0
  98. relier-0.1.0/src/relier/cli/chaos.py +176 -0
  99. relier-0.1.0/src/relier/cli/cluster.py +145 -0
  100. relier-0.1.0/src/relier/cli/config.py +117 -0
  101. relier-0.1.0/src/relier/cli/dlq.py +118 -0
  102. relier-0.1.0/src/relier/cli/main.py +322 -0
  103. relier-0.1.0/src/relier/cli/manual.py +255 -0
  104. relier-0.1.0/src/relier/cli/slo.py +173 -0
  105. relier-0.1.0/src/relier/cli/tasks.py +562 -0
  106. relier-0.1.0/src/relier/cli/ui/__init__.py +5 -0
  107. relier-0.1.0/src/relier/cli/ui/live.py +20 -0
  108. relier-0.1.0/src/relier/cli/ui/panels.py +39 -0
  109. relier-0.1.0/src/relier/cli/ui/tables.py +201 -0
  110. relier-0.1.0/src/relier/cli/utils.py +55 -0
  111. relier-0.1.0/src/relier/cli/workers.py +209 -0
  112. relier-0.1.0/src/relier/config.py +490 -0
  113. relier-0.1.0/src/relier/core/__init__.py +32 -0
  114. relier-0.1.0/src/relier/core/admission.py +172 -0
  115. relier-0.1.0/src/relier/core/checkpoint.py +333 -0
  116. relier-0.1.0/src/relier/core/dlq.py +315 -0
  117. relier-0.1.0/src/relier/core/exceptions.py +227 -0
  118. relier-0.1.0/src/relier/core/idempotency.py +243 -0
  119. relier-0.1.0/src/relier/core/keys.py +199 -0
  120. relier-0.1.0/src/relier/core/phoenix.py +1052 -0
  121. relier-0.1.0/src/relier/core/schema.py +205 -0
  122. relier-0.1.0/src/relier/core/shutdown.py +193 -0
  123. relier-0.1.0/src/relier/core/slo.py +144 -0
  124. relier-0.1.0/src/relier/core/timeouts.py +197 -0
  125. relier-0.1.0/src/relier/core/validation.py +209 -0
  126. relier-0.1.0/src/relier/py.typed +0 -0
  127. relier-0.1.0/src/relier/storage/__init__.py +13 -0
  128. relier-0.1.0/src/relier/storage/lua/__init__.py +5 -0
  129. relier-0.1.0/src/relier/storage/lua/scripts.py +140 -0
  130. relier-0.1.0/src/relier/storage/redis.py +335 -0
  131. relier-0.1.0/src/relier/tasks/__init__.py +16 -0
  132. relier-0.1.0/src/relier/tasks/app.py +466 -0
  133. relier-0.1.0/src/relier/tasks/context.py +180 -0
  134. relier-0.1.0/src/relier/tasks/decorator.py +1121 -0
  135. relier-0.1.0/src/relier/tasks/signals.py +101 -0
  136. relier-0.1.0/src/relier/telemetry/__init__.py +16 -0
  137. relier-0.1.0/src/relier/telemetry/logging.py +98 -0
  138. relier-0.1.0/src/relier/telemetry/metrics.py +151 -0
  139. relier-0.1.0/src/relier/telemetry/setup.py +82 -0
  140. relier-0.1.0/src/relier/telemetry/spans.py +107 -0
  141. relier-0.1.0/tests/__init__.py +5 -0
  142. relier-0.1.0/tests/conftest.py +167 -0
  143. relier-0.1.0/tests/integration/__init__.py +0 -0
  144. relier-0.1.0/tests/integration/conftest.py +157 -0
  145. relier-0.1.0/tests/integration/tasks.py +61 -0
  146. relier-0.1.0/tests/integration/test_admission_concurrency.py +65 -0
  147. relier-0.1.0/tests/integration/test_core_integration.py +599 -0
  148. relier-0.1.0/tests/integration/test_dependencies.py +12 -0
  149. relier-0.1.0/tests/integration/test_fencing.py +164 -0
  150. relier-0.1.0/tests/integration/test_idempotency_e2e.py +53 -0
  151. relier-0.1.0/tests/integration/test_resurrection.py +134 -0
  152. relier-0.1.0/tests/integration/test_resurrection_bounds.py +146 -0
  153. relier-0.1.0/tests/integration/test_storage.py +31 -0
  154. relier-0.1.0/tests/integration/test_timeout_e2e.py +22 -0
  155. relier-0.1.0/tests/integration/test_worker_integration.py +931 -0
  156. relier-0.1.0/tests/unit/conftest.py +436 -0
  157. relier-0.1.0/tests/unit/test_admission.py +92 -0
  158. relier-0.1.0/tests/unit/test_checkpoint.py +270 -0
  159. relier-0.1.0/tests/unit/test_coverage_gap.py +275 -0
  160. relier-0.1.0/tests/unit/test_dlq.py +149 -0
  161. relier-0.1.0/tests/unit/test_exceptions.py +38 -0
  162. relier-0.1.0/tests/unit/test_idempotency.py +105 -0
  163. relier-0.1.0/tests/unit/test_phoenix.py +505 -0
  164. relier-0.1.0/tests/unit/test_redis_ha.py +280 -0
  165. relier-0.1.0/tests/unit/test_schema.py +214 -0
  166. relier-0.1.0/tests/unit/test_shutdown.py +148 -0
  167. relier-0.1.0/tests/unit/test_slo.py +70 -0
  168. relier-0.1.0/tests/unit/test_tasks_app.py +308 -0
  169. relier-0.1.0/tests/unit/test_tasks_context.py +29 -0
  170. relier-0.1.0/tests/unit/test_tasks_debug.py +98 -0
  171. relier-0.1.0/tests/unit/test_tasks_decorator.py +418 -0
  172. relier-0.1.0/tests/unit/test_tasks_signals.py +74 -0
  173. relier-0.1.0/tests/unit/test_telemetry.py +276 -0
  174. relier-0.1.0/tests/unit/test_timeouts.py +67 -0
  175. 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,12 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+
8
+ - package-ecosystem: "pip"
9
+ directory: "/"
10
+ schedule:
11
+ interval: "weekly"
12
+ open-pull-requests-limit: 3
@@ -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