stemtrace 0.2.1__tar.gz → 0.3.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 (135) hide show
  1. {stemtrace-0.2.1 → stemtrace-0.3.0}/.bumpversion.toml +15 -1
  2. {stemtrace-0.2.1 → stemtrace-0.3.0}/.github/workflows/e2e.yml +48 -10
  3. {stemtrace-0.2.1 → stemtrace-0.3.0}/CHANGELOG.md +4 -0
  4. {stemtrace-0.2.1 → stemtrace-0.3.0}/Makefile +34 -4
  5. {stemtrace-0.2.1 → stemtrace-0.3.0}/PKG-INFO +26 -7
  6. {stemtrace-0.2.1 → stemtrace-0.3.0}/README.md +24 -6
  7. stemtrace-0.3.0/docker-compose.e2e.rabbitmq.yml +88 -0
  8. stemtrace-0.3.0/docker-compose.rabbitmq.yml +44 -0
  9. {stemtrace-0.2.1 → stemtrace-0.3.0}/pyproject.toml +12 -1
  10. stemtrace-0.3.0/scripts/wait_for_http.py +41 -0
  11. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/__init__.py +1 -1
  12. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/core/exceptions.py +1 -1
  13. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/library/transports/__init__.py +5 -0
  14. stemtrace-0.3.0/src/stemtrace/library/transports/rabbitmq.py +250 -0
  15. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/package.json +1 -1
  16. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/static.py +41 -2
  17. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/e2e/tasks.py +3 -2
  18. stemtrace-0.3.0/tests/e2e/test_workers_e2e.py +197 -0
  19. stemtrace-0.3.0/tests/integration/test_rabbitmq_transport.py +139 -0
  20. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/integration/test_static_ui.py +51 -0
  21. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_init.py +9 -3
  22. stemtrace-0.3.0/tests/unit/test_transports.py +1033 -0
  23. stemtrace-0.3.0/tests/unit/test_ui_static_prefix.py +61 -0
  24. {stemtrace-0.2.1 → stemtrace-0.3.0}/uv.lock +1 -1
  25. stemtrace-0.2.1/tests/e2e/test_workers_e2e.py +0 -117
  26. stemtrace-0.2.1/tests/unit/test_transports.py +0 -543
  27. {stemtrace-0.2.1 → stemtrace-0.3.0}/.dockerignore +0 -0
  28. {stemtrace-0.2.1 → stemtrace-0.3.0}/.github/dependabot.yml +0 -0
  29. {stemtrace-0.2.1 → stemtrace-0.3.0}/.github/workflows/ci.yml +0 -0
  30. {stemtrace-0.2.1 → stemtrace-0.3.0}/.github/workflows/release.yml +0 -0
  31. {stemtrace-0.2.1 → stemtrace-0.3.0}/.gitignore +0 -0
  32. {stemtrace-0.2.1 → stemtrace-0.3.0}/.pre-commit-config.yaml +0 -0
  33. {stemtrace-0.2.1 → stemtrace-0.3.0}/.python-version +0 -0
  34. {stemtrace-0.2.1 → stemtrace-0.3.0}/CONTRIBUTING.md +0 -0
  35. {stemtrace-0.2.1 → stemtrace-0.3.0}/Dockerfile +0 -0
  36. {stemtrace-0.2.1 → stemtrace-0.3.0}/Dockerfile.e2e +0 -0
  37. {stemtrace-0.2.1 → stemtrace-0.3.0}/LICENSE +0 -0
  38. {stemtrace-0.2.1 → stemtrace-0.3.0}/build_ui.py +0 -0
  39. {stemtrace-0.2.1 → stemtrace-0.3.0}/docker-compose.e2e.yml +0 -0
  40. {stemtrace-0.2.1 → stemtrace-0.3.0}/docker-compose.yml +0 -0
  41. {stemtrace-0.2.1 → stemtrace-0.3.0}/docs/screenshots/task_details.png +0 -0
  42. {stemtrace-0.2.1 → stemtrace-0.3.0}/docs/screenshots/unregistered.png +0 -0
  43. {stemtrace-0.2.1 → stemtrace-0.3.0}/docs/screenshots/workflow.png +0 -0
  44. {stemtrace-0.2.1 → stemtrace-0.3.0}/examples/celery_app.py +0 -0
  45. {stemtrace-0.2.1 → stemtrace-0.3.0}/examples/fastapi_integration.py +0 -0
  46. {stemtrace-0.2.1 → stemtrace-0.3.0}/examples/with_auth.py +0 -0
  47. {stemtrace-0.2.1 → stemtrace-0.3.0}/progress.md +0 -0
  48. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/core/__init__.py +0 -0
  49. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/core/events.py +0 -0
  50. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/core/graph.py +0 -0
  51. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/core/ports.py +0 -0
  52. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/library/__init__.py +0 -0
  53. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/library/bootsteps.py +0 -0
  54. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/library/config.py +0 -0
  55. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/library/scrubbing.py +0 -0
  56. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/library/signals.py +0 -0
  57. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/library/transports/memory.py +0 -0
  58. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/library/transports/redis.py +0 -0
  59. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/py.typed +0 -0
  60. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/__init__.py +0 -0
  61. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/__main__.py +0 -0
  62. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/api/__init__.py +0 -0
  63. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/api/routes.py +0 -0
  64. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/api/schemas.py +0 -0
  65. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/api/websocket.py +0 -0
  66. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/consumer.py +0 -0
  67. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/fastapi/__init__.py +0 -0
  68. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/fastapi/auth.py +0 -0
  69. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/fastapi/extension.py +0 -0
  70. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/fastapi/router.py +0 -0
  71. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/store.py +0 -0
  72. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/__init__.py +0 -0
  73. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/biome.json +0 -0
  74. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/index.html +0 -0
  75. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/package-lock.json +0 -0
  76. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/playwright.config.ts +0 -0
  77. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/postcss.config.js +0 -0
  78. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/api/client.ts +0 -0
  79. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/api/queries.ts +0 -0
  80. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/components/DateRangePicker.tsx +0 -0
  81. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/components/Filters.tsx +0 -0
  82. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/components/TaskGraph.tsx +0 -0
  83. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/components/TaskList.tsx +0 -0
  84. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/components/TaskStateBadge.tsx +0 -0
  85. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/components/TaskTimeline.tsx +0 -0
  86. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/components/TimelineBar.tsx +0 -0
  87. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/components/Tooltip.tsx +0 -0
  88. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/hooks/WebSocketContext.tsx +0 -0
  89. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/hooks/useInfiniteScroll.ts +0 -0
  90. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/index.css +0 -0
  91. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/main.tsx +0 -0
  92. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/routes/__root.tsx +0 -0
  93. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/routes/graph.$rootId.tsx +0 -0
  94. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/routes/graphs.tsx +0 -0
  95. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/routes/index.tsx +0 -0
  96. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/routes/registry.tsx +0 -0
  97. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/routes/tasks.$taskId.tsx +0 -0
  98. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/routes/workers.tsx +0 -0
  99. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/utils/format.ts +0 -0
  100. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/src/vite-env.d.ts +0 -0
  101. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/tests/fixtures/mock-api.ts +0 -0
  102. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/tests/fixtures/mock-data.ts +0 -0
  103. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/tests/graphs.spec.ts +0 -0
  104. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/tests/registry.spec.ts +0 -0
  105. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/tests/task-detail.spec.ts +0 -0
  106. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/tests/tasks.spec.ts +0 -0
  107. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/tests/workers.spec.ts +0 -0
  108. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/tsconfig.json +0 -0
  109. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/tsconfig.tsbuildinfo +0 -0
  110. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/ui/frontend/vite.config.ts +0 -0
  111. {stemtrace-0.2.1 → stemtrace-0.3.0}/src/stemtrace/server/websocket.py +0 -0
  112. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/__init__.py +0 -0
  113. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/conftest.py +0 -0
  114. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/e2e/__init__.py +0 -0
  115. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/e2e/conftest.py +0 -0
  116. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/e2e/test_api_e2e.py +0 -0
  117. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/integration/__init__.py +0 -0
  118. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/integration/test_embedded_static.py +0 -0
  119. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/integration/test_fastapi_integration.py +0 -0
  120. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/integration/test_redis_transport.py +0 -0
  121. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/integration/test_workers_refresh.py +0 -0
  122. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/__init__.py +0 -0
  123. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_auth.py +0 -0
  124. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_bootsteps.py +0 -0
  125. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_config.py +0 -0
  126. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_consumer.py +0 -0
  127. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_events.py +0 -0
  128. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_examples.py +0 -0
  129. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_exceptions.py +0 -0
  130. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_graph.py +0 -0
  131. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_routes.py +0 -0
  132. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_scrubbing.py +0 -0
  133. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_signals.py +0 -0
  134. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_store.py +0 -0
  135. {stemtrace-0.2.1 → stemtrace-0.3.0}/tests/unit/test_websocket.py +0 -0
@@ -1,5 +1,5 @@
1
1
  [tool.bumpversion]
2
- current_version = "0.2.1"
2
+ current_version = "0.3.0"
3
3
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
4
4
  serialize = ["{major}.{minor}.{patch}"]
5
5
  commit = true
@@ -24,6 +24,14 @@ filename = "src/stemtrace/server/ui/frontend/package.json"
24
24
  search = '"version": "{current_version}"'
25
25
  replace = '"version": "{new_version}"'
26
26
 
27
+ # uv.lock - keep workspace lockfile in sync (uv stores the local project version)
28
+ [[tool.bumpversion.files]]
29
+ filename = "uv.lock"
30
+ search = """name = "stemtrace"
31
+ version = "{current_version}"""
32
+ replace = """name = "stemtrace"
33
+ version = "{new_version}"""
34
+
27
35
  # CHANGELOG.md - insert new version header
28
36
  [[tool.bumpversion.files]]
29
37
  filename = "CHANGELOG.md"
@@ -31,3 +39,9 @@ search = "## [Unreleased]"
31
39
  replace = """## [Unreleased]
32
40
 
33
41
  ## [{new_version}] - {now:%Y-%m-%d}"""
42
+
43
+ # README.md - keep PyPI badge in sync with version (avoid cached badge drift)
44
+ [[tool.bumpversion.files]]
45
+ filename = "README.md"
46
+ search = "[![PyPI version](https://img.shields.io/badge/pypi-v{current_version}-darklime)](https://pypi.org/project/stemtrace)"
47
+ replace = "[![PyPI version](https://img.shields.io/badge/pypi-v{new_version}-darklime)](https://pypi.org/project/stemtrace)"
@@ -13,6 +13,12 @@ jobs:
13
13
  name: API E2E Tests
14
14
  runs-on: ubuntu-latest
15
15
  timeout-minutes: 15
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ broker:
20
+ - redis
21
+ - rabbitmq
16
22
 
17
23
  steps:
18
24
  - uses: actions/checkout@v6
@@ -20,13 +26,25 @@ jobs:
20
26
  - name: Set up Docker Buildx
21
27
  uses: docker/setup-buildx-action@v3
22
28
 
29
+ - name: Select compose file and Celery env
30
+ run: |
31
+ if [ "${{ matrix.broker }}" = "rabbitmq" ]; then
32
+ echo "COMPOSE_FILE=docker-compose.e2e.rabbitmq.yml" >> "$GITHUB_ENV"
33
+ echo "CELERY_BROKER_URL=amqp://guest:guest@localhost:5672//" >> "$GITHUB_ENV"
34
+ echo "CELERY_RESULT_BACKEND=redis://localhost:16380/1" >> "$GITHUB_ENV"
35
+ else
36
+ echo "COMPOSE_FILE=docker-compose.e2e.yml" >> "$GITHUB_ENV"
37
+ echo "CELERY_BROKER_URL=redis://localhost:16379/0" >> "$GITHUB_ENV"
38
+ echo "CELERY_RESULT_BACKEND=redis://localhost:16379/1" >> "$GITHUB_ENV"
39
+ fi
40
+
23
41
  - name: Build images
24
42
  run: |
25
- docker compose -f docker-compose.e2e.yml build
43
+ docker compose -f "$COMPOSE_FILE" build
26
44
 
27
45
  - name: Start services
28
46
  run: |
29
- docker compose -f docker-compose.e2e.yml up -d
47
+ docker compose -f "$COMPOSE_FILE" up -d
30
48
  # Wait for services to be healthy
31
49
  echo "Waiting for services..."
32
50
  timeout 120 bash -c 'until curl -sf http://localhost:8000/stemtrace/api/health -o /dev/null; do sleep 2; done'
@@ -51,16 +69,23 @@ jobs:
51
69
  - name: Show logs on failure
52
70
  if: failure()
53
71
  run: |
54
- docker compose -f docker-compose.e2e.yml logs
72
+ docker compose -f "$COMPOSE_FILE" logs
55
73
 
56
74
  - name: Stop services
57
75
  if: always()
58
- run: docker compose -f docker-compose.e2e.yml down -v
76
+ run: |
77
+ docker compose -f "$COMPOSE_FILE" down -v
59
78
 
60
79
  playwright:
61
80
  name: Playwright E2E Tests
62
81
  runs-on: ubuntu-latest
63
82
  timeout-minutes: 20
83
+ strategy:
84
+ fail-fast: false
85
+ matrix:
86
+ broker:
87
+ - redis
88
+ - rabbitmq
64
89
 
65
90
  steps:
66
91
  - uses: actions/checkout@v6
@@ -68,13 +93,25 @@ jobs:
68
93
  - name: Set up Docker Buildx
69
94
  uses: docker/setup-buildx-action@v3
70
95
 
96
+ - name: Select compose file and Celery env
97
+ run: |
98
+ if [ "${{ matrix.broker }}" = "rabbitmq" ]; then
99
+ echo "COMPOSE_FILE=docker-compose.e2e.rabbitmq.yml" >> "$GITHUB_ENV"
100
+ echo "CELERY_BROKER_URL=amqp://guest:guest@localhost:5672//" >> "$GITHUB_ENV"
101
+ echo "CELERY_RESULT_BACKEND=redis://localhost:16380/1" >> "$GITHUB_ENV"
102
+ else
103
+ echo "COMPOSE_FILE=docker-compose.e2e.yml" >> "$GITHUB_ENV"
104
+ echo "CELERY_BROKER_URL=redis://localhost:16379/0" >> "$GITHUB_ENV"
105
+ echo "CELERY_RESULT_BACKEND=redis://localhost:16379/1" >> "$GITHUB_ENV"
106
+ fi
107
+
71
108
  - name: Build images
72
109
  run: |
73
- docker compose -f docker-compose.e2e.yml build
110
+ docker compose -f "$COMPOSE_FILE" build
74
111
 
75
112
  - name: Start services
76
113
  run: |
77
- docker compose -f docker-compose.e2e.yml up -d
114
+ docker compose -f "$COMPOSE_FILE" up -d
78
115
  echo "Waiting for services..."
79
116
  timeout 120 bash -c 'until curl -sf http://localhost:8000/stemtrace/api/health -o /dev/null; do sleep 2; done'
80
117
  echo "Services ready!"
@@ -133,7 +170,7 @@ jobs:
133
170
  uses: actions/upload-artifact@v6
134
171
  if: always()
135
172
  with:
136
- name: playwright-report
173
+ name: playwright-report-${{ matrix.broker }}
137
174
  path: src/stemtrace/server/ui/frontend/playwright-report/
138
175
  retention-days: 7
139
176
 
@@ -141,15 +178,16 @@ jobs:
141
178
  uses: actions/upload-artifact@v6
142
179
  if: failure()
143
180
  with:
144
- name: playwright-test-results
181
+ name: playwright-test-results-${{ matrix.broker }}
145
182
  path: src/stemtrace/server/ui/frontend/test-results/
146
183
  retention-days: 7
147
184
 
148
185
  - name: Show logs on failure
149
186
  if: failure()
150
187
  run: |
151
- docker compose -f docker-compose.e2e.yml logs
188
+ docker compose -f "$COMPOSE_FILE" logs
152
189
 
153
190
  - name: Stop services
154
191
  if: always()
155
- run: docker compose -f docker-compose.e2e.yml down -v
192
+ run: |
193
+ docker compose -f "$COMPOSE_FILE" down -v
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.0] - 2026-01-04
11
+
12
+ ## [0.2.2] - 2026-01-03
13
+
10
14
  ## [0.2.1] - 2026-01-03
11
15
 
12
16
  ### Added
@@ -126,7 +126,7 @@ bump-patch:
126
126
  @NEW_VER=$$(uv run bump-my-version show current_version); \
127
127
  echo "✅ Version bumped to $$NEW_VER"; \
128
128
  echo ""; \
129
- echo "Next: git add -A && git commit -m 'chore: release v$$NEW_VER' && make release"
129
+ echo "Next: make release"
130
130
 
131
131
  # Bump minor version (0.1.0 -> 0.2.0)
132
132
  bump-minor:
@@ -134,7 +134,7 @@ bump-minor:
134
134
  @NEW_VER=$$(uv run bump-my-version show current_version); \
135
135
  echo "✅ Version bumped to $$NEW_VER"; \
136
136
  echo ""; \
137
- echo "Next: git add -A && git commit -m 'chore: release v$$NEW_VER' && make release"
137
+ echo "Next: make release"
138
138
 
139
139
  # Bump major version (0.1.0 -> 1.0.0)
140
140
  bump-major:
@@ -142,7 +142,7 @@ bump-major:
142
142
  @NEW_VER=$$(uv run bump-my-version show current_version); \
143
143
  echo "✅ Version bumped to $$NEW_VER"; \
144
144
  echo ""; \
145
- echo "Next: git add -A && git commit -m 'chore: release v$$NEW_VER' && make release"
145
+ echo "Next: make release"
146
146
 
147
147
  # Tag and push to trigger release workflow
148
148
  release:
@@ -168,9 +168,10 @@ e2e-mock:
168
168
 
169
169
  # Start E2E test environment (Docker)
170
170
  e2e-up:
171
+ docker compose -f docker-compose.e2e.yml build
171
172
  docker compose -f docker-compose.e2e.yml up -d --wait
172
173
  @echo "Waiting for services..."
173
- @timeout 60 bash -c 'until curl -sf http://localhost:8000/stemtrace/api/health -o /dev/null; do sleep 2; done' || (echo "❌ Service failed to become healthy"; exit 1)
174
+ @uv run python scripts/wait_for_http.py http://localhost:8000/stemtrace/api/health --timeout 60
174
175
  @echo "✅ E2E environment ready at http://localhost:8000"
175
176
 
176
177
  # Stop E2E test environment
@@ -193,5 +194,34 @@ e2e:
193
194
  $(MAKE) e2e-down; \
194
195
  exit $$status
195
196
 
197
+ # =============================================================================
198
+ # E2E Testing (RabbitMQ broker)
199
+ # =============================================================================
200
+
201
+ e2e-up-rabbitmq:
202
+ docker compose -f docker-compose.e2e.rabbitmq.yml build
203
+ docker compose -f docker-compose.e2e.rabbitmq.yml up -d --wait
204
+ @echo "Waiting for services..."
205
+ @uv run python scripts/wait_for_http.py http://localhost:8000/stemtrace/api/health --timeout 60
206
+ @echo "✅ RabbitMQ E2E environment ready at http://localhost:8000"
207
+
208
+ e2e-down-rabbitmq:
209
+ docker compose -f docker-compose.e2e.rabbitmq.yml down -v
210
+
211
+ e2e-api-rabbitmq:
212
+ CELERY_BROKER_URL=amqp://guest:guest@localhost:5672// \
213
+ CELERY_RESULT_BACKEND=redis://localhost:16380/1 \
214
+ uv run pytest tests/e2e/ -m e2e -v
215
+
216
+ e2e-playwright-real-rabbitmq:
217
+ cd $(FRONTEND_DIR) && E2E_MODE=real PLAYWRIGHT_BASE_URL=http://localhost:8000 npm test
218
+
219
+ e2e-rabbitmq:
220
+ $(MAKE) e2e-up-rabbitmq
221
+ $(MAKE) e2e-api-rabbitmq && $(MAKE) e2e-playwright-real-rabbitmq; \
222
+ status=$$?; \
223
+ $(MAKE) e2e-down-rabbitmq; \
224
+ exit $$status
225
+
196
226
  # Quick E2E alias (mock mode, no Docker)
197
227
  e2e-quick: e2e-mock
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stemtrace
3
- Version: 0.2.1
3
+ Version: 0.3.0
4
4
  Summary: A lightweight Celery task flow visualizer
5
5
  Project-URL: Homepage, https://github.com/iansokolskyi/stemtrace
6
6
  Project-URL: Documentation, https://github.com/iansokolskyi/stemtrace#readme
@@ -8,6 +8,7 @@ Project-URL: Repository, https://github.com/iansokolskyi/stemtrace
8
8
  Project-URL: Issues, https://github.com/iansokolskyi/stemtrace/issues
9
9
  Project-URL: Changelog, https://github.com/iansokolskyi/stemtrace/blob/main/CHANGELOG.md
10
10
  Author-email: Ian Sokolskyi <iansokolskyi@gmail.com>
11
+ Maintainer-email: Ian Sokolskyi <iansokolskyi@gmail.com>
11
12
  License: MIT
12
13
  License-File: LICENSE
13
14
  Keywords: celery,monitoring,queue,task,visualization,workflow
@@ -55,7 +56,7 @@ Description-Content-Type: text/markdown
55
56
 
56
57
  **Zero-infrastructure Celery task flow visualizer**
57
58
 
58
- [![PyPI version](https://img.shields.io/pypi/v/stemtrace?color=darklime)](https://pypi.org/project/stemtrace)
59
+ [![PyPI version](https://img.shields.io/badge/pypi-v0.3.0-darklime)](https://pypi.org/project/stemtrace)
59
60
  [![Python](https://img.shields.io/pypi/pyversions/stemtrace.svg)](https://pypi.org/project/stemtrace/)
60
61
  [![CI](https://github.com/iansokolskyi/stemtrace/actions/workflows/ci.yml/badge.svg)](https://github.com/iansokolskyi/stemtrace/actions/workflows/ci.yml)
61
62
  [![codecov](https://codecov.io/gh/iansokolskyi/stemtrace/graph/badge.svg)](https://codecov.io/gh/iansokolskyi/stemtrace)
@@ -71,7 +72,7 @@ Ever stared at a failed Celery task wondering "what called this?" or "why did it
71
72
 
72
73
  Stemtrace captures your task executions as a graph — visualize parent→child flows, see retry chains, track groups and chords, all without adding any new infrastructure.
73
74
 
74
- **Today stemtrace supports Redis** for event transport (via Redis Streams). **RabbitMQ support is planned.**
75
+ **stemtrace supports Redis and RabbitMQ** for event transport.
75
76
 
76
77
  ## ✨ Features
77
78
 
@@ -90,7 +91,7 @@ Stemtrace captures your task executions as a graph — visualize parent→child
90
91
  - **Registry status badges** — Quickly spot tasks that are active, never run, or not registered by any current worker
91
92
 
92
93
  **Production Ready**
93
- - **Zero Infrastructure** — Uses your existing Redis broker, no database needed
94
+ - **Zero Infrastructure** — Uses your existing broker (Redis or RabbitMQ), no database needed
94
95
  - **Sensitive Data Scrubbing** — Passwords and API keys filtered automatically
95
96
  - **Read-Only** — Safe for production; never modifies your task queue
96
97
  - **FastAPI Integration** — Mount into your existing app with one line
@@ -161,6 +162,14 @@ stemtrace server
161
162
 
162
163
  Open [http://localhost:8000](http://localhost:8000).
163
164
 
165
+ Tip: make sure the server is pointed at the same broker as your workers:
166
+
167
+ ```bash
168
+ stemtrace server --broker-url redis://localhost:6379/0
169
+ # or:
170
+ stemtrace server --broker-url amqp://guest:guest@localhost:5672//
171
+ ```
172
+
164
173
  **Option B: Embed in your FastAPI app** (no extra container)
165
174
 
166
175
  ```python
@@ -174,7 +183,7 @@ stemtrace.init_app(app, broker_url="redis://localhost:6379/0")
174
183
 
175
184
  Access at `/stemtrace/` in your existing app — no new services to deploy.
176
185
 
177
- See [Deployment Options](#️-deployment-options) for auth, scaling, and more.
186
+ See [Deployment Options](#deployment-options) for auth, scaling, and more.
178
187
 
179
188
  ## 📦 Architecture
180
189
 
@@ -304,7 +313,7 @@ batch_processor
304
313
  | Broker | URL Scheme | Status |
305
314
  |--------|------------|--------|
306
315
  | Redis | `redis://`, `rediss://` | ✅ Supported |
307
- | RabbitMQ | `amqp://`, `amqps://` | 🚧 Planned |
316
+ | RabbitMQ | `amqp://`, `amqps://`, `pyamqp://` | ✅ Supported |
308
317
 
309
318
  ## 🐳 Docker
310
319
 
@@ -314,6 +323,14 @@ docker run -p 8000:8000 \
314
323
  ghcr.io/iansokolskyi/stemtrace
315
324
  ```
316
325
 
326
+ RabbitMQ example:
327
+
328
+ ```bash
329
+ docker run -p 8000:8000 \
330
+ -e STEMTRACE_BROKER_URL=amqp://guest:guest@host.docker.internal:5672// \
331
+ ghcr.io/iansokolskyi/stemtrace
332
+ ```
333
+
317
334
  Or with Docker Compose:
318
335
 
319
336
  ```yaml
@@ -326,6 +343,8 @@ services:
326
343
  - STEMTRACE_BROKER_URL=redis://redis:6379/0
327
344
  ```
328
345
 
346
+ For a local RabbitMQ setup, see [`docker-compose.rabbitmq.yml`](docker-compose.rabbitmq.yml).
347
+
329
348
  ## 🖥️ Deployment Options
330
349
 
331
350
  `stemtrace` offers two deployment modes depending on your needs:
@@ -436,12 +455,12 @@ stemtrace.init_app(
436
455
  - ✅ **Sensitive data scrubbing** — Passwords and API keys filtered automatically
437
456
  - ✅ **Real-time updates** — WebSocket-powered live dashboard
438
457
  - ✅ **FastAPI integration** — Mount into your existing app
458
+ - ✅ **RabbitMQ support** — Use your existing RabbitMQ broker (`amqp://`, `amqps://`, `pyamqp://`)
439
459
  - ✅ **Workers page** — Monitor online/offline workers and their registered tasks
440
460
  - ✅ **Task registry** — Browse discovered + registered tasks with clear status badges
441
461
 
442
462
  ### Coming Soon
443
463
 
444
- - 🔜 **RabbitMQ support** — Use your existing RabbitMQ broker
445
464
  - 🔜 **Anomaly detection** — Spot stuck, orphaned, or failed tasks
446
465
  - 🔜 **Dashboard with stats** — Success rates, durations, failure trends
447
466
  - 🔜 **OpenTelemetry export** — Send traces to Jaeger, Tempo, Datadog
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Zero-infrastructure Celery task flow visualizer**
4
4
 
5
- [![PyPI version](https://img.shields.io/pypi/v/stemtrace?color=darklime)](https://pypi.org/project/stemtrace)
5
+ [![PyPI version](https://img.shields.io/badge/pypi-v0.3.0-darklime)](https://pypi.org/project/stemtrace)
6
6
  [![Python](https://img.shields.io/pypi/pyversions/stemtrace.svg)](https://pypi.org/project/stemtrace/)
7
7
  [![CI](https://github.com/iansokolskyi/stemtrace/actions/workflows/ci.yml/badge.svg)](https://github.com/iansokolskyi/stemtrace/actions/workflows/ci.yml)
8
8
  [![codecov](https://codecov.io/gh/iansokolskyi/stemtrace/graph/badge.svg)](https://codecov.io/gh/iansokolskyi/stemtrace)
@@ -18,7 +18,7 @@ Ever stared at a failed Celery task wondering "what called this?" or "why did it
18
18
 
19
19
  Stemtrace captures your task executions as a graph — visualize parent→child flows, see retry chains, track groups and chords, all without adding any new infrastructure.
20
20
 
21
- **Today stemtrace supports Redis** for event transport (via Redis Streams). **RabbitMQ support is planned.**
21
+ **stemtrace supports Redis and RabbitMQ** for event transport.
22
22
 
23
23
  ## ✨ Features
24
24
 
@@ -37,7 +37,7 @@ Stemtrace captures your task executions as a graph — visualize parent→child
37
37
  - **Registry status badges** — Quickly spot tasks that are active, never run, or not registered by any current worker
38
38
 
39
39
  **Production Ready**
40
- - **Zero Infrastructure** — Uses your existing Redis broker, no database needed
40
+ - **Zero Infrastructure** — Uses your existing broker (Redis or RabbitMQ), no database needed
41
41
  - **Sensitive Data Scrubbing** — Passwords and API keys filtered automatically
42
42
  - **Read-Only** — Safe for production; never modifies your task queue
43
43
  - **FastAPI Integration** — Mount into your existing app with one line
@@ -108,6 +108,14 @@ stemtrace server
108
108
 
109
109
  Open [http://localhost:8000](http://localhost:8000).
110
110
 
111
+ Tip: make sure the server is pointed at the same broker as your workers:
112
+
113
+ ```bash
114
+ stemtrace server --broker-url redis://localhost:6379/0
115
+ # or:
116
+ stemtrace server --broker-url amqp://guest:guest@localhost:5672//
117
+ ```
118
+
111
119
  **Option B: Embed in your FastAPI app** (no extra container)
112
120
 
113
121
  ```python
@@ -121,7 +129,7 @@ stemtrace.init_app(app, broker_url="redis://localhost:6379/0")
121
129
 
122
130
  Access at `/stemtrace/` in your existing app — no new services to deploy.
123
131
 
124
- See [Deployment Options](#️-deployment-options) for auth, scaling, and more.
132
+ See [Deployment Options](#deployment-options) for auth, scaling, and more.
125
133
 
126
134
  ## 📦 Architecture
127
135
 
@@ -251,7 +259,7 @@ batch_processor
251
259
  | Broker | URL Scheme | Status |
252
260
  |--------|------------|--------|
253
261
  | Redis | `redis://`, `rediss://` | ✅ Supported |
254
- | RabbitMQ | `amqp://`, `amqps://` | 🚧 Planned |
262
+ | RabbitMQ | `amqp://`, `amqps://`, `pyamqp://` | ✅ Supported |
255
263
 
256
264
  ## 🐳 Docker
257
265
 
@@ -261,6 +269,14 @@ docker run -p 8000:8000 \
261
269
  ghcr.io/iansokolskyi/stemtrace
262
270
  ```
263
271
 
272
+ RabbitMQ example:
273
+
274
+ ```bash
275
+ docker run -p 8000:8000 \
276
+ -e STEMTRACE_BROKER_URL=amqp://guest:guest@host.docker.internal:5672// \
277
+ ghcr.io/iansokolskyi/stemtrace
278
+ ```
279
+
264
280
  Or with Docker Compose:
265
281
 
266
282
  ```yaml
@@ -273,6 +289,8 @@ services:
273
289
  - STEMTRACE_BROKER_URL=redis://redis:6379/0
274
290
  ```
275
291
 
292
+ For a local RabbitMQ setup, see [`docker-compose.rabbitmq.yml`](docker-compose.rabbitmq.yml).
293
+
276
294
  ## 🖥️ Deployment Options
277
295
 
278
296
  `stemtrace` offers two deployment modes depending on your needs:
@@ -383,12 +401,12 @@ stemtrace.init_app(
383
401
  - ✅ **Sensitive data scrubbing** — Passwords and API keys filtered automatically
384
402
  - ✅ **Real-time updates** — WebSocket-powered live dashboard
385
403
  - ✅ **FastAPI integration** — Mount into your existing app
404
+ - ✅ **RabbitMQ support** — Use your existing RabbitMQ broker (`amqp://`, `amqps://`, `pyamqp://`)
386
405
  - ✅ **Workers page** — Monitor online/offline workers and their registered tasks
387
406
  - ✅ **Task registry** — Browse discovered + registered tasks with clear status badges
388
407
 
389
408
  ### Coming Soon
390
409
 
391
- - 🔜 **RabbitMQ support** — Use your existing RabbitMQ broker
392
410
  - 🔜 **Anomaly detection** — Spot stuck, orphaned, or failed tasks
393
411
  - 🔜 **Dashboard with stats** — Success rates, durations, failure trends
394
412
  - 🔜 **OpenTelemetry export** — Send traces to Jaeger, Tempo, Datadog
@@ -0,0 +1,88 @@
1
+ # Docker Compose for stemtrace E2E testing (RabbitMQ broker)
2
+ #
3
+ # Usage:
4
+ # docker compose -f docker-compose.e2e.rabbitmq.yml up -d --wait
5
+ # docker compose -f docker-compose.e2e.rabbitmq.yml down -v
6
+ #
7
+ # Services:
8
+ # - rabbitmq: RabbitMQ broker (with management UI)
9
+ # - worker: Celery worker running E2E test tasks
10
+ # - server: stemtrace server with UI and API
11
+
12
+ services:
13
+ rabbitmq:
14
+ image: rabbitmq:3-management
15
+ ports:
16
+ - "5672:5672"
17
+ - "15672:15672"
18
+ healthcheck:
19
+ test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
20
+ interval: 2s
21
+ timeout: 5s
22
+ retries: 20
23
+
24
+ redis:
25
+ image: redis:7-alpine
26
+ ports:
27
+ - "16380:6379" # Dedicated port for RabbitMQ E2E result backend
28
+ healthcheck:
29
+ test: ["CMD", "redis-cli", "ping"]
30
+ interval: 2s
31
+ timeout: 2s
32
+ retries: 10
33
+
34
+ worker:
35
+ build:
36
+ context: .
37
+ dockerfile: Dockerfile.e2e
38
+ environment:
39
+ - CELERY_BROKER_URL=amqp://guest:guest@rabbitmq:5672//
40
+ # Redis result backend required for group->callback workflows (Celery upgrades
41
+ # chain(group(...), callback) to a chord, which rpc:// does not support).
42
+ - CELERY_RESULT_BACKEND=redis://redis:6379/1
43
+ depends_on:
44
+ rabbitmq:
45
+ condition: service_healthy
46
+ redis:
47
+ condition: service_healthy
48
+ command: ["celery", "-A", "tests.e2e.tasks", "worker", "--loglevel=info", "--concurrency=2", "-E"]
49
+ healthcheck:
50
+ test: ["CMD", "celery", "-A", "tests.e2e.tasks", "inspect", "ping"]
51
+ interval: 5s
52
+ timeout: 10s
53
+ retries: 10
54
+ start_period: 10s
55
+
56
+ server:
57
+ build:
58
+ context: .
59
+ dockerfile: Dockerfile
60
+ ports:
61
+ - "8000:8000"
62
+ environment:
63
+ - STEMTRACE_BROKER_URL=amqp://guest:guest@rabbitmq:5672//
64
+ depends_on:
65
+ rabbitmq:
66
+ condition: service_healthy
67
+ command:
68
+ [
69
+ "server",
70
+ "--broker-url",
71
+ "amqp://guest:guest@rabbitmq:5672//",
72
+ "--host",
73
+ "0.0.0.0",
74
+ "--port",
75
+ "8000",
76
+ ]
77
+ healthcheck:
78
+ test:
79
+ [
80
+ "CMD",
81
+ "python",
82
+ "-c",
83
+ "import httpx; httpx.get('http://localhost:8000/stemtrace/api/health').raise_for_status()",
84
+ ]
85
+ interval: 5s
86
+ timeout: 10s
87
+ retries: 10
88
+ start_period: 5s
@@ -0,0 +1,44 @@
1
+ # Docker Compose for stemtrace with RabbitMQ
2
+ #
3
+ # Usage:
4
+ # docker compose -f docker-compose.rabbitmq.yml up -d
5
+ # docker compose -f docker-compose.rabbitmq.yml logs -f server
6
+ # docker compose -f docker-compose.rabbitmq.yml down
7
+ #
8
+ # Access:
9
+ # - stemtrace UI: http://localhost:8000
10
+ # - RabbitMQ management UI: http://localhost:15672 (guest/guest)
11
+
12
+ services:
13
+ rabbitmq:
14
+ image: rabbitmq:3-management
15
+ ports:
16
+ - "5672:5672"
17
+ - "15672:15672"
18
+ healthcheck:
19
+ test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
20
+ interval: 5s
21
+ timeout: 5s
22
+ retries: 10
23
+
24
+ server:
25
+ build:
26
+ context: .
27
+ dockerfile: Dockerfile
28
+ ports:
29
+ - "8000:8000"
30
+ environment:
31
+ - STEMTRACE_BROKER_URL=amqp://guest:guest@rabbitmq:5672//
32
+ depends_on:
33
+ rabbitmq:
34
+ condition: service_healthy
35
+ command:
36
+ [
37
+ "server",
38
+ "--broker-url",
39
+ "amqp://guest:guest@rabbitmq:5672//",
40
+ "--host",
41
+ "0.0.0.0",
42
+ "--port",
43
+ "8000",
44
+ ]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "stemtrace"
3
- version = "0.2.1"
3
+ version = "0.3.0"
4
4
  description = "A lightweight Celery task flow visualizer"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -8,6 +8,9 @@ requires-python = ">=3.10"
8
8
  authors = [
9
9
  { name = "Ian Sokolskyi", email = "iansokolskyi@gmail.com" },
10
10
  ]
11
+ maintainers = [
12
+ { name = "Ian Sokolskyi", email = "iansokolskyi@gmail.com" },
13
+ ]
11
14
  keywords = ["celery", "task", "queue", "visualization", "monitoring", "workflow"]
12
15
  classifiers = [
13
16
  "Development Status :: 3 - Alpha",
@@ -106,6 +109,14 @@ ignore_missing_imports = true
106
109
  module = "typer.*"
107
110
  ignore_missing_imports = true
108
111
 
112
+ [[tool.mypy.overrides]]
113
+ module = "kombu.*"
114
+ ignore_missing_imports = true
115
+
116
+ [[tool.mypy.overrides]]
117
+ module = "amqp.*"
118
+ ignore_missing_imports = true
119
+
109
120
  # =============================================================================
110
121
  # ruff
111
122
  # =============================================================================
@@ -0,0 +1,41 @@
1
+ """Wait for an HTTP endpoint to respond with a 2xx status."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import time
7
+ import urllib.error
8
+ import urllib.request
9
+
10
+
11
+ def _parse_args() -> argparse.Namespace:
12
+ parser = argparse.ArgumentParser(description=__doc__)
13
+ parser.add_argument("url")
14
+ parser.add_argument("--timeout", type=float, default=60.0)
15
+ parser.add_argument("--interval", type=float, default=2.0)
16
+ return parser.parse_args()
17
+
18
+
19
+ def main() -> None:
20
+ """Wait for an HTTP endpoint to become healthy (2xx) or exit non-zero."""
21
+ args = _parse_args()
22
+ deadline = time.monotonic() + args.timeout
23
+ last_error: str | None = None
24
+
25
+ while time.monotonic() < deadline:
26
+ try:
27
+ request = urllib.request.Request(args.url, method="GET")
28
+ with urllib.request.urlopen(request, timeout=2.0) as response:
29
+ if 200 <= response.status < 300:
30
+ return
31
+ last_error = f"HTTP {response.status}"
32
+ except (urllib.error.URLError, TimeoutError) as exc:
33
+ last_error = str(exc)
34
+
35
+ time.sleep(args.interval)
36
+
37
+ raise SystemExit(f"Service not healthy within {args.timeout}s: {last_error}")
38
+
39
+
40
+ if __name__ == "__main__":
41
+ main()
@@ -38,7 +38,7 @@ if TYPE_CHECKING:
38
38
  from celery import Celery
39
39
  from fastapi import FastAPI
40
40
 
41
- __version__ = "0.2.1"
41
+ __version__ = "0.3.0"
42
42
  __all__ = [
43
43
  "ConfigurationError",
44
44
  "StemtraceConfig",
@@ -21,5 +21,5 @@ class UnsupportedBrokerError(ConfigurationError):
21
21
  self.scheme = scheme
22
22
  super().__init__(
23
23
  f"Unsupported broker scheme: '{scheme}'. "
24
- f"Supported: redis, rediss, amqp, amqps, memory"
24
+ f"Supported: redis, rediss, amqp, amqps, pyamqp, memory"
25
25
  )