patchwork-client-redis 1.0.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 (36) hide show
  1. patchwork_client_redis-1.0.0/.gitignore +68 -0
  2. patchwork_client_redis-1.0.0/.gitlab-ci.yml +220 -0
  3. patchwork_client_redis-1.0.0/.idea/inspectionProfiles/Project_Default.xml +25 -0
  4. patchwork_client_redis-1.0.0/.idea/inspectionProfiles/profiles_settings.xml +6 -0
  5. patchwork_client_redis-1.0.0/.idea/patchwork-client-redis.iml +12 -0
  6. patchwork_client_redis-1.0.0/LICENSE +21 -0
  7. patchwork_client_redis-1.0.0/PKG-INFO +50 -0
  8. patchwork_client_redis-1.0.0/README.md +25 -0
  9. patchwork_client_redis-1.0.0/doc/docs/changelog.md +13 -0
  10. patchwork_client_redis-1.0.0/doc/docs/contribution.md +23 -0
  11. patchwork_client_redis-1.0.0/doc/docs/getstarted.md +58 -0
  12. patchwork_client_redis-1.0.0/doc/docs/index.md +29 -0
  13. patchwork_client_redis-1.0.0/doc/docs/license.md +21 -0
  14. patchwork_client_redis-1.0.0/doc/docs/source.md +9 -0
  15. patchwork_client_redis-1.0.0/doc/docs/usage.md +116 -0
  16. patchwork_client_redis-1.0.0/doc/mkdocs.yml +87 -0
  17. patchwork_client_redis-1.0.0/docker-compose.ci.yml +8 -0
  18. patchwork_client_redis-1.0.0/int/test_integration.py +59 -0
  19. patchwork_client_redis-1.0.0/patchwork/client/redis/__init__.py +2 -0
  20. patchwork_client_redis-1.0.0/patchwork/client/redis/common.py +24 -0
  21. patchwork_client_redis-1.0.0/patchwork/client/redis/publisher.py +129 -0
  22. patchwork_client_redis-1.0.0/patchwork/client/redis/subscriber.py +398 -0
  23. patchwork_client_redis-1.0.0/patchwork_client_redis.egg-info/PKG-INFO +50 -0
  24. patchwork_client_redis-1.0.0/patchwork_client_redis.egg-info/SOURCES.txt +34 -0
  25. patchwork_client_redis-1.0.0/patchwork_client_redis.egg-info/dependency_links.txt +1 -0
  26. patchwork_client_redis-1.0.0/patchwork_client_redis.egg-info/requires.txt +7 -0
  27. patchwork_client_redis-1.0.0/patchwork_client_redis.egg-info/scm_file_list.json +31 -0
  28. patchwork_client_redis-1.0.0/patchwork_client_redis.egg-info/scm_version.json +8 -0
  29. patchwork_client_redis-1.0.0/patchwork_client_redis.egg-info/top_level.txt +1 -0
  30. patchwork_client_redis-1.0.0/pyproject.toml +115 -0
  31. patchwork_client_redis-1.0.0/setup.cfg +4 -0
  32. patchwork_client_redis-1.0.0/tests/__init__.py +0 -0
  33. patchwork_client_redis-1.0.0/tests/conftest.py +36 -0
  34. patchwork_client_redis-1.0.0/tests/test_client.py +233 -0
  35. patchwork_client_redis-1.0.0/tests/test_contract.py +36 -0
  36. patchwork_client_redis-1.0.0/uv.lock +1548 -0
@@ -0,0 +1,68 @@
1
+ # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
2
+ # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
3
+
4
+ # User-specific stuff
5
+ .idea/**/workspace.xml
6
+ .idea/**/tasks.xml
7
+ .idea/**/dictionaries
8
+ .idea/**/shelf
9
+ .idea/**/modules.xml
10
+
11
+ # Sensitive or high-churn files
12
+ .idea/**/dataSources/
13
+ .idea/**/dataSources.ids
14
+ .idea/**/dataSources.local.xml
15
+ .idea/**/sqlDataSources.xml
16
+ .idea/**/dynamic.xml
17
+ .idea/**/uiDesigner.xml
18
+ .idea/**/dbnavigator.xml
19
+
20
+ # Gradle
21
+ .idea/**/gradle.xml
22
+ .idea/**/libraries
23
+
24
+ # CMake
25
+ cmake-build-debug/
26
+ cmake-build-release/
27
+
28
+ # Mongo Explorer plugin
29
+ .idea/**/mongoSettings.xml
30
+
31
+ # File-based project format
32
+ *.iws
33
+
34
+ # IntelliJ
35
+ out/
36
+
37
+ # mpeltonen/sbt-idea plugin
38
+ .idea_modules/
39
+
40
+ # JIRA plugin
41
+ atlassian-ide-plugin.xml
42
+
43
+ # Cursive Clojure plugin
44
+ .idea/replstate.xml
45
+
46
+ # Crashlytics plugin (for Android Studio and IntelliJ)
47
+ com_crashlytics_export_strings.xml
48
+ crashlytics.properties
49
+ crashlytics-build.properties
50
+ fabric.properties
51
+
52
+ # Editor-based Rest Client
53
+ .idea/httpRequests
54
+
55
+ # lib build
56
+ build/
57
+ dist/
58
+ django-pool.egg.info/
59
+ .env/
60
+ django_pool.egg-info/
61
+ /doc/site/
62
+ /node/patchwork/node/settings.json
63
+ .pytest_cache/
64
+ /patchwork_client_kafka.egg-info/
65
+ **/__pycache__
66
+ *.pyc
67
+ # build metadata
68
+ *.egg-info/
@@ -0,0 +1,220 @@
1
+ # Advise GitLab that these environment vars should be loaded from the Variables config.
2
+ variables:
3
+ PROD_PYPI_TOKEN: SECURE
4
+ TEST_PYPI_TOKEN: SECURE
5
+
6
+ include:
7
+ - template: Dependency-Scanning.gitlab-ci.yml
8
+
9
+ default:
10
+ image: ghcr.io/astral-sh/uv:python3.11-bookworm
11
+
12
+ gemnasium-python-dependency_scanning:
13
+ rules:
14
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
15
+
16
+ stages:
17
+ - test
18
+ - build
19
+ - deploy
20
+
21
+ .test:
22
+ cache:
23
+ key: uv-cache
24
+ paths:
25
+ - .uv/
26
+ - .cache/uv/
27
+
28
+ before_script:
29
+ - uv --version
30
+ - uv sync --all-extras --dev
31
+
32
+ script:
33
+ - uv run pytest tests
34
+
35
+ # Python matrix tests
36
+ test 3.11:
37
+ extends: .test
38
+ image: ghcr.io/astral-sh/uv:python3.11-bookworm
39
+
40
+ test 3.12:
41
+ extends: .test
42
+ image: ghcr.io/astral-sh/uv:python3.12-bookworm
43
+
44
+ test 3.13:
45
+ extends: .test
46
+ image: ghcr.io/astral-sh/uv:python3.13-bookworm
47
+
48
+
49
+ coverage:
50
+ image: ghcr.io/astral-sh/uv:python3.11-bookworm
51
+
52
+ only:
53
+ - master
54
+ - merge_requests
55
+
56
+ before_script:
57
+ - uv sync --all-extras --dev
58
+
59
+ script:
60
+ - uv run pytest --cov=. tests
61
+ - uv run coverage xml
62
+
63
+ coverage: '/TOTAL.+ ([0-9]{1,3}%)/'
64
+
65
+
66
+ doc:
67
+ stage: build
68
+
69
+ only:
70
+ - /^client-redis-\d+\.\d+(\.\d+)?(\.?(a|b|rc)\d*)?$/
71
+ - merge_requests
72
+
73
+ script:
74
+ - uv sync --extra docs
75
+ - uv run mkdocs build -f doc/mkdocs.yml
76
+
77
+ artifacts:
78
+ paths:
79
+ - doc/site/
80
+ expire_in: 1d
81
+
82
+ pages:
83
+ stage: deploy
84
+ only:
85
+ - /^client-redis-\d+\.\d+(\.\d+)?(\.?(a|b|rc)\d*)?$/
86
+
87
+ needs:
88
+ - job: doc
89
+ artifacts: true
90
+
91
+ script:
92
+ - mkdir -p public/
93
+ - cp -r doc/site/* public/
94
+
95
+ artifacts:
96
+ paths:
97
+ - public
98
+
99
+ compute_version:
100
+ stage: test
101
+ image: ghcr.io/astral-sh/uv:python3.11-bookworm
102
+
103
+ before_script:
104
+ - git checkout -B "$CI_COMMIT_REF_NAME" "$CI_COMMIT_SHA"
105
+ - uv sync --group dev
106
+
107
+ script:
108
+ - git fetch --tags --unshallow || git fetch --tags
109
+ - |
110
+ LAST=$(uv run semantic-release version --print-last-released)
111
+ NEXT=$(uv run semantic-release version --print)
112
+ if [ "$LAST" = "$NEXT" ]; then
113
+ echo "SHOULD_RELEASE=false" >> release.env
114
+ echo "VERSION=" >> release.env
115
+ echo "No new version to release, skipping RC build"
116
+ else
117
+ echo "SHOULD_RELEASE=true" >> release.env
118
+ echo "VERSION=$NEXT" >> release.env
119
+ echo "Next version: $NEXT"
120
+ fi
121
+
122
+ artifacts:
123
+ reports:
124
+ dotenv: release.env
125
+
126
+ only:
127
+ - master
128
+
129
+ publish_rc:
130
+ stage: build
131
+ image: ghcr.io/astral-sh/uv:python3.11-bookworm
132
+
133
+ needs:
134
+ - job: compute_version
135
+ artifacts: true
136
+
137
+ rules:
138
+ - if: '$CI_COMMIT_BRANCH == "master"'
139
+
140
+ before_script:
141
+ - |
142
+ if [ "$SHOULD_RELEASE" = "true" ]; then
143
+ echo "Publishing RC for version $VERSION"
144
+ # your publish logic here
145
+ else
146
+ echo "No release needed, skipping publish"
147
+ exit 0
148
+ fi
149
+ - git fetch --tags --unshallow || true
150
+ - uv sync --group dev
151
+
152
+ script: |
153
+ BASE_TAG=$(git describe --tags --abbrev=0 --match "client-redis-*" 2>/dev/null || echo "")
154
+ if [ -n "$BASE_TAG" ]; then
155
+ RC=$(git rev-list ${BASE_TAG}..HEAD --count)
156
+ else
157
+ RC=$(git rev-list HEAD --count)
158
+ fi
159
+ RC_VERSION="${VERSION}rc${RC}"
160
+ echo "Building RC version: $RC_VERSION"
161
+ export SETUPTOOLS_SCM_PRETEND_VERSION="$RC_VERSION"
162
+ uv build
163
+ ls -lah dist/
164
+ uv publish --index testpypi --token "$TEST_PYPI_TOKEN"
165
+
166
+ tag_release:
167
+ stage: deploy
168
+ image: ghcr.io/astral-sh/uv:python3.11-bookworm
169
+ when: manual
170
+
171
+ needs:
172
+ - job: compute_version
173
+ artifacts: true
174
+
175
+ rules:
176
+ - if: '$CI_COMMIT_BRANCH == "master"'
177
+
178
+ before_script:
179
+ - |
180
+ if [ "$SHOULD_RELEASE" = "true" ]; then
181
+ echo "Releasing for version $VERSION"
182
+ else
183
+ echo "No pending RC release, can't create release tag"
184
+ exit 1
185
+ fi
186
+ - apt-get update
187
+ - export DEBIAN_FRONTEND=noninteractive
188
+ - apt-get -y install git curl jq gawk
189
+
190
+ script: |
191
+ git fetch --tags
192
+ TAG="client-redis-$VERSION"
193
+ export VERSION_TAG_EXISTS=$(git tag | grep $VERSION | wc -l)
194
+ test $VERSION_TAG_EXISTS -eq 1 && exit 0 # exit if version already exist
195
+ echo "Creating release of version $VERSION"
196
+ jq -n --arg version "$TAG" --arg desc "$CI_COMMIT_MESSAGE" --arg sha "$CI_COMMIT_SHA" '{ "name":$version, "tag_name":$version, "description":$desc, "ref":$sha, "assets":{}}' > release-tmp.txt
197
+ cat release-tmp.txt
198
+ curl --header "Content-Type:application/json" --header "PRIVATE-TOKEN:$RELEASE_API_TOKEN" --data @release-tmp.txt --request POST $CI_API_V4_URL/projects/$CI_PROJECT_ID/releases -v
199
+
200
+
201
+ upload_pypi:
202
+ stage: deploy
203
+ image: ghcr.io/astral-sh/uv:python3.11-bookworm
204
+
205
+ before_script:
206
+ - git fetch --tags --unshallow || true
207
+ - uv sync --group dev
208
+
209
+ script:
210
+ - FULL_TAG=$(git describe --tags --exact-match --match "client-redis-*")
211
+ - VERSION=${FULL_TAG#client-redis-}
212
+ - echo "Publishing version $VERSION"
213
+
214
+ - export SETUPTOOLS_SCM_PRETEND_VERSION="$VERSION"
215
+
216
+ - uv build
217
+ - uv publish --token $PROD_PYPI_TOKEN
218
+
219
+ only:
220
+ - /^client-redis-\d+\.\d+(\.\d+)?(\.?(a|b|rc)\d*)?$/
@@ -0,0 +1,25 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
5
+ <inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
6
+ <option name="ourVersions">
7
+ <value>
8
+ <list size="2">
9
+ <item index="0" class="java.lang.String" itemvalue="3.10" />
10
+ <item index="1" class="java.lang.String" itemvalue="3.11" />
11
+ </list>
12
+ </value>
13
+ </option>
14
+ </inspection_tool>
15
+ <inspection_tool class="PyInterpreterInspection" enabled="false" level="WARNING" enabled_by_default="false" />
16
+ <inspection_tool class="PyPackageRequirementsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
17
+ <inspection_tool class="PyStubPackagesAdvertiser" enabled="true" level="WARNING" enabled_by_default="true">
18
+ <option name="ignoredPackages">
19
+ <list>
20
+ <option value="pandas" />
21
+ </list>
22
+ </option>
23
+ </inspection_tool>
24
+ </profile>
25
+ </component>
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <settings>
3
+ <option name="USE_PROJECT_PROFILE" value="false" />
4
+ <version value="1.0" />
5
+ </settings>
6
+ </component>
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="PYTHON_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$" />
5
+ <orderEntry type="inheritedJdk" />
6
+ <orderEntry type="sourceFolder" forTests="false" />
7
+ </component>
8
+ <component name="PackageRequirementsSettings" />
9
+ <component name="PyDocumentationSettings" />
10
+ <component name="ReSTService" />
11
+ <component name="TestRunnerService" />
12
+ </module>
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,50 @@
1
+ Metadata-Version: 2.4
2
+ Name: patchwork-client-redis
3
+ Version: 1.0.0
4
+ Summary: Redis Streams client for Patchwork - The distributed asynchronous microframework
5
+ Author: Paweł Pecio
6
+ License: MIT
7
+ Classifier: Development Status :: 5 - Production/Stable
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: POSIX :: Linux
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: Implementation :: CPython
14
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
15
+ Requires-Python: >=3.11.0
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: patchwork-core<3,>=2.0.0
19
+ Requires-Dist: redis>=5.0
20
+ Provides-Extra: docs
21
+ Requires-Dist: mkdocs<2,==1.6.1; extra == "docs"
22
+ Requires-Dist: mkdocs-material; extra == "docs"
23
+ Requires-Dist: mkdocstrings[python]; extra == "docs"
24
+ Dynamic: license-file
25
+
26
+ # Patchwork Client Redis
27
+
28
+ Redis Streams client for Patchwork - an asynchronous distributed microframework.
29
+
30
+ ## Requirements
31
+
32
+ * Python 3.11+
33
+ * Redis 7.0+
34
+ * `patchwork-core` 2.0+
35
+
36
+ ## Installation
37
+
38
+ ``pip install patchwork-client-redis``
39
+
40
+ ## Development
41
+
42
+ ```bash
43
+ uv sync --all-extras --dev
44
+ uv run pytest tests
45
+ REDIS_URL=redis://127.0.0.1:6379/0 uv run pytest int
46
+ ```
47
+
48
+ ## Documentation
49
+
50
+ https://patchwork-framework.gitlab.io/redis-client
@@ -0,0 +1,25 @@
1
+ # Patchwork Client Redis
2
+
3
+ Redis Streams client for Patchwork - an asynchronous distributed microframework.
4
+
5
+ ## Requirements
6
+
7
+ * Python 3.11+
8
+ * Redis 7.0+
9
+ * `patchwork-core` 2.0+
10
+
11
+ ## Installation
12
+
13
+ ``pip install patchwork-client-redis``
14
+
15
+ ## Development
16
+
17
+ ```bash
18
+ uv sync --all-extras --dev
19
+ uv run pytest tests
20
+ REDIS_URL=redis://127.0.0.1:6379/0 uv run pytest int
21
+ ```
22
+
23
+ ## Documentation
24
+
25
+ https://patchwork-framework.gitlab.io/redis-client
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0
4
+
5
+ First release:
6
+
7
+ - `AsyncRedisPublisher` (`XADD`) and `AsyncRedisSubscriber` (`XREADGROUP` consumer groups)
8
+ - commits with `XACK` in any order, native rollback with `XCLAIM` and broker delivery counter
9
+ - taking over messages of dead consumers with `XAUTOCLAIM` (`claim_idle_ms`), recovery of own pending messages
10
+ after restart with a stable consumer name
11
+ - automatic consumer group creation and re-creation, retries on connection errors, subscriber failure instead
12
+ of hanging
13
+ - passes Patchwork client contract tests (patchwork-core 2.0)
@@ -0,0 +1,23 @@
1
+ # Contribution
2
+
3
+ ```bash
4
+ uv sync --all-extras --dev
5
+ uv run pytest tests
6
+ uv run ruff check patchwork tests int
7
+ ```
8
+
9
+ Unit tests and client contract tests in `tests/` run against [fakeredis](https://github.com/cunla/fakeredis-py).
10
+ To run them against a real Redis set `REDIS_TEST_URL`, the database is **flushed** before each test, use
11
+ a dedicated one:
12
+
13
+ ```bash
14
+ docker compose -f docker-compose.ci.yml up -d
15
+ REDIS_TEST_URL=redis://127.0.0.1:6379/15 uv run pytest tests
16
+ ```
17
+
18
+ Integration tests in `int/` run the client contract test suite against a real Redis (keys are prefixed and removed
19
+ after tests):
20
+
21
+ ```bash
22
+ REDIS_URL=redis://127.0.0.1:6379/0 uv run pytest int
23
+ ```
@@ -0,0 +1,58 @@
1
+ # Getting started
2
+
3
+ ```python
4
+ import asyncio
5
+
6
+ from patchwork.client.redis import AsyncRedisPublisher, AsyncRedisSubscriber
7
+
8
+ URL = 'redis://localhost:6379/0'
9
+
10
+
11
+ async def main():
12
+ async with (
13
+ AsyncRedisPublisher(url=URL) as publisher,
14
+ AsyncRedisSubscriber(url=URL, queues=['orders'], group='billing') as subscriber,
15
+ ):
16
+ await publisher.send({'order': 1}, queue='orders', type='order.created')
17
+
18
+ delivery = await subscriber.get(timeout=5)
19
+ print(delivery.message.type, delivery.message.get_payload())
20
+ await subscriber.commit(delivery)
21
+
22
+
23
+ asyncio.run(main())
24
+ ```
25
+
26
+ ## With Patchwork node
27
+
28
+ ```python
29
+ from patchwork.client.redis import AsyncRedisPublisher, AsyncRedisSubscriber
30
+ from patchwork.node import Worker
31
+ from patchwork.node.core import TaskRouter
32
+ from patchwork.node.node import run
33
+ from patchwork.node.processor import InlineUnit
34
+
35
+ URL = 'redis://redis:6379/0'
36
+
37
+ router = TaskRouter(processor=InlineUnit(concurrency=10))
38
+
39
+
40
+ @router.on('order.created')
41
+ async def order_created(message):
42
+ ...
43
+
44
+
45
+ worker = Worker(
46
+ subscriber=AsyncRedisSubscriber(url=URL, queues=['orders'], group='billing', consumer='billing-0'),
47
+ publisher=AsyncRedisPublisher(url=URL, postpone_queue='postpone'),
48
+ )
49
+ worker.add_router(router)
50
+
51
+ if __name__ == '__main__':
52
+ run(worker)
53
+ ```
54
+
55
+ !!! hint
56
+
57
+ Set `consumer` to a stable name (eg. Kubernetes pod name), so messages pending on the consumer are delivered
58
+ again immediately after restart instead of waiting for `claim_idle_ms`.
@@ -0,0 +1,29 @@
1
+ # Patchwork Client Redis
2
+
3
+ [Redis Streams](https://redis.io/docs/latest/develop/data-types/streams/) client for
4
+ [Patchwork](https://patchwork-framework.gitlab.io/core): `AsyncRedisPublisher` and `AsyncRedisSubscriber`
5
+ implementing the Patchwork client contract.
6
+
7
+ - each queue is a stream, messages are appended with `XADD`
8
+ - subscribers read in consumer groups (`XREADGROUP`), each group receives all messages, consumers in a group
9
+ compete for messages
10
+ - commits acknowledge single messages (`XACK`) in any order
11
+ - native rollback: the message is claimed back and delivered again, broker delivery counter is reported as
12
+ `Delivery.redelivered`
13
+ - messages of consumers which went away are taken over after `claim_idle_ms` (`XAUTOCLAIM`)
14
+ - failures are never silent: connection errors are retried, then the subscriber stops and `get()` raises
15
+ `SubscriberClosed`
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install patchwork-client-redis
21
+ ```
22
+
23
+ Requires Python 3.11+, Redis 7.0+ and patchwork-core 2.0+.
24
+
25
+ !!! note
26
+
27
+ Redis streams don't support delayed delivery. Messages with `not_before` in the future are sent to the
28
+ publisher `postpone_queue` and forwarded by the [patchwork-postponer](https://gitlab.com/patchwork-framework/postponer)
29
+ service.
@@ -0,0 +1,21 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2019 - 2020
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,9 @@
1
+ # Source code
2
+
3
+ Project source code can be found at [GitLab](https://gitlab.com/patchwork-framework/redis-client).
4
+
5
+ Package name: `patchwork-client-redis`
6
+
7
+ ::: patchwork.client.redis.publisher
8
+ ::: patchwork.client.redis.subscriber
9
+ ::: patchwork.client.redis.common