tarsk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. tarsk-0.1.0/.github/workflows/bench.yml +64 -0
  2. tarsk-0.1.0/.github/workflows/ci.yml +148 -0
  3. tarsk-0.1.0/.github/workflows/pages.yml +50 -0
  4. tarsk-0.1.0/.github/workflows/release.yml +158 -0
  5. tarsk-0.1.0/.gitignore +7 -0
  6. tarsk-0.1.0/Cargo.lock +1830 -0
  7. tarsk-0.1.0/Cargo.toml +44 -0
  8. tarsk-0.1.0/LICENSE +21 -0
  9. tarsk-0.1.0/PKG-INFO +146 -0
  10. tarsk-0.1.0/README.md +117 -0
  11. tarsk-0.1.0/bench/README.md +34 -0
  12. tarsk-0.1.0/bench/__init__.py +0 -0
  13. tarsk-0.1.0/bench/celery_app.py +28 -0
  14. tarsk-0.1.0/bench/footprint_app.py +24 -0
  15. tarsk-0.1.0/bench/footprint_celery.py +24 -0
  16. tarsk-0.1.0/bench/footprint_taskiq.py +31 -0
  17. tarsk-0.1.0/bench/handlers.py +101 -0
  18. tarsk-0.1.0/bench/run.py +1046 -0
  19. tarsk-0.1.0/bench/tarsk_app.py +17 -0
  20. tarsk-0.1.0/bench/taskiq_app.py +26 -0
  21. tarsk-0.1.0/bench/taskiq_stream_app.py +26 -0
  22. tarsk-0.1.0/demo/__init__.py +0 -0
  23. tarsk-0.1.0/demo/leaky_app.py +23 -0
  24. tarsk-0.1.0/demo/one-hour.svg +1 -0
  25. tarsk-0.1.0/demo/run.py +291 -0
  26. tarsk-0.1.0/demo/show-hn.md +243 -0
  27. tarsk-0.1.0/mise.toml +31 -0
  28. tarsk-0.1.0/pyproject.toml +49 -0
  29. tarsk-0.1.0/site/_config.yml +6 -0
  30. tarsk-0.1.0/site/benchmarks.md +499 -0
  31. tarsk-0.1.0/site/how-it-works.md +105 -0
  32. tarsk-0.1.0/site/index.md +62 -0
  33. tarsk-0.1.0/site/operating.md +170 -0
  34. tarsk-0.1.0/site/routing.md +156 -0
  35. tarsk-0.1.0/site/tasks.md +236 -0
  36. tarsk-0.1.0/src/broker.rs +2266 -0
  37. tarsk-0.1.0/src/console.rs +671 -0
  38. tarsk-0.1.0/src/cron.rs +219 -0
  39. tarsk-0.1.0/src/lib.rs +2487 -0
  40. tarsk-0.1.0/src/metrics.rs +191 -0
  41. tarsk-0.1.0/src/transport.rs +148 -0
  42. tarsk-0.1.0/tarsk/__init__.py +803 -0
  43. tarsk-0.1.0/tarsk/_child.py +363 -0
  44. tarsk-0.1.0/tarsk/_cli.py +275 -0
  45. tarsk-0.1.0/tarsk/_proto.py +160 -0
  46. tarsk-0.1.0/tarsk/_supervisor.py +106 -0
  47. tarsk-0.1.0/tarsk/py.typed +0 -0
  48. tarsk-0.1.0/tests/broker_app.py +183 -0
  49. tarsk-0.1.0/tests/broker_worker.py +21 -0
  50. tarsk-0.1.0/tests/demo_app.py +164 -0
  51. tarsk-0.1.0/tests/leaky_app.py +35 -0
  52. tarsk-0.1.0/tests/rss_probe.py +85 -0
  53. tarsk-0.1.0/tests/soft_app.py +42 -0
  54. tarsk-0.1.0/tests/test_brokers.py +880 -0
  55. tarsk-0.1.0/tests/test_ipc.py +192 -0
  56. tarsk-0.1.0/tests/test_recycle.py +290 -0
@@ -0,0 +1,64 @@
1
+ name: bench
2
+
3
+ # Manual only. A benchmark on a shared runner is worth running when you want it,
4
+ # not on every push: it takes about twenty minutes and its absolute numbers are
5
+ # not comparable between runs on different machines.
6
+ on:
7
+ workflow_dispatch:
8
+ inputs:
9
+ scenarios:
10
+ description: "scenarios to run, space separated (empty = all)"
11
+ required: false
12
+ default: ""
13
+
14
+ jobs:
15
+ bench:
16
+ runs-on: ubuntu-24.04
17
+ timeout-minutes: 60
18
+ steps:
19
+ - uses: actions/checkout@v7
20
+
21
+ - uses: actions/setup-python@v7
22
+ with:
23
+ python-version: "3.12"
24
+
25
+ - name: Report the machine
26
+ # Every absolute number below depends on these. A run with a different
27
+ # core count is a different experiment, not a later data point.
28
+ run: |
29
+ echo "cores: $(nproc)"
30
+ free -m | sed -n 2p
31
+ lscpu | grep -E "Model name|MHz" || true
32
+
33
+ - name: Install Redis
34
+ # Only Redis: no bench scenario touches Postgres, and the tests that do
35
+ # are not what this workflow runs. The harness starts its own instance
36
+ # on its own port, so the one apt starts is stopped to keep it out of
37
+ # the way.
38
+ run: |
39
+ sudo apt-get update -qq
40
+ sudo apt-get install -y -qq redis-server
41
+ sudo systemctl stop redis-server || true
42
+
43
+ - name: Allow a memory-limited scope
44
+ # The runner is started from a service and has no user session bus, so
45
+ # `systemd-run --user` fails. The harness falls back to `sudo -n`, which
46
+ # is available here; this step only proves it before twenty minutes of
47
+ # work rather than after.
48
+ run: |
49
+ sudo -n systemd-run --scope -q -p MemoryMax=64M -p MemorySwapMax=0 -- true
50
+ echo "memory-limited scopes work"
51
+
52
+ - name: Build the extension
53
+ run: |
54
+ python -m venv .venv
55
+ .venv/bin/pip install -q maturin celery taskiq taskiq-redis redis
56
+ .venv/bin/maturin develop --release
57
+
58
+ - name: Run the benchmark
59
+ run: .venv/bin/python bench/run.py ${{ inputs.scenarios }} | tee bench-output.md
60
+
61
+ - uses: actions/upload-artifact@v7
62
+ with:
63
+ name: bench-${{ github.sha }}
64
+ path: bench-output.md
@@ -0,0 +1,148 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-24.04
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ # 3.14t from day one (spec §7). It is not the default path — the memory
15
+ # guarantee comes from processes, not threads — but a free-threading
16
+ # break should show up here rather than in someone's deploy.
17
+ python: ["3.11", "3.13", "3.14", "3.14t"]
18
+ steps:
19
+ - uses: actions/checkout@v7
20
+ - uses: dtolnay/rust-toolchain@stable
21
+ - uses: Swatinem/rust-cache@v2
22
+ - uses: actions/setup-python@v7
23
+ with:
24
+ python-version: ${{ matrix.python }}
25
+
26
+ # The broker tests start their own servers on free ports; these are just
27
+ # the binaries. Postgres ships with the runner image.
28
+ - run: sudo apt-get update && sudo apt-get install -y redis-server
29
+
30
+ # A venv so `maturin develop` puts the extension in the source tree,
31
+ # which is where the tests add ROOT to sys.path expects to find it.
32
+ - run: python -m venv .venv
33
+ - run: .venv/bin/pip install --upgrade pip maturin msgpack
34
+ - run: .venv/bin/maturin develop --release
35
+
36
+ - run: .venv/bin/python tests/test_ipc.py
37
+ - run: .venv/bin/python tests/test_recycle.py
38
+ - run: .venv/bin/python tests/test_brokers.py
39
+
40
+ # The definition of done, at a length CI can afford. Exits non-zero if a
41
+ # single task went missing.
42
+ - run: .venv/bin/python demo/run.py --minutes 1 --ceiling 150MB --rate 30
43
+
44
+ lint:
45
+ runs-on: ubuntu-24.04
46
+ steps:
47
+ - uses: actions/checkout@v7
48
+ - uses: dtolnay/rust-toolchain@stable
49
+ with:
50
+ components: rustfmt, clippy
51
+ - uses: Swatinem/rust-cache@v2
52
+ - run: cargo fmt --check
53
+ - run: cargo clippy --all-targets -- -D warnings
54
+ - run: cargo test --lib
55
+
56
+ test-macos:
57
+ # The wheel has been built for macOS since the first CI commit and nothing
58
+ # had ever run there, so "Linux and macOS" in pyproject.toml was a guess.
59
+ # Everything platform-specific here is a candidate: RSS accounting through
60
+ # sysinfo, ru_maxrss being bytes rather than kilobytes, and the spawn and
61
+ # socket paths.
62
+ runs-on: macos-14
63
+ steps:
64
+ - uses: actions/checkout@v7
65
+ - uses: actions/setup-python@v7
66
+ with:
67
+ python-version: "3.12"
68
+ - uses: dtolnay/rust-toolchain@stable
69
+ - name: Install Redis and Postgres
70
+ run: |
71
+ brew install -q redis postgresql@16
72
+ # The harness starts its own instances and finds initdb by globbing
73
+ # Homebrew's opt directory, so nothing needs to be on PATH or running.
74
+ brew services stop redis 2>/dev/null || true
75
+ - name: Build and test
76
+ run: |
77
+ python -m venv .venv
78
+ .venv/bin/pip install -q maturin msgpack
79
+ .venv/bin/maturin develop --release
80
+ .venv/bin/python tests/rss_probe.py
81
+ .venv/bin/python tests/test_ipc.py
82
+ .venv/bin/python tests/test_recycle.py
83
+ .venv/bin/python tests/test_brokers.py
84
+
85
+ test-windows:
86
+ # No Redis and no Postgres: neither ships for Windows, so this runs the two
87
+ # suites that use the in-process memory broker. That still exercises the
88
+ # part that is actually different — spawning a child, the named pipe, the
89
+ # protocol, RSS accounting and the recycling ceiling.
90
+ runs-on: windows-latest
91
+ steps:
92
+ - uses: actions/checkout@v7
93
+ - uses: actions/setup-python@v7
94
+ with:
95
+ python-version: "3.12"
96
+ - uses: dtolnay/rust-toolchain@stable
97
+ - name: Build and test
98
+ run: |
99
+ python -m venv .venv
100
+ .venv\Scripts\pip install -q maturin msgpack
101
+ .venv\Scripts\maturin develop --release
102
+ .venv\Scripts\python tests/rss_probe.py
103
+ .venv\Scripts\python tests/test_ipc.py
104
+ .venv\Scripts\python tests/test_recycle.py
105
+
106
+ wheels:
107
+ # Proves the matrix builds; publishing is a separate, deliberate step.
108
+ runs-on: ${{ matrix.os }}
109
+ strategy:
110
+ fail-fast: false
111
+ matrix:
112
+ include:
113
+ - { os: ubuntu-24.04, target: x86_64 }
114
+ # aarch64 cross-compiles through zig rather than the manylinux
115
+ # container's toolchain. rustls pulls in ring, whose ARM assembly the
116
+ # container's assembler rejects with `#error "ARM assembler must
117
+ # define __ARM_ARCH"`. zig cc gets the target flags right; verified by
118
+ # building this wheel on an x86_64 host before it was written here.
119
+ - { os: ubuntu-24.04, target: aarch64, zig: true }
120
+ - { os: macos-14, target: universal2-apple-darwin }
121
+ - { os: windows-latest, target: x64 }
122
+ steps:
123
+ - uses: actions/checkout@v7
124
+ - uses: actions/setup-python@v7
125
+ with:
126
+ python-version: "3.12"
127
+ - name: Provide zig
128
+ if: matrix.zig
129
+ # maturin looks for a `zig` binary on PATH; the pip package is a Python
130
+ # module, so it needs a shim.
131
+ run: |
132
+ python -m pip install --quiet ziglang
133
+ mkdir -p "$HOME/.local/bin"
134
+ printf '#!/bin/sh\nexec %s -m ziglang "$@"\n' "$(which python)" > "$HOME/.local/bin/zig"
135
+ chmod +x "$HOME/.local/bin/zig"
136
+ echo "$HOME/.local/bin" >> "$GITHUB_PATH"
137
+ - uses: PyO3/maturin-action@v1
138
+ with:
139
+ target: ${{ matrix.target }}
140
+ args: --release --out dist ${{ matrix.zig && '--zig' || '' }}
141
+ # zig cross-compiles on the host and tags the wheel manylinux itself,
142
+ # so the container would only get in the way of finding it.
143
+ container: ${{ matrix.zig && 'off' || 'auto' }}
144
+ manylinux: auto
145
+ - uses: actions/upload-artifact@v7
146
+ with:
147
+ name: wheels-${{ matrix.os }}-${{ matrix.target }}
148
+ path: dist
@@ -0,0 +1,50 @@
1
+ name: pages
2
+
3
+ # The docs are the README's long half, moved out so the README can be read in
4
+ # under a minute. Built from `site/` rather than `docs/`, which this repository
5
+ # keeps out of git.
6
+ on:
7
+ push:
8
+ branches: [main]
9
+ paths:
10
+ - "site/**"
11
+ - ".github/workflows/pages.yml"
12
+ workflow_dispatch:
13
+
14
+ permissions:
15
+ contents: read
16
+ pages: write
17
+ id-token: write
18
+
19
+ # One deploy at a time, and let a newer push win rather than queueing behind an
20
+ # older one that is about to be replaced anyway.
21
+ concurrency:
22
+ group: pages
23
+ cancel-in-progress: true
24
+
25
+ jobs:
26
+ build:
27
+ runs-on: ubuntu-24.04
28
+ steps:
29
+ - uses: actions/checkout@v7
30
+ # Pages has never been switched on for this repository, and this
31
+ # turns it on rather than failing the first run with a setting
32
+ # somebody has to find in the web UI.
33
+ - uses: actions/configure-pages@v6
34
+ with:
35
+ enablement: true
36
+ - uses: actions/jekyll-build-pages@v1
37
+ with:
38
+ source: ./site
39
+ destination: ./_site
40
+ - uses: actions/upload-pages-artifact@v5
41
+
42
+ deploy:
43
+ needs: build
44
+ runs-on: ubuntu-24.04
45
+ environment:
46
+ name: github-pages
47
+ url: ${{ steps.deploy.outputs.page_url }}
48
+ steps:
49
+ - id: deploy
50
+ uses: actions/deploy-pages@v5
@@ -0,0 +1,158 @@
1
+ name: release
2
+
3
+ # Started from `maturin generate-ci github --platform all`, then cut down. What
4
+ # changed from the generated file, and why, is in the comments below — the
5
+ # generator does not know what this project links against or what it needs at
6
+ # runtime, and two of its defaults would have shipped wheels that cannot work.
7
+ #
8
+ # Tags only. `ci.yml` already builds a four-target smoke matrix on every push;
9
+ # this one is the full set and the publish, and both are wasted on a branch.
10
+ on:
11
+ push:
12
+ # Both spellings. The first tag written for this project was `0.1.0`, the
13
+ # trigger only listened for `v*`, and the push went nowhere — a release
14
+ # that silently does not happen is a worse failure than one that stops
15
+ # with a message.
16
+ tags: ["v[0-9]*", "[0-9]*"]
17
+ workflow_dispatch:
18
+
19
+ permissions:
20
+ contents: read
21
+
22
+ jobs:
23
+ check:
24
+ # Before ten wheels are built and before anything can reach PyPI, because
25
+ # PyPI does not allow a version to be uploaded twice: publishing 0.1.0
26
+ # under a tag that says something else cannot be taken back.
27
+ runs-on: ubuntu-24.04
28
+ steps:
29
+ - uses: actions/checkout@v7
30
+ - name: The tag must match the version
31
+ if: startsWith(github.ref, 'refs/tags/')
32
+ run: |
33
+ declared=$(grep -m1 '^version' pyproject.toml | cut -d'"' -f2)
34
+ tagged=${GITHUB_REF_NAME#v}
35
+ echo "pyproject says $declared, tag says $tagged"
36
+ if [ "$declared" != "$tagged" ]; then
37
+ echo "::error::tag $GITHUB_REF_NAME does not match version $declared in pyproject.toml"
38
+ exit 1
39
+ fi
40
+
41
+ build:
42
+ needs: check
43
+ runs-on: ${{ matrix.os }}
44
+ strategy:
45
+ fail-fast: false
46
+ matrix:
47
+ include:
48
+ - { os: ubuntu-24.04, target: x86_64, manylinux: auto }
49
+ # aarch64 cross-compiles through zig rather than the manylinux
50
+ # container's toolchain. rustls pulls in ring, whose ARM assembly the
51
+ # container's assembler rejects with `#error "ARM assembler must
52
+ # define __ARM_ARCH"`.
53
+ #
54
+ # `maturin generate-ci --zig` does exist and adds the flag, but it
55
+ # leaves the container on; only `container: off` is the form this
56
+ # repository has actually built an aarch64 wheel with. Whether the
57
+ # generated combination also works here is untested, which is the
58
+ # only reason it is not used.
59
+ - { os: ubuntu-24.04, target: aarch64, manylinux: auto, zig: true }
60
+ - { os: ubuntu-24.04, target: x86_64, manylinux: musllinux_1_2, musl: true }
61
+ - { os: macos-14, target: universal2-apple-darwin }
62
+ - { os: windows-latest, target: x64 }
63
+ steps:
64
+ - uses: actions/checkout@v7
65
+ - uses: actions/setup-python@v7
66
+ with:
67
+ python-version: "3.12"
68
+ - name: Provide zig
69
+ if: matrix.zig
70
+ # maturin looks for a `zig` binary on PATH; the pip package is a Python
71
+ # module, so it needs a shim.
72
+ run: |
73
+ python -m pip install --quiet ziglang
74
+ mkdir -p "$HOME/.local/bin"
75
+ printf '#!/bin/sh\nexec %s -m ziglang "$@"\n' "$(which python)" > "$HOME/.local/bin/zig"
76
+ chmod +x "$HOME/.local/bin/zig"
77
+ echo "$HOME/.local/bin" >> "$GITHUB_PATH"
78
+ - uses: PyO3/maturin-action@v1
79
+ with:
80
+ target: ${{ matrix.target }}
81
+ args: --release --out dist ${{ matrix.zig && '--zig' || '' }}
82
+ # zig cross-compiles on the host and tags the wheel manylinux itself,
83
+ # so the container would only get in the way of finding it.
84
+ container: ${{ matrix.zig && 'off' || 'auto' }}
85
+ manylinux: ${{ matrix.manylinux }}
86
+ sccache: true
87
+ - name: Build the free-threaded wheel
88
+ # abi3 stops at the GIL: a free-threaded build cannot use the stable
89
+ # ABI, so 3.14t needs a wheel of its own or its users compile from the
90
+ # sdist. CI has tested 3.14t since the first commit, and shipping
91
+ # without this would have been a supported version with no wheel.
92
+ uses: PyO3/maturin-action@v1
93
+ with:
94
+ target: ${{ matrix.target }}
95
+ args: --release --out dist -i python3.14t ${{ matrix.zig && '--zig' || '' }}
96
+ container: ${{ matrix.zig && 'off' || 'auto' }}
97
+ manylinux: ${{ matrix.manylinux }}
98
+ sccache: true
99
+ - uses: actions/upload-artifact@v7
100
+ with:
101
+ name: wheels-${{ matrix.os }}-${{ matrix.target }}${{ matrix.musl && '-musl' || '' }}
102
+ path: dist
103
+
104
+ sdist:
105
+ needs: check
106
+ runs-on: ubuntu-24.04
107
+ steps:
108
+ - uses: actions/checkout@v7
109
+ - uses: PyO3/maturin-action@v1
110
+ with:
111
+ command: sdist
112
+ args: --out dist
113
+ - uses: actions/upload-artifact@v7
114
+ with:
115
+ name: wheels-sdist
116
+ path: dist
117
+
118
+ publish:
119
+ needs: [build, sdist]
120
+ runs-on: ubuntu-24.04
121
+ environment:
122
+ name: pypi
123
+ url: https://pypi.org/p/tarsk
124
+ permissions:
125
+ # Trusted publishing, so there is no API token in this repository to
126
+ # rotate or leak. PyPI has to know about this workflow first: add a
127
+ # pending publisher for `tarsk` naming this repository, `release.yml`
128
+ # and the `pypi` environment. Renaming this file breaks that link.
129
+ id-token: write
130
+ # For the artifact attestation and the GitHub release.
131
+ attestations: write
132
+ contents: write
133
+ steps:
134
+ - uses: actions/download-artifact@v8
135
+ with:
136
+ pattern: wheels-*
137
+ merge-multiple: true
138
+ path: dist
139
+ - uses: actions/attest-build-provenance@v4
140
+ with:
141
+ subject-path: "dist/*"
142
+ # Pinned to the full version: setup-uv stopped publishing a moving
143
+ # major tag after v7, so @v10 does not resolve.
144
+ - uses: astral-sh/setup-uv@v10.0.1
145
+ - name: Publish to PyPI
146
+ # Only a tag publishes. A manual run builds every wheel and attests
147
+ # them, which is the rehearsal worth having before the first release.
148
+ if: startsWith(github.ref, 'refs/tags/')
149
+ # `always` rather than the `automatic` default: automatic falls back
150
+ # to looking for a token and would fail with a credentials error
151
+ # instead of saying the publisher is not configured.
152
+ run: uv publish --trusted-publishing always dist/*
153
+ - uses: softprops/action-gh-release@v3
154
+ if: startsWith(github.ref, 'refs/tags/')
155
+ with:
156
+ files: dist/*
157
+ generate_release_notes: true
158
+ prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }}
tarsk-0.1.0/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ /docs/
2
+ /target/
3
+ /.venv/
4
+ __pycache__/
5
+ *.py[cod]
6
+ *.so
7
+ /demo/out*/