DefStream-RabbitMQ 0.1.1__tar.gz → 0.1.1.2__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.
- defstream_rabbitmq-0.1.1.2/.github/workflows/ci.yml +403 -0
- defstream_rabbitmq-0.1.1.2/.gitignore +58 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/DefStream_RabbitMQ.egg-info/PKG-INFO +54 -6
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/DefStream_RabbitMQ.egg-info/SOURCES.txt +5 -2
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/PKG-INFO +54 -6
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/README.md +52 -5
- defstream_rabbitmq-0.1.1.2/sample/Sample.RPC.py +168 -0
- defstream_rabbitmq-0.1.1.2/sample/Sample.Stream.py +84 -0
- defstream_rabbitmq-0.1.1.2/sample/Sample.py +127 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/setup.py +7 -1
- defstream_rabbitmq-0.1.1/MANIFEST.in +0 -1
- defstream_rabbitmq-0.1.1/VERSION +0 -1
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/DefStream_RabbitMQ.egg-info/dependency_links.txt +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/DefStream_RabbitMQ.egg-info/requires.txt +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/DefStream_RabbitMQ.egg-info/top_level.txt +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/LICENSE +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/setup.cfg +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/src/Configuration.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/src/Connection.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/src/Consumer.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/src/Event.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/src/Exchange.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/src/Policies.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/src/Queue.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/src/Serializer.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/src/Stream.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/src/Subscription.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/src/__init__.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/test/test_broker_methods.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/test/test_rabbitmq_integration.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/test/test_rabbitmq_worker.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/test/test_rpc.py +0 -0
- {defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/test/test_rpc_integration.py +0 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [master]
|
|
6
|
+
push:
|
|
7
|
+
branches: [master]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
env:
|
|
13
|
+
RELEASE_SERIES: '0.1'
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
17
|
+
cancel-in-progress: false
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
changes:
|
|
21
|
+
name: Plan release version
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
timeout-minutes: 5
|
|
24
|
+
outputs:
|
|
25
|
+
release: ${{ steps.changes.outputs.release }}
|
|
26
|
+
version: ${{ steps.changes.outputs.version }}
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v7
|
|
29
|
+
with:
|
|
30
|
+
fetch-depth: 0
|
|
31
|
+
persist-credentials: false
|
|
32
|
+
- name: Set up release planner Python
|
|
33
|
+
uses: actions/setup-python@v7
|
|
34
|
+
with:
|
|
35
|
+
python-version: '3.13'
|
|
36
|
+
- name: Check complete push range and plan version
|
|
37
|
+
id: changes
|
|
38
|
+
env:
|
|
39
|
+
BEFORE: ${{ github.event.before }}
|
|
40
|
+
RELEASE_PUSH: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
|
41
|
+
run: |
|
|
42
|
+
python - <<'PY'
|
|
43
|
+
from os import environ
|
|
44
|
+
from pathlib import Path
|
|
45
|
+
from re import fullmatch
|
|
46
|
+
from subprocess import check_output
|
|
47
|
+
|
|
48
|
+
if environ['RELEASE_PUSH'] != 'true':
|
|
49
|
+
with Path(environ['GITHUB_OUTPUT']).open('a', encoding='utf-8') as output:
|
|
50
|
+
output.write('release=false\n')
|
|
51
|
+
raise SystemExit(0)
|
|
52
|
+
series = environ['RELEASE_SERIES']
|
|
53
|
+
if fullmatch(r'(0|[1-9]\d*)\.(0|[1-9]\d*)', series) is None:
|
|
54
|
+
raise ValueError(f'Invalid RELEASE_SERIES: {series!r}')
|
|
55
|
+
before = environ['BEFORE']
|
|
56
|
+
if not before:
|
|
57
|
+
raise ValueError('Missing push base commit')
|
|
58
|
+
first_push = set(before) == {'0'}
|
|
59
|
+
base = check_output(['git', 'hash-object', '-t', 'tree', '--stdin'], input='', text=True).strip() if first_push else before
|
|
60
|
+
changed = check_output(
|
|
61
|
+
['git', 'diff', '--name-only', '--no-renames', base, environ['GITHUB_SHA'], '--', 'src/'],
|
|
62
|
+
text=True,
|
|
63
|
+
).strip()
|
|
64
|
+
# Anchor to the pre-push history so a rerun ignores its own release tag.
|
|
65
|
+
tags = [] if first_push else check_output(['git', 'tag', '--merged', before], text=True).splitlines()
|
|
66
|
+
releases = []
|
|
67
|
+
for tag in tags:
|
|
68
|
+
match = fullmatch(r'v?(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?(?:\.post\d+)?', tag)
|
|
69
|
+
if match and f'{int(match[1])}.{int(match[2])}' == series:
|
|
70
|
+
releases.append(tuple(map(int, match.groups()[:3])) + (int(match[4] or 0),))
|
|
71
|
+
latest = max(releases) if releases else None
|
|
72
|
+
number = int(environ['GITHUB_RUN_NUMBER'])
|
|
73
|
+
if number < 1:
|
|
74
|
+
raise ValueError('Build number must be positive')
|
|
75
|
+
if latest is not None and number <= latest[3]:
|
|
76
|
+
raise ValueError('Build number must exceed the previous build; do not reset the workflow counter')
|
|
77
|
+
if changed:
|
|
78
|
+
patch = latest[2] + 1 if latest is not None else 0
|
|
79
|
+
print(f'Source changes:\n{changed}')
|
|
80
|
+
else:
|
|
81
|
+
if latest is None:
|
|
82
|
+
raise ValueError(
|
|
83
|
+
'No release tag in pre-push history for this series. '
|
|
84
|
+
'Tag the exact source commit of the existing PyPI release before retrying.'
|
|
85
|
+
)
|
|
86
|
+
patch = latest[2]
|
|
87
|
+
print('No src changes: keeping MAJOR.MINOR.PATCH and increasing BUILD')
|
|
88
|
+
version = f'{series}.{patch}.{number}'
|
|
89
|
+
print(f'Planned version: {version}')
|
|
90
|
+
with Path(environ['GITHUB_OUTPUT']).open('a', encoding='utf-8') as output:
|
|
91
|
+
output.write(f'release=true\nversion={version}\n')
|
|
92
|
+
PY
|
|
93
|
+
|
|
94
|
+
test:
|
|
95
|
+
name: Test Python ${{ matrix.python }}
|
|
96
|
+
needs: changes
|
|
97
|
+
runs-on: ubuntu-latest
|
|
98
|
+
timeout-minutes: 25
|
|
99
|
+
strategy:
|
|
100
|
+
fail-fast: false
|
|
101
|
+
matrix:
|
|
102
|
+
python: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
|
|
103
|
+
env:
|
|
104
|
+
PROJECT: ${{ github.event.repository.name }}
|
|
105
|
+
DEFSTREAM_RABBITMQ_TESTS: '1'
|
|
106
|
+
DEFSTREAM_REDIS_TESTS: '1'
|
|
107
|
+
services:
|
|
108
|
+
rabbitmq:
|
|
109
|
+
image: rabbitmq:4.1
|
|
110
|
+
ports:
|
|
111
|
+
- 5672:5672
|
|
112
|
+
env:
|
|
113
|
+
RABBITMQ_DEFAULT_USER: guest
|
|
114
|
+
RABBITMQ_DEFAULT_PASS: guest
|
|
115
|
+
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS: '-rabbit loopback_users []'
|
|
116
|
+
options: >-
|
|
117
|
+
--health-cmd "rabbitmq-diagnostics -q ping"
|
|
118
|
+
--health-interval 10s
|
|
119
|
+
--health-timeout 10s
|
|
120
|
+
--health-retries 12
|
|
121
|
+
redis:
|
|
122
|
+
image: redis:7.4
|
|
123
|
+
ports:
|
|
124
|
+
- 6379:6379
|
|
125
|
+
options: >-
|
|
126
|
+
--health-cmd "redis-cli ping"
|
|
127
|
+
--health-interval 5s
|
|
128
|
+
--health-timeout 5s
|
|
129
|
+
--health-retries 12
|
|
130
|
+
steps:
|
|
131
|
+
- name: Check out core
|
|
132
|
+
uses: actions/checkout@v7
|
|
133
|
+
with:
|
|
134
|
+
repository: yong5eon/DefStream
|
|
135
|
+
ref: ${{ github.event.repository.name == 'DefStream' && github.sha || 'master' }}
|
|
136
|
+
path: packages/DefStream
|
|
137
|
+
fetch-depth: 0
|
|
138
|
+
persist-credentials: false
|
|
139
|
+
|
|
140
|
+
- name: Check out RabbitMQ adapter
|
|
141
|
+
uses: actions/checkout@v7
|
|
142
|
+
with:
|
|
143
|
+
repository: yong5eon/DefStream-RabbitMQ
|
|
144
|
+
ref: ${{ github.event.repository.name == 'DefStream-RabbitMQ' && github.sha || 'master' }}
|
|
145
|
+
path: packages/DefStream-RabbitMQ
|
|
146
|
+
fetch-depth: 0
|
|
147
|
+
persist-credentials: false
|
|
148
|
+
|
|
149
|
+
- name: Check out Redis adapter
|
|
150
|
+
uses: actions/checkout@v7
|
|
151
|
+
with:
|
|
152
|
+
repository: yong5eon/DefStream-Redis
|
|
153
|
+
ref: ${{ github.event.repository.name == 'DefStream-Redis' && github.sha || 'master' }}
|
|
154
|
+
path: packages/DefStream-Redis
|
|
155
|
+
fetch-depth: 0
|
|
156
|
+
persist-credentials: false
|
|
157
|
+
|
|
158
|
+
- name: Set up Python
|
|
159
|
+
uses: actions/setup-python@v7
|
|
160
|
+
with:
|
|
161
|
+
python-version: ${{ matrix.python }}
|
|
162
|
+
|
|
163
|
+
- name: Record source commits and tag candidate locally
|
|
164
|
+
env:
|
|
165
|
+
RELEASE_BUILD: ${{ needs.changes.outputs.release }}
|
|
166
|
+
RELEASE_VERSION: ${{ needs.changes.outputs.version }}
|
|
167
|
+
run: |
|
|
168
|
+
for package in packages/*; do
|
|
169
|
+
echo "$package: $(git -C "$package" rev-parse HEAD)"
|
|
170
|
+
done
|
|
171
|
+
echo "SOURCE_DATE_EPOCH=$(git -C "packages/$PROJECT" show -s --format=%ct HEAD)" >> "$GITHUB_ENV"
|
|
172
|
+
python - <<'PY'
|
|
173
|
+
from os import environ
|
|
174
|
+
from pathlib import Path
|
|
175
|
+
from re import fullmatch
|
|
176
|
+
from subprocess import check_output, run
|
|
177
|
+
|
|
178
|
+
project = environ['PROJECT']
|
|
179
|
+
if project not in ('DefStream', 'DefStream-RabbitMQ', 'DefStream-Redis'):
|
|
180
|
+
raise ValueError(f'Unexpected project: {project}')
|
|
181
|
+
if environ['RELEASE_BUILD'] != 'true':
|
|
182
|
+
print('Test-only build: using the existing Git-derived development version.')
|
|
183
|
+
raise SystemExit(0)
|
|
184
|
+
version = environ['RELEASE_VERSION']
|
|
185
|
+
if fullmatch(r'(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)\.[1-9]\d*', version) is None:
|
|
186
|
+
raise ValueError(f'Invalid planned version: {version!r}')
|
|
187
|
+
path = Path('packages') / project
|
|
188
|
+
tag = version
|
|
189
|
+
tags = check_output(['git', '-C', str(path), 'tag', '--list', tag], text=True).strip()
|
|
190
|
+
if tags:
|
|
191
|
+
tagged = check_output(['git', '-C', str(path), 'rev-parse', f'{tag}^{{commit}}'], text=True).strip()
|
|
192
|
+
if tagged != environ['GITHUB_SHA']:
|
|
193
|
+
raise RuntimeError(f'{tag} already points at another commit')
|
|
194
|
+
else:
|
|
195
|
+
run(['git', '-C', str(path), 'tag', tag, environ['GITHUB_SHA']], check=True)
|
|
196
|
+
print(f'{project}: local candidate {tag}')
|
|
197
|
+
with Path(environ['GITHUB_STEP_SUMMARY']).open('a', encoding='utf-8') as summary:
|
|
198
|
+
summary.write(f'## {project} {version}\n\nSource: `{environ["GITHUB_SHA"]}`\n')
|
|
199
|
+
PY
|
|
200
|
+
|
|
201
|
+
- name: Install build tools
|
|
202
|
+
run: python -m pip install --upgrade build twine
|
|
203
|
+
|
|
204
|
+
- name: Build source distributions and wheels
|
|
205
|
+
run: |
|
|
206
|
+
mkdir -p dist dependency-wheels
|
|
207
|
+
for name in DefStream DefStream-RabbitMQ DefStream-Redis; do
|
|
208
|
+
if [ "$name" = "$PROJECT" ]; then
|
|
209
|
+
python -m build --outdir "$GITHUB_WORKSPACE/dist" "packages/$name"
|
|
210
|
+
else
|
|
211
|
+
python -m build --outdir "$GITHUB_WORKSPACE/dependency-wheels" "packages/$name"
|
|
212
|
+
fi
|
|
213
|
+
done
|
|
214
|
+
python -m twine check --strict dist/*
|
|
215
|
+
|
|
216
|
+
- name: Install built wheels into a clean environment
|
|
217
|
+
run: |
|
|
218
|
+
python -m venv "$RUNNER_TEMP/installed"
|
|
219
|
+
"$RUNNER_TEMP/installed/bin/python" -m pip install dist/*.whl dependency-wheels/*.whl
|
|
220
|
+
"$RUNNER_TEMP/installed/bin/python" -m pip check
|
|
221
|
+
|
|
222
|
+
- name: Test installed package
|
|
223
|
+
run: |
|
|
224
|
+
cd "$RUNNER_TEMP"
|
|
225
|
+
"$RUNNER_TEMP/installed/bin/python" -m unittest discover \
|
|
226
|
+
-s "$GITHUB_WORKSPACE/packages/$PROJECT/test" -p 'test_*.py' -v
|
|
227
|
+
|
|
228
|
+
- name: Set up Node for core UI tests
|
|
229
|
+
if: env.PROJECT == 'DefStream'
|
|
230
|
+
uses: actions/setup-node@v7
|
|
231
|
+
with:
|
|
232
|
+
node-version: '22'
|
|
233
|
+
|
|
234
|
+
- name: Test core UI
|
|
235
|
+
if: env.PROJECT == 'DefStream'
|
|
236
|
+
run: node --test packages/DefStream/test/test_dashboard_ui.cjs
|
|
237
|
+
|
|
238
|
+
- name: Preserve verified release distributions
|
|
239
|
+
if: needs.changes.outputs.release == 'true' && matrix.python == '3.13'
|
|
240
|
+
uses: actions/upload-artifact@v7
|
|
241
|
+
with:
|
|
242
|
+
name: distributions
|
|
243
|
+
path: dist/*
|
|
244
|
+
if-no-files-found: error
|
|
245
|
+
retention-days: 14
|
|
246
|
+
|
|
247
|
+
publish:
|
|
248
|
+
name: Publish PyPI
|
|
249
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && needs.changes.outputs.release == 'true'
|
|
250
|
+
needs: [changes, test]
|
|
251
|
+
runs-on: ubuntu-latest
|
|
252
|
+
timeout-minutes: 10
|
|
253
|
+
environment: pypi
|
|
254
|
+
permissions:
|
|
255
|
+
contents: write
|
|
256
|
+
steps:
|
|
257
|
+
- name: Check out release source for tagging
|
|
258
|
+
uses: actions/checkout@v7
|
|
259
|
+
with:
|
|
260
|
+
ref: ${{ github.sha }}
|
|
261
|
+
path: release-source
|
|
262
|
+
fetch-depth: 0
|
|
263
|
+
|
|
264
|
+
- name: Download verified distributions
|
|
265
|
+
uses: actions/download-artifact@v8
|
|
266
|
+
with:
|
|
267
|
+
name: distributions
|
|
268
|
+
path: dist
|
|
269
|
+
|
|
270
|
+
- name: Set up Python
|
|
271
|
+
uses: actions/setup-python@v7
|
|
272
|
+
with:
|
|
273
|
+
python-version: '3.13'
|
|
274
|
+
|
|
275
|
+
- name: Check release status
|
|
276
|
+
id: release
|
|
277
|
+
env:
|
|
278
|
+
PROJECT: ${{ github.event.repository.name }}
|
|
279
|
+
RELEASE_VERSION: ${{ needs.changes.outputs.version }}
|
|
280
|
+
run: |
|
|
281
|
+
python - <<'PY'
|
|
282
|
+
from email.parser import BytesParser
|
|
283
|
+
from json import load
|
|
284
|
+
from os import environ
|
|
285
|
+
from pathlib import Path
|
|
286
|
+
from urllib.error import HTTPError
|
|
287
|
+
from urllib.request import urlopen
|
|
288
|
+
from zipfile import ZipFile
|
|
289
|
+
|
|
290
|
+
wheels = list(Path('dist').glob('*.whl'))
|
|
291
|
+
sources = list(Path('dist').glob('*.tar.gz'))
|
|
292
|
+
if len(wheels) != 1 or len(sources) != 1:
|
|
293
|
+
raise ValueError('Expected exactly one wheel and one source distribution')
|
|
294
|
+
with ZipFile(wheels[0]) as archive:
|
|
295
|
+
metadata_path, = (name for name in archive.namelist() if name.endswith('.dist-info/METADATA'))
|
|
296
|
+
metadata = BytesParser().parsebytes(archive.read(metadata_path))
|
|
297
|
+
project = environ['PROJECT']
|
|
298
|
+
if metadata['Name'] != project:
|
|
299
|
+
raise ValueError(f'Unexpected distribution: {metadata["Name"]}')
|
|
300
|
+
version = metadata['Version']
|
|
301
|
+
expected_version = environ['RELEASE_VERSION']
|
|
302
|
+
if version != expected_version:
|
|
303
|
+
raise ValueError(f'Expected {expected_version}, got {version}')
|
|
304
|
+
try:
|
|
305
|
+
with urlopen(f'https://pypi.org/pypi/{project}/{version}/json', timeout=30) as response:
|
|
306
|
+
release = load(response)
|
|
307
|
+
except HTTPError as error:
|
|
308
|
+
if error.code != 404:
|
|
309
|
+
raise
|
|
310
|
+
exists = False
|
|
311
|
+
else:
|
|
312
|
+
expected = {wheels[0].name, sources[0].name}
|
|
313
|
+
published = {file['filename'] for file in release['urls']}
|
|
314
|
+
if int(environ['GITHUB_RUN_ATTEMPT']) == 1 or not expected.issubset(published):
|
|
315
|
+
raise RuntimeError(
|
|
316
|
+
f'{project} {version} already exists or is partially published. '
|
|
317
|
+
'Do not overwrite it; use a new run/version or repair the release manually.'
|
|
318
|
+
)
|
|
319
|
+
print(f'{project} {version}: already published; skipping this rerun')
|
|
320
|
+
exists = True
|
|
321
|
+
with Path(environ['GITHUB_OUTPUT']).open('a', encoding='utf-8') as output:
|
|
322
|
+
output.write(f'publish={str(not exists).lower()}\n')
|
|
323
|
+
output.write(f'version={version}\n')
|
|
324
|
+
PY
|
|
325
|
+
|
|
326
|
+
- name: Record verified release tag
|
|
327
|
+
env:
|
|
328
|
+
VERSION: ${{ steps.release.outputs.version }}
|
|
329
|
+
run: |
|
|
330
|
+
tag="$VERSION"
|
|
331
|
+
cd release-source
|
|
332
|
+
if git show-ref --verify --quiet "refs/tags/$tag"; then
|
|
333
|
+
if [ "$(git rev-parse "$tag^{commit}")" != "$GITHUB_SHA" ]; then
|
|
334
|
+
echo "::error::$tag already points at another commit."
|
|
335
|
+
exit 1
|
|
336
|
+
fi
|
|
337
|
+
else
|
|
338
|
+
git tag "$tag" "$GITHUB_SHA"
|
|
339
|
+
fi
|
|
340
|
+
git push origin "refs/tags/$tag"
|
|
341
|
+
|
|
342
|
+
- name: Install upload tool
|
|
343
|
+
if: steps.release.outputs.publish == 'true'
|
|
344
|
+
run: python -m pip install --upgrade twine
|
|
345
|
+
|
|
346
|
+
- name: Upload to PyPI
|
|
347
|
+
if: steps.release.outputs.publish == 'true'
|
|
348
|
+
env:
|
|
349
|
+
TWINE_USERNAME: __token__
|
|
350
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
351
|
+
run: |
|
|
352
|
+
if [ -z "$TWINE_PASSWORD" ]; then
|
|
353
|
+
echo "::error::Configure PYPI_API_TOKEN in the pypi environment or repository Actions secrets."
|
|
354
|
+
exit 1
|
|
355
|
+
fi
|
|
356
|
+
python -m twine upload --non-interactive dist/*
|
|
357
|
+
|
|
358
|
+
- name: Publish GitHub Release with verified distributions
|
|
359
|
+
env:
|
|
360
|
+
GH_TOKEN: ${{ github.token }}
|
|
361
|
+
VERSION: ${{ steps.release.outputs.version }}
|
|
362
|
+
run: |
|
|
363
|
+
python - <<'PY'
|
|
364
|
+
from json import load
|
|
365
|
+
from os import environ
|
|
366
|
+
from pathlib import Path
|
|
367
|
+
from subprocess import run
|
|
368
|
+
from urllib.error import HTTPError
|
|
369
|
+
from urllib.parse import quote
|
|
370
|
+
from urllib.request import Request, urlopen
|
|
371
|
+
|
|
372
|
+
repository = environ['GITHUB_REPOSITORY']
|
|
373
|
+
version = environ['VERSION']
|
|
374
|
+
request = Request(
|
|
375
|
+
f'{environ["GITHUB_API_URL"]}/repos/{repository}/releases/tags/{quote(version, safe="")}',
|
|
376
|
+
headers={
|
|
377
|
+
'Authorization': f'Bearer {environ["GH_TOKEN"]}',
|
|
378
|
+
'Accept': 'application/vnd.github+json',
|
|
379
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
380
|
+
},
|
|
381
|
+
)
|
|
382
|
+
try:
|
|
383
|
+
with urlopen(request, timeout=30) as response:
|
|
384
|
+
release = load(response)
|
|
385
|
+
except HTTPError as error:
|
|
386
|
+
if error.code != 404:
|
|
387
|
+
raise
|
|
388
|
+
run([
|
|
389
|
+
'gh', 'release', 'create', version, '--repo', repository,
|
|
390
|
+
'--verify-tag', '--title', version, '--generate-notes', '--draft',
|
|
391
|
+
], check=True)
|
|
392
|
+
else:
|
|
393
|
+
if release['tag_name'] != version:
|
|
394
|
+
raise ValueError('GitHub Release does not match the verified version')
|
|
395
|
+
artifacts = sorted(str(path) for path in Path('dist').iterdir() if path.is_file())
|
|
396
|
+
run([
|
|
397
|
+
'gh', 'release', 'upload', version, '--repo', repository,
|
|
398
|
+
'--clobber', *artifacts,
|
|
399
|
+
], check=True)
|
|
400
|
+
run([
|
|
401
|
+
'gh', 'release', 'edit', version, '--repo', repository, '--draft=false',
|
|
402
|
+
], check=True)
|
|
403
|
+
PY
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Python bytecode and caches
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
.mypy_cache/
|
|
7
|
+
.ruff_cache/
|
|
8
|
+
.tox/
|
|
9
|
+
.nox/
|
|
10
|
+
.coverage
|
|
11
|
+
.coverage.*
|
|
12
|
+
|
|
13
|
+
# Virtual environments and local environment files
|
|
14
|
+
.venv/
|
|
15
|
+
venv/
|
|
16
|
+
env/
|
|
17
|
+
.env
|
|
18
|
+
.env.*
|
|
19
|
+
|
|
20
|
+
# Python packaging and build artifacts
|
|
21
|
+
build/
|
|
22
|
+
dist/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
*.egg
|
|
25
|
+
.Python
|
|
26
|
+
|
|
27
|
+
# Operating system files
|
|
28
|
+
.DS_Store
|
|
29
|
+
Thumbs.db
|
|
30
|
+
Desktop.ini
|
|
31
|
+
|
|
32
|
+
# Miscellaneous files
|
|
33
|
+
*.log
|
|
34
|
+
*.tmp
|
|
35
|
+
*.bak
|
|
36
|
+
*.swp
|
|
37
|
+
*.swo
|
|
38
|
+
|
|
39
|
+
# Temporary files
|
|
40
|
+
tmp/
|
|
41
|
+
*.tmp
|
|
42
|
+
*.temp
|
|
43
|
+
|
|
44
|
+
# IDE and editor specific files
|
|
45
|
+
.vscode/
|
|
46
|
+
.idea/
|
|
47
|
+
|
|
48
|
+
# Git
|
|
49
|
+
.git/
|
|
50
|
+
|
|
51
|
+
# GitHub specific files
|
|
52
|
+
.github/
|
|
53
|
+
!/.github/
|
|
54
|
+
/.github/*
|
|
55
|
+
!/.github/workflows/
|
|
56
|
+
|
|
57
|
+
# GitLab specific files
|
|
58
|
+
.gitlab/
|
{defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/DefStream_RabbitMQ.egg-info/PKG-INFO
RENAMED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: DefStream-RabbitMQ
|
|
3
|
-
Version: 0.1.1
|
|
3
|
+
Version: 0.1.1.2
|
|
4
4
|
Summary: RabbitMQ broker adapter for DefStream
|
|
5
5
|
Home-page: https://github.com/yong5eon/DefStream-RabbitMQ
|
|
6
6
|
Author: Heo Yongseon
|
|
7
7
|
Project-URL: Source, https://github.com/yong5eon/DefStream-RabbitMQ
|
|
8
8
|
Project-URL: Issues, https://github.com/yong5eon/DefStream-RabbitMQ/issues
|
|
9
|
+
Project-URL: Releases, https://github.com/yong5eon/DefStream-RabbitMQ/releases
|
|
9
10
|
Classifier: Programming Language :: Python :: 3.9
|
|
10
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
11
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -41,11 +42,58 @@ commit IDs recorded in the log. All three GitHub repositories must be accessible
|
|
|
41
42
|
This bootstrap setup does not require existing PyPI releases and does not
|
|
42
43
|
certify compatibility with previously published dependencies.
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
There is no `VERSION` or `pyproject.toml` file. `setup.py` configures
|
|
46
|
+
`setuptools-scm` via `setup_requires`; `python -m build` resolves the build
|
|
47
|
+
dependency in isolation. This legacy declaration may emit a deprecation warning.
|
|
48
|
+
`setuptools-scm` derives versions from Git tags.
|
|
49
|
+
CI fetches full history and creates a local candidate tag
|
|
50
|
+
`<RELEASE_SERIES>.<PATCH>.<github.run_number>` (for example, `0.1.3.123`) on
|
|
51
|
+
every `master` push. Source changes increment PATCH by one; all other changes
|
|
52
|
+
keep MAJOR.MINOR.PATCH. BUILD is always the Actions run number:
|
|
53
|
+
`0.1.3.123` -> `0.1.3.124` (docs) -> `0.1.4.125` (source).
|
|
54
|
+
The highest matching version in pre-push history supplies the base, keeping
|
|
55
|
+
reruns stable. The four-part value is the full public PyPI version.
|
|
56
|
+
New tags have no `v` prefix; existing `v` tags remain readable.
|
|
57
|
+
PRs only run tests using their Git-derived development version without a tag.
|
|
58
|
+
The complete push range is compared, including additions, deletions, and
|
|
59
|
+
renames. Changes only to tests, docs, samples, workflows, or `setup.py` increase
|
|
60
|
+
only BUILD. PyPI files cannot be overwritten; every upload has a distinct
|
|
61
|
+
version identifier. Change
|
|
62
|
+
`RELEASE_SERIES` in the workflow to start a new major/minor series. No version
|
|
63
|
+
commit or version-update PR is created; run numbers can have gaps.
|
|
64
|
+
|
|
65
|
+
After all tests pass, the publish job pushes the release tag to the tested
|
|
66
|
+
commit before uploading the verified artifacts. A tag may exist if uploading
|
|
67
|
+
subsequently fails; retry the run and check PyPI for publication status.
|
|
68
|
+
Existing tags on other commits are never overwritten. Allow the workflow's
|
|
69
|
+
`GITHUB_TOKEN` to write contents and permit numeric four-part tags
|
|
70
|
+
in any tag rulesets.
|
|
71
|
+
|
|
72
|
+
After PyPI upload succeeds (or a rerun confirms the version is fully
|
|
73
|
+
published), CI creates a GitHub Release titled and tagged with the same
|
|
74
|
+
version, with automatically generated notes and the verified wheel and sdist
|
|
75
|
+
attached. New releases remain drafts until both assets are uploaded. A retry
|
|
76
|
+
reuses the release, replaces matching assets with the verified files, and
|
|
77
|
+
publishes it. PyPI upload failures prevent this step. The existing write-enabled
|
|
78
|
+
`GITHUB_TOKEN` is sufficient; no extra token secret is required. PyPI's project
|
|
79
|
+
links include the GitHub Releases page for change history.
|
|
80
|
+
|
|
81
|
+
Fetch tags with `git fetch --tags` for local builds. Tagged commits produce
|
|
82
|
+
release versions; later commits produce development versions, with local
|
|
83
|
+
suffixes for dirty trees. Build from a Git checkout or a published sdist, not
|
|
84
|
+
a GitHub source ZIP without Git metadata. Installed versions are available via
|
|
85
|
+
`importlib.metadata.version('DefStream-RabbitMQ')`. Before migration, tag the
|
|
86
|
+
exact source commits of existing PyPI releases in all three repositories,
|
|
87
|
+
using their version numbers as tags.
|
|
88
|
+
Untagged SCM dependencies may resolve below their required minimum version;
|
|
89
|
+
initial release tags also provide the starting PATCH for numeric builds.
|
|
90
|
+
A tag such as `0.1.3` must name the commit used to publish that version, not
|
|
91
|
+
an arbitrary current commit. Adding that tag does not edit sources or upload
|
|
92
|
+
anything to PyPI.
|
|
93
|
+
A new release series needs a source change or an existing matching release tag
|
|
94
|
+
before it can produce builds. Its first source release starts at PATCH 0.
|
|
95
|
+
Build counter regressions fail explicitly. Legacy `.postN` tags remain
|
|
96
|
+
readable; numeric builds sort above post releases of a three-part base.
|
|
49
97
|
|
|
50
98
|
Only after all six Python checks pass does a separate publish job upload the
|
|
51
99
|
exact Python 3.13 build artifacts. A fully published version is skipped on a
|
{defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/DefStream_RabbitMQ.egg-info/SOURCES.txt
RENAMED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
.gitignore
|
|
1
2
|
LICENSE
|
|
2
|
-
MANIFEST.in
|
|
3
3
|
README.md
|
|
4
|
-
VERSION
|
|
5
4
|
setup.py
|
|
5
|
+
.github/workflows/ci.yml
|
|
6
6
|
DefStream_RabbitMQ.egg-info/PKG-INFO
|
|
7
7
|
DefStream_RabbitMQ.egg-info/SOURCES.txt
|
|
8
8
|
DefStream_RabbitMQ.egg-info/dependency_links.txt
|
|
9
9
|
DefStream_RabbitMQ.egg-info/requires.txt
|
|
10
10
|
DefStream_RabbitMQ.egg-info/top_level.txt
|
|
11
|
+
sample/Sample.RPC.py
|
|
12
|
+
sample/Sample.Stream.py
|
|
13
|
+
sample/Sample.py
|
|
11
14
|
src/Configuration.py
|
|
12
15
|
src/Connection.py
|
|
13
16
|
src/Consumer.py
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: DefStream-RabbitMQ
|
|
3
|
-
Version: 0.1.1
|
|
3
|
+
Version: 0.1.1.2
|
|
4
4
|
Summary: RabbitMQ broker adapter for DefStream
|
|
5
5
|
Home-page: https://github.com/yong5eon/DefStream-RabbitMQ
|
|
6
6
|
Author: Heo Yongseon
|
|
7
7
|
Project-URL: Source, https://github.com/yong5eon/DefStream-RabbitMQ
|
|
8
8
|
Project-URL: Issues, https://github.com/yong5eon/DefStream-RabbitMQ/issues
|
|
9
|
+
Project-URL: Releases, https://github.com/yong5eon/DefStream-RabbitMQ/releases
|
|
9
10
|
Classifier: Programming Language :: Python :: 3.9
|
|
10
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
11
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -41,11 +42,58 @@ commit IDs recorded in the log. All three GitHub repositories must be accessible
|
|
|
41
42
|
This bootstrap setup does not require existing PyPI releases and does not
|
|
42
43
|
certify compatibility with previously published dependencies.
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
There is no `VERSION` or `pyproject.toml` file. `setup.py` configures
|
|
46
|
+
`setuptools-scm` via `setup_requires`; `python -m build` resolves the build
|
|
47
|
+
dependency in isolation. This legacy declaration may emit a deprecation warning.
|
|
48
|
+
`setuptools-scm` derives versions from Git tags.
|
|
49
|
+
CI fetches full history and creates a local candidate tag
|
|
50
|
+
`<RELEASE_SERIES>.<PATCH>.<github.run_number>` (for example, `0.1.3.123`) on
|
|
51
|
+
every `master` push. Source changes increment PATCH by one; all other changes
|
|
52
|
+
keep MAJOR.MINOR.PATCH. BUILD is always the Actions run number:
|
|
53
|
+
`0.1.3.123` -> `0.1.3.124` (docs) -> `0.1.4.125` (source).
|
|
54
|
+
The highest matching version in pre-push history supplies the base, keeping
|
|
55
|
+
reruns stable. The four-part value is the full public PyPI version.
|
|
56
|
+
New tags have no `v` prefix; existing `v` tags remain readable.
|
|
57
|
+
PRs only run tests using their Git-derived development version without a tag.
|
|
58
|
+
The complete push range is compared, including additions, deletions, and
|
|
59
|
+
renames. Changes only to tests, docs, samples, workflows, or `setup.py` increase
|
|
60
|
+
only BUILD. PyPI files cannot be overwritten; every upload has a distinct
|
|
61
|
+
version identifier. Change
|
|
62
|
+
`RELEASE_SERIES` in the workflow to start a new major/minor series. No version
|
|
63
|
+
commit or version-update PR is created; run numbers can have gaps.
|
|
64
|
+
|
|
65
|
+
After all tests pass, the publish job pushes the release tag to the tested
|
|
66
|
+
commit before uploading the verified artifacts. A tag may exist if uploading
|
|
67
|
+
subsequently fails; retry the run and check PyPI for publication status.
|
|
68
|
+
Existing tags on other commits are never overwritten. Allow the workflow's
|
|
69
|
+
`GITHUB_TOKEN` to write contents and permit numeric four-part tags
|
|
70
|
+
in any tag rulesets.
|
|
71
|
+
|
|
72
|
+
After PyPI upload succeeds (or a rerun confirms the version is fully
|
|
73
|
+
published), CI creates a GitHub Release titled and tagged with the same
|
|
74
|
+
version, with automatically generated notes and the verified wheel and sdist
|
|
75
|
+
attached. New releases remain drafts until both assets are uploaded. A retry
|
|
76
|
+
reuses the release, replaces matching assets with the verified files, and
|
|
77
|
+
publishes it. PyPI upload failures prevent this step. The existing write-enabled
|
|
78
|
+
`GITHUB_TOKEN` is sufficient; no extra token secret is required. PyPI's project
|
|
79
|
+
links include the GitHub Releases page for change history.
|
|
80
|
+
|
|
81
|
+
Fetch tags with `git fetch --tags` for local builds. Tagged commits produce
|
|
82
|
+
release versions; later commits produce development versions, with local
|
|
83
|
+
suffixes for dirty trees. Build from a Git checkout or a published sdist, not
|
|
84
|
+
a GitHub source ZIP without Git metadata. Installed versions are available via
|
|
85
|
+
`importlib.metadata.version('DefStream-RabbitMQ')`. Before migration, tag the
|
|
86
|
+
exact source commits of existing PyPI releases in all three repositories,
|
|
87
|
+
using their version numbers as tags.
|
|
88
|
+
Untagged SCM dependencies may resolve below their required minimum version;
|
|
89
|
+
initial release tags also provide the starting PATCH for numeric builds.
|
|
90
|
+
A tag such as `0.1.3` must name the commit used to publish that version, not
|
|
91
|
+
an arbitrary current commit. Adding that tag does not edit sources or upload
|
|
92
|
+
anything to PyPI.
|
|
93
|
+
A new release series needs a source change or an existing matching release tag
|
|
94
|
+
before it can produce builds. Its first source release starts at PATCH 0.
|
|
95
|
+
Build counter regressions fail explicitly. Legacy `.postN` tags remain
|
|
96
|
+
readable; numeric builds sort above post releases of a three-part base.
|
|
49
97
|
|
|
50
98
|
Only after all six Python checks pass does a separate publish job upload the
|
|
51
99
|
exact Python 3.13 build artifacts. A fully published version is skipped on a
|
|
@@ -11,11 +11,58 @@ commit IDs recorded in the log. All three GitHub repositories must be accessible
|
|
|
11
11
|
This bootstrap setup does not require existing PyPI releases and does not
|
|
12
12
|
certify compatibility with previously published dependencies.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
There is no `VERSION` or `pyproject.toml` file. `setup.py` configures
|
|
15
|
+
`setuptools-scm` via `setup_requires`; `python -m build` resolves the build
|
|
16
|
+
dependency in isolation. This legacy declaration may emit a deprecation warning.
|
|
17
|
+
`setuptools-scm` derives versions from Git tags.
|
|
18
|
+
CI fetches full history and creates a local candidate tag
|
|
19
|
+
`<RELEASE_SERIES>.<PATCH>.<github.run_number>` (for example, `0.1.3.123`) on
|
|
20
|
+
every `master` push. Source changes increment PATCH by one; all other changes
|
|
21
|
+
keep MAJOR.MINOR.PATCH. BUILD is always the Actions run number:
|
|
22
|
+
`0.1.3.123` -> `0.1.3.124` (docs) -> `0.1.4.125` (source).
|
|
23
|
+
The highest matching version in pre-push history supplies the base, keeping
|
|
24
|
+
reruns stable. The four-part value is the full public PyPI version.
|
|
25
|
+
New tags have no `v` prefix; existing `v` tags remain readable.
|
|
26
|
+
PRs only run tests using their Git-derived development version without a tag.
|
|
27
|
+
The complete push range is compared, including additions, deletions, and
|
|
28
|
+
renames. Changes only to tests, docs, samples, workflows, or `setup.py` increase
|
|
29
|
+
only BUILD. PyPI files cannot be overwritten; every upload has a distinct
|
|
30
|
+
version identifier. Change
|
|
31
|
+
`RELEASE_SERIES` in the workflow to start a new major/minor series. No version
|
|
32
|
+
commit or version-update PR is created; run numbers can have gaps.
|
|
33
|
+
|
|
34
|
+
After all tests pass, the publish job pushes the release tag to the tested
|
|
35
|
+
commit before uploading the verified artifacts. A tag may exist if uploading
|
|
36
|
+
subsequently fails; retry the run and check PyPI for publication status.
|
|
37
|
+
Existing tags on other commits are never overwritten. Allow the workflow's
|
|
38
|
+
`GITHUB_TOKEN` to write contents and permit numeric four-part tags
|
|
39
|
+
in any tag rulesets.
|
|
40
|
+
|
|
41
|
+
After PyPI upload succeeds (or a rerun confirms the version is fully
|
|
42
|
+
published), CI creates a GitHub Release titled and tagged with the same
|
|
43
|
+
version, with automatically generated notes and the verified wheel and sdist
|
|
44
|
+
attached. New releases remain drafts until both assets are uploaded. A retry
|
|
45
|
+
reuses the release, replaces matching assets with the verified files, and
|
|
46
|
+
publishes it. PyPI upload failures prevent this step. The existing write-enabled
|
|
47
|
+
`GITHUB_TOKEN` is sufficient; no extra token secret is required. PyPI's project
|
|
48
|
+
links include the GitHub Releases page for change history.
|
|
49
|
+
|
|
50
|
+
Fetch tags with `git fetch --tags` for local builds. Tagged commits produce
|
|
51
|
+
release versions; later commits produce development versions, with local
|
|
52
|
+
suffixes for dirty trees. Build from a Git checkout or a published sdist, not
|
|
53
|
+
a GitHub source ZIP without Git metadata. Installed versions are available via
|
|
54
|
+
`importlib.metadata.version('DefStream-RabbitMQ')`. Before migration, tag the
|
|
55
|
+
exact source commits of existing PyPI releases in all three repositories,
|
|
56
|
+
using their version numbers as tags.
|
|
57
|
+
Untagged SCM dependencies may resolve below their required minimum version;
|
|
58
|
+
initial release tags also provide the starting PATCH for numeric builds.
|
|
59
|
+
A tag such as `0.1.3` must name the commit used to publish that version, not
|
|
60
|
+
an arbitrary current commit. Adding that tag does not edit sources or upload
|
|
61
|
+
anything to PyPI.
|
|
62
|
+
A new release series needs a source change or an existing matching release tag
|
|
63
|
+
before it can produce builds. Its first source release starts at PATCH 0.
|
|
64
|
+
Build counter regressions fail explicitly. Legacy `.postN` tags remain
|
|
65
|
+
readable; numeric builds sort above post releases of a three-part base.
|
|
19
66
|
|
|
20
67
|
Only after all six Python checks pass does a separate publish job upload the
|
|
21
68
|
exact Python 3.13 build artifacts. A fully published version is skipped on a
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
2
|
+
from sys import stderr
|
|
3
|
+
from threading import Event as PyEvent
|
|
4
|
+
from uuid import uuid4
|
|
5
|
+
|
|
6
|
+
from DefStream.Broker import RemoteError
|
|
7
|
+
from DefStream.Broker.Implements.RabbitMQ import (
|
|
8
|
+
Connection,
|
|
9
|
+
Configuration,
|
|
10
|
+
Consumer,
|
|
11
|
+
Event,
|
|
12
|
+
EventHandler,
|
|
13
|
+
ExchangeType,
|
|
14
|
+
Reject,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Calculate(EventHandler):
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
consumer: Consumer,
|
|
22
|
+
):
|
|
23
|
+
self.consumer = consumer
|
|
24
|
+
|
|
25
|
+
def __call__(
|
|
26
|
+
self,
|
|
27
|
+
event: Event,
|
|
28
|
+
) -> None:
|
|
29
|
+
try:
|
|
30
|
+
result = event.body['a'] / event.body['b']
|
|
31
|
+
except ZeroDivisionError:
|
|
32
|
+
self.consumer.fail(
|
|
33
|
+
event,
|
|
34
|
+
Reject(),
|
|
35
|
+
)
|
|
36
|
+
else:
|
|
37
|
+
self.consumer.complete(
|
|
38
|
+
event,
|
|
39
|
+
result,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def serve(
|
|
44
|
+
configuration: Configuration,
|
|
45
|
+
queue: str,
|
|
46
|
+
ready: PyEvent,
|
|
47
|
+
stopping: PyEvent,
|
|
48
|
+
) -> None:
|
|
49
|
+
broker = Connection(configuration)
|
|
50
|
+
try:
|
|
51
|
+
broker.connect()
|
|
52
|
+
consumer = broker.consumer()
|
|
53
|
+
try:
|
|
54
|
+
consumer.subs(
|
|
55
|
+
queue,
|
|
56
|
+
Calculate(consumer),
|
|
57
|
+
)
|
|
58
|
+
ready.set()
|
|
59
|
+
|
|
60
|
+
def check_stop() -> None:
|
|
61
|
+
if stopping.is_set():
|
|
62
|
+
consumer.stop()
|
|
63
|
+
else:
|
|
64
|
+
broker.connection.call_later(
|
|
65
|
+
0.1,
|
|
66
|
+
check_stop,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
broker.connection.call_later(
|
|
70
|
+
0.1,
|
|
71
|
+
check_stop,
|
|
72
|
+
)
|
|
73
|
+
consumer.run()
|
|
74
|
+
finally:
|
|
75
|
+
consumer.close()
|
|
76
|
+
finally:
|
|
77
|
+
broker.close()
|
|
78
|
+
ready.set()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
if __name__ == '__main__':
|
|
82
|
+
configuration = Configuration(
|
|
83
|
+
host='127.0.0.1',
|
|
84
|
+
port=5672,
|
|
85
|
+
username='guest',
|
|
86
|
+
password='guest',
|
|
87
|
+
)
|
|
88
|
+
broker = Connection(configuration)
|
|
89
|
+
name = 'defstream-rpc-sample-' + uuid4().hex
|
|
90
|
+
ready = PyEvent()
|
|
91
|
+
stopping = PyEvent()
|
|
92
|
+
created_queue = False
|
|
93
|
+
created_exchange = False
|
|
94
|
+
try:
|
|
95
|
+
broker.connect()
|
|
96
|
+
broker.create_exchange(
|
|
97
|
+
name,
|
|
98
|
+
ExchangeType.Direct,
|
|
99
|
+
durable=False,
|
|
100
|
+
)
|
|
101
|
+
created_exchange = True
|
|
102
|
+
broker.create_queue(
|
|
103
|
+
name,
|
|
104
|
+
durable=False,
|
|
105
|
+
)
|
|
106
|
+
created_queue = True
|
|
107
|
+
broker.bind_exchange_to_queue(
|
|
108
|
+
name,
|
|
109
|
+
name,
|
|
110
|
+
event='divide',
|
|
111
|
+
)
|
|
112
|
+
with ThreadPoolExecutor(1) as executor:
|
|
113
|
+
server = executor.submit(
|
|
114
|
+
serve,
|
|
115
|
+
configuration,
|
|
116
|
+
name,
|
|
117
|
+
ready,
|
|
118
|
+
stopping,
|
|
119
|
+
)
|
|
120
|
+
try:
|
|
121
|
+
if not ready.wait(10):
|
|
122
|
+
raise TimeoutError('RPC server did not start')
|
|
123
|
+
if server.done():
|
|
124
|
+
server.result()
|
|
125
|
+
raise RuntimeError('RPC server exited before handling requests')
|
|
126
|
+
result = broker.queue(name).call(
|
|
127
|
+
{
|
|
128
|
+
'a': 20,
|
|
129
|
+
'b': 4,
|
|
130
|
+
},
|
|
131
|
+
timeout=5,
|
|
132
|
+
)
|
|
133
|
+
print(f'Queue RPC: 20 / 4 = {result}')
|
|
134
|
+
result = broker.exchange(name).call(
|
|
135
|
+
{
|
|
136
|
+
'a': 30,
|
|
137
|
+
'b': 5,
|
|
138
|
+
},
|
|
139
|
+
timeout=5,
|
|
140
|
+
event='divide',
|
|
141
|
+
)
|
|
142
|
+
print(f'Exchange RPC: 30 / 5 = {result}')
|
|
143
|
+
try:
|
|
144
|
+
broker.queue(name).call(
|
|
145
|
+
{
|
|
146
|
+
'a': 10,
|
|
147
|
+
'b': 0,
|
|
148
|
+
},
|
|
149
|
+
timeout=5,
|
|
150
|
+
)
|
|
151
|
+
except RemoteError as error:
|
|
152
|
+
print(
|
|
153
|
+
f'RPC rejected: {error}',
|
|
154
|
+
file=stderr,
|
|
155
|
+
)
|
|
156
|
+
finally:
|
|
157
|
+
stopping.set()
|
|
158
|
+
server.result(timeout=10)
|
|
159
|
+
finally:
|
|
160
|
+
try:
|
|
161
|
+
if created_queue:
|
|
162
|
+
broker.delete_queue(name)
|
|
163
|
+
finally:
|
|
164
|
+
try:
|
|
165
|
+
if created_exchange:
|
|
166
|
+
broker.delete_exchange(name)
|
|
167
|
+
finally:
|
|
168
|
+
broker.close()
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Sample for DefStream.Broker.Implements.RabbitMQ
|
|
2
|
+
|
|
3
|
+
from DefStream.Broker.Implements.RabbitMQ import (
|
|
4
|
+
Connection as RabbitConnection,
|
|
5
|
+
Configuration,
|
|
6
|
+
Event,
|
|
7
|
+
EventHandler,
|
|
8
|
+
)
|
|
9
|
+
from threading import Timer
|
|
10
|
+
from random import randint
|
|
11
|
+
|
|
12
|
+
if __name__ == '__main__':
|
|
13
|
+
|
|
14
|
+
con = RabbitConnection(
|
|
15
|
+
Configuration(
|
|
16
|
+
host='127.0.0.1',
|
|
17
|
+
port=5672,
|
|
18
|
+
username='guest',
|
|
19
|
+
password='guest',
|
|
20
|
+
),
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
con.connect()
|
|
24
|
+
con.create_stream('stream')
|
|
25
|
+
|
|
26
|
+
stream = con.stream('stream')
|
|
27
|
+
for i in range(randint(
|
|
28
|
+
5,
|
|
29
|
+
10,
|
|
30
|
+
)):
|
|
31
|
+
stream.send(randint(
|
|
32
|
+
0,
|
|
33
|
+
10,
|
|
34
|
+
))
|
|
35
|
+
|
|
36
|
+
class SampleEventHandler(EventHandler):
|
|
37
|
+
def __call__(
|
|
38
|
+
self,
|
|
39
|
+
event: Event,
|
|
40
|
+
):
|
|
41
|
+
try:
|
|
42
|
+
print(event.body)
|
|
43
|
+
event.ack()
|
|
44
|
+
except RuntimeError:
|
|
45
|
+
event.nack() # if you want requeue message
|
|
46
|
+
# event.reject() # if you want drop message or move to DLQ or DLE
|
|
47
|
+
pass
|
|
48
|
+
return
|
|
49
|
+
|
|
50
|
+
for i in range(randint(
|
|
51
|
+
2,
|
|
52
|
+
5,
|
|
53
|
+
)):
|
|
54
|
+
print('Consuming Events from Stream Queue: {}'.format(i + 1))
|
|
55
|
+
print('-' * 20)
|
|
56
|
+
consumer = con.consumer(
|
|
57
|
+
handler=SampleEventHandler(),
|
|
58
|
+
qos=1,
|
|
59
|
+
offset=0,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
def stop(timer):
|
|
63
|
+
consumer.stop()
|
|
64
|
+
return
|
|
65
|
+
|
|
66
|
+
Timer(
|
|
67
|
+
1,
|
|
68
|
+
lambda: stop(None),
|
|
69
|
+
).start()
|
|
70
|
+
|
|
71
|
+
consumer.subs('stream')
|
|
72
|
+
consumer.run()
|
|
73
|
+
|
|
74
|
+
print('Read Events from Stream Queue:')
|
|
75
|
+
print('-' * 20)
|
|
76
|
+
stream = con.stream('stream')
|
|
77
|
+
try:
|
|
78
|
+
for event in stream.read(timeout=1000):
|
|
79
|
+
print(event.body)
|
|
80
|
+
except KeyboardInterrupt:
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
con.delete_stream('stream')
|
|
84
|
+
con.close()
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Sample for DefStream.Broker.Implements.RabbitMQ
|
|
2
|
+
|
|
3
|
+
from DefStream.Broker.Implements.RabbitMQ import (
|
|
4
|
+
Connection as RabbitConnection,
|
|
5
|
+
Configuration,
|
|
6
|
+
ExchangeType,
|
|
7
|
+
Event,
|
|
8
|
+
EventHandler,
|
|
9
|
+
)
|
|
10
|
+
from threading import Timer
|
|
11
|
+
|
|
12
|
+
if __name__ == '__main__':
|
|
13
|
+
|
|
14
|
+
con = RabbitConnection(
|
|
15
|
+
Configuration(
|
|
16
|
+
host='127.0.0.1',
|
|
17
|
+
port=5672,
|
|
18
|
+
username='guest',
|
|
19
|
+
password='guest',
|
|
20
|
+
),
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
con.connect()
|
|
24
|
+
con.create_exchange(
|
|
25
|
+
'topic',
|
|
26
|
+
ExchangeType.Topic,
|
|
27
|
+
)
|
|
28
|
+
con.create_queue(
|
|
29
|
+
'queue',
|
|
30
|
+
maxPriority=255,
|
|
31
|
+
)
|
|
32
|
+
con.bind_exchange_to_queue(
|
|
33
|
+
'topic',
|
|
34
|
+
'queue',
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
exchange = con.exchange('topic')
|
|
38
|
+
exchange.send(
|
|
39
|
+
{
|
|
40
|
+
'a': True,
|
|
41
|
+
'b': 1,
|
|
42
|
+
'c': 1.0,
|
|
43
|
+
'd': 'abc',
|
|
44
|
+
},
|
|
45
|
+
priority=1,
|
|
46
|
+
)
|
|
47
|
+
queue = con.queue('queue')
|
|
48
|
+
queue.send({
|
|
49
|
+
'a': False,
|
|
50
|
+
'b': 2,
|
|
51
|
+
'c': 2.0,
|
|
52
|
+
'd': 'def',
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
reader = con.queue('queue')
|
|
56
|
+
e = reader.pop()
|
|
57
|
+
print(e)
|
|
58
|
+
e.ack()
|
|
59
|
+
e = reader.pop()
|
|
60
|
+
print(e)
|
|
61
|
+
e.ack()
|
|
62
|
+
|
|
63
|
+
exchange.send(
|
|
64
|
+
{
|
|
65
|
+
'a': True,
|
|
66
|
+
'b': 1,
|
|
67
|
+
'c': 1.0,
|
|
68
|
+
'd': 'abc',
|
|
69
|
+
},
|
|
70
|
+
priority=0,
|
|
71
|
+
)
|
|
72
|
+
queue.send(
|
|
73
|
+
{
|
|
74
|
+
'a': False,
|
|
75
|
+
'b': 2,
|
|
76
|
+
'c': 2.0,
|
|
77
|
+
'd': 'def',
|
|
78
|
+
},
|
|
79
|
+
priority=255,
|
|
80
|
+
)
|
|
81
|
+
exchange.send({
|
|
82
|
+
'a': True,
|
|
83
|
+
'b': 1,
|
|
84
|
+
'c': 1.0,
|
|
85
|
+
'd': 'abc',
|
|
86
|
+
})
|
|
87
|
+
queue.send({
|
|
88
|
+
'a': False,
|
|
89
|
+
'b': 1,
|
|
90
|
+
'c': 3.0,
|
|
91
|
+
'd': 'def',
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
class SampleEventHandler(EventHandler):
|
|
95
|
+
def __call__(
|
|
96
|
+
self,
|
|
97
|
+
event: Event,
|
|
98
|
+
):
|
|
99
|
+
try:
|
|
100
|
+
print(event.body)
|
|
101
|
+
print(event.priority)
|
|
102
|
+
event.ack()
|
|
103
|
+
except RuntimeError:
|
|
104
|
+
event.nack() # if you want requeue message
|
|
105
|
+
# event.reject() # if you want drop message or move to DLQ or DLE
|
|
106
|
+
return
|
|
107
|
+
|
|
108
|
+
consumer = con.consumer(
|
|
109
|
+
handler=SampleEventHandler(),
|
|
110
|
+
qos=1,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
def stop(timer):
|
|
114
|
+
consumer.stop()
|
|
115
|
+
return
|
|
116
|
+
|
|
117
|
+
Timer(
|
|
118
|
+
1,
|
|
119
|
+
lambda: stop(None),
|
|
120
|
+
).start()
|
|
121
|
+
|
|
122
|
+
consumer.subs('queue')
|
|
123
|
+
consumer.run()
|
|
124
|
+
|
|
125
|
+
con.delete_queue('queue')
|
|
126
|
+
con.delete_exchange('topic')
|
|
127
|
+
con.close()
|
|
@@ -38,8 +38,14 @@ setup(
|
|
|
38
38
|
project_urls={
|
|
39
39
|
'Source': 'https://github.com/yong5eon/DefStream-RabbitMQ',
|
|
40
40
|
'Issues': 'https://github.com/yong5eon/DefStream-RabbitMQ/issues',
|
|
41
|
+
'Releases': 'https://github.com/yong5eon/DefStream-RabbitMQ/releases',
|
|
41
42
|
},
|
|
42
|
-
|
|
43
|
+
use_scm_version={
|
|
44
|
+
'tag_regex': r'^v?(?P<version>[0-9]+\.[0-9]+\.[0-9]+(?:\.[0-9]+)?(?:(?:rc|\.post)[0-9]+)?)$',
|
|
45
|
+
},
|
|
46
|
+
setup_requires=[
|
|
47
|
+
'setuptools-scm>=8,<10',
|
|
48
|
+
],
|
|
43
49
|
packages=PACKAGES,
|
|
44
50
|
package_dir=PACKAGE_DIR,
|
|
45
51
|
include_package_data=False,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
include VERSION
|
defstream_rabbitmq-0.1.1/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.1.1
|
|
File without changes
|
{defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/DefStream_RabbitMQ.egg-info/requires.txt
RENAMED
|
File without changes
|
{defstream_rabbitmq-0.1.1 → defstream_rabbitmq-0.1.1.2}/DefStream_RabbitMQ.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|