3401 Commits

Author SHA1 Message Date
Benoit Chesneau
6d2139bb6c feat(dirty): update worker for binary protocol
Update worker tests to work with the binary protocol:
- Use integer request IDs instead of strings
- Update MockStreamWriter to decode binary messages
- Import binary protocol constants from module level
2026-02-11 23:01:21 +01:00
Benoit Chesneau
1665857c0e feat(dirty): implement binary protocol
Replace JSON-based protocol with binary format using 16-byte header:
- Magic bytes (GD), version, message type, payload length, request ID
- TLV-encoded payloads for efficient binary data transfer
- No base64 encoding needed for binary data
- Backwards compatible API (DirtyProtocol alias, dict-based interface)

Header format inspired by OpenBSD msgctl/msgsnd.
2026-02-11 22:58:43 +01:00
Benoit Chesneau
0e0dc669c8 feat(dirty): add TLV binary encoder/decoder
Implement TLV (Type-Length-Value) serialization layer for the binary
dirty worker protocol. This enables efficient binary data transfer
without base64 encoding overhead.

Supported types:
- None, bool, int64, float64
- bytes (raw binary, no encoding needed)
- string (UTF-8)
- list, dict (nested structures)

Inspired by OpenBSD msgctl/msgsnd message format.
2026-02-11 22:55:03 +01:00
Benoit Chesneau
fc850687df chore: prepare release 25.0.3 2026-02-07 15:36:43 +01:00
Benoit Chesneau
787602fc88 docs: shorten README sponsor section
Match homepage style and link to sponsor page for details.
2026-02-07 14:49:09 +01:00
Benoit Chesneau
a52c81ff3a
Merge pull request #3492 from benoitc/feature/improve-sponsorship
docs: improve sponsorship visibility
2026-02-07 14:45:53 +01:00
Benoit Chesneau
1afb2b7da9
Merge pull request #3490 from tyrossel/master
fix: passing maxsplit in re.split() as positional argument is deprecated
2026-02-07 14:45:05 +01:00
Benoit Chesneau
2ead70d7b3 docs: add Sponsor to top-level navigation
Make sponsor page more visible by adding it as a top-level nav item
after Community, while keeping it in Community submenu as well.
2026-02-07 14:07:53 +01:00
Benoit Chesneau
874e8be0a1 docs: shorten sponsor section on homepage
Simplify the sponsor section to a single concise line and link to
the dedicated sponsor page instead of GitHub sponsors directly.
2026-02-07 11:31:40 +01:00
Benoit Chesneau
7293b216f4 docs: add prominent sponsorship options
- Add sponsor banner at top of README
- Add Revolut and Open Collective to FUNDING.yml
- Add dedicated sponsor page in docs
- Add sponsor heart link in footer
2026-02-07 11:29:15 +01:00
Benoit Chesneau
70d571bd7c docs: update homepage title and remove version display
- Change title from "The Python WSGI Server" to "Serve Python Apps on the Web"
- Remove "Version {{ version }}" text from hero section
- Remove unused .hero__version CSS
2026-02-07 11:08:04 +01:00
Benoit Chesneau
d301d53758 fix: resolve RuntimeError when StopIteration raised in ASGI coroutine
In Python 3.7+, PEP 479 converts StopIteration raised inside coroutines
to RuntimeError. Changed _read_into() to raise NoMoreData instead, which
is already properly handled by the protocol layer.
2026-02-07 09:00:46 +01:00
Benoit Chesneau
9508df658d test: increase CI timeout for signal tests on PyPy 2026-02-06 09:00:29 +01:00
Tanguy Rossel
68abb98e4e
fix: passing maxsplit in re.split() as positional argument is deprecated 2026-02-06 08:42:32 +01:00
Benoit Chesneau
2c0f9593a4 fix: remove trailing blank line in instrument/__init__.py 2026-02-06 08:36:35 +01:00
Benoit Chesneau
95b7ffeeaa chore: prepare release 25.0.2
- Bump version to 25.0.2
- Update copyright year to 2026 in LICENSE and NOTICE
- Add license headers to all Python source files
- Add changelog entry for 25.0.2
2026-02-06 08:21:18 +01:00
Benoit Chesneau
026167acc9 refactor: extract _normalize_sockaddr utility function
Consolidate the repeated pattern for normalizing socket addresses
to ASGI-compatible (host, port) tuples into a single utility function.
2026-02-06 02:57:04 +01:00
Benoit Chesneau
e780508f56 fix: resolve ASGI concurrent request failures through nginx proxy
- Fix nginx config to use keepalive with upstream (was sending
  Connection: close which caused premature connection closure)
- Add _safe_write() to handle socket errors (EPIPE, ECONNRESET,
  ENOTCONN) gracefully when client disconnects
- Fix ASGI scope server/client to always be 2-tuples for IPv6
  compatibility (IPv6 sockets return 4-tuples)
- Add write_eof() before close() to ensure buffered data is flushed
- Bind to [::] for dual-stack IPv4/IPv6 support in test containers
2026-02-06 01:57:28 +01:00
Benoit Chesneau
866e88cfd6
Merge pull request #3485 from benoitc/fix/asgi-graceful-disconnect
fix: graceful disconnect handling for ASGI worker
2026-02-03 09:30:19 +01:00
Benoit Chesneau
3bf718ea52 fix: graceful disconnect handling for ASGI worker
Closes #3484

When a client disconnects during an ASGI request, the worker now:
1. Sends http.disconnect message to the app's receive queue
2. Allows a configurable grace period for cleanup (default: 3 seconds)
3. Only cancels the task after the grace period expires

This follows the ASGI HTTP Connection Scope spec which defines
http.disconnect as the message apps should receive when clients
disconnect: https://asgi.readthedocs.io/en/latest/specs/www.html#disconnect-receive-event

The grace period prevents CancelledError from propagating to async
database operations, allowing SQLAlchemy and other async DB libraries
to properly reset their connection pools.

New config option: --asgi-disconnect-grace-period (default: 3 seconds)
2026-02-03 02:46:07 +01:00
Benoit Chesneau
15cadf87a7
Merge pull request #3483 from benoitc/fix/gevent-concurrent-futures-import
fix: lazy import dirty module for gevent compatibility
2026-02-03 01:33:32 +01:00
Benoit Chesneau
b19c648a67 fix: lazy import dirty module for gevent compatibility
Closes #3482

The dirty module (which uses asyncio and concurrent.futures) was being
imported at gunicorn startup via gunicorn.arbiter. This caused
concurrent.futures to be imported before user code could call
gevent.monkey.patch_all(), breaking gevent's monkey-patching.

Changes:
- gunicorn/arbiter.py: Import DirtyArbiter and set_dirty_socket_path
  lazily inside spawn_dirty_arbiter() instead of at module level
- gunicorn/dirty/worker.py: Import ThreadPoolExecutor lazily inside
  run() method instead of at module level
- Add tests/workers/test_gevent_import_order.py with 5 tests verifying:
  - concurrent.futures is NOT imported when gunicorn.arbiter loads
  - gevent patching works correctly with gunicorn
  - Reproduces the exact scenario from the bug report gist

This ensures gevent's monkey.patch_all() can run before concurrent.futures
is imported, allowing proper patching of threading primitives.
2026-02-03 01:15:39 +01:00
Benoit Chesneau
3373e4b987 docs: add CNAME file for custom domain 2026-02-02 23:36:30 +01:00
Benoit Chesneau
a7e14e16fd docs: replace sponsors section with expanded support section
Update README.md and docs homepage with detailed support messaging
including sponsorship benefits and corporate contact information.
2026-02-02 21:49:15 +01:00
Benoit Chesneau
3bf529f6c2 docs: sync news.md with 2026-news.md 2026-02-02 14:28:37 +01:00
Benoit Chesneau
1f4f245d76
Merge pull request #3478 from benoitc/feature/asgi-compliance-testbed
Add ASGI compliance test suite
2026-02-02 14:20:52 +01:00
Benoit Chesneau
e1519c0569 docs: add ASGI compliance test suite to changelog 2026-02-02 14:11:22 +01:00
Benoit Chesneau
0885005b08 fix(tests): correct assertions in ASGI compliance tests
- Fix path expectation in test_scope_path_preserved (router strips /http prefix)
- Fix lifespan state check to use scope_state instead of module_state
- Add tolerance for partial failures in proxy concurrent test
- Add retry logic with proper assertions in HTTPS proxy FastAPI test
2026-02-02 14:04:26 +01:00
Benoit Chesneau
658924c436 docs: update changelog for 25.0.1 2026-02-02 10:17:50 +01:00
Benoit Chesneau
c5b6e82277 chore: bump version to 25.0.1 2026-02-02 10:16:07 +01:00
Benoit Chesneau
ce352dc230 fix(asgi): add chunked transfer encoding for streaming responses
Add chunked transfer encoding support to the ASGI worker for HTTP/1.1
streaming responses that don't have a Content-Length header. This fixes
SSE (Server-Sent Events) connections not closing properly.

Without chunked encoding or Content-Length, HTTP/1.1 clients wait for
the connection to close to determine end-of-response, causing streaming
endpoints to hang.

Also updates the celery_alternative example to use FastAPI with the
native ASGI worker and uvloop, demonstrating async task execution with
proper SSE streaming.
2026-02-02 10:13:33 +01:00
Benoit Chesneau
29b8a3a763
Merge pull request #3476 from benoitc/dependabot/github_actions/actions/checkout-6
chore(deps): bump actions/checkout from 4 to 6
2026-02-02 00:47:56 +01:00
dependabot[bot]
791ab46e1c
chore(deps): bump actions/checkout from 4 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-01 23:47:36 +00:00
Benoit Chesneau
9235b72ab8
Merge pull request #3475 from benoitc/dependabot/github_actions/actions/upload-artifact-6
chore(deps): bump actions/upload-artifact from 4 to 6
2026-02-02 00:47:05 +01:00
Benoit Chesneau
26674b2ee8
Merge pull request #3474 from benoitc/dependabot/github_actions/actions/setup-python-6
chore(deps): bump actions/setup-python from 5 to 6
2026-02-02 00:46:36 +01:00
dependabot[bot]
0d8c3abe17
chore(deps): bump actions/upload-artifact from 4 to 6
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-01 21:42:44 +00:00
dependabot[bot]
772e4a250b
chore(deps): bump actions/setup-python from 5 to 6
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-01 21:42:41 +00:00
Benoit Chesneau
be54850ff8 docs: rename example title to Celery Alternative 2026-02-01 16:54:22 +01:00
Benoit Chesneau
17ac6a5254 examples: add celery_alternative example using dirty arbiters
Demonstrates replacing Celery with Gunicorn's dirty arbiters for
background task processing. Includes:

- 4 task workers: Email, Image, Data, Scheduled
- Stateful workers with persistent connections/caches
- Streaming progress for long-running tasks
- Per-app worker allocation
- Flask API with 15+ endpoints
- Docker deployment (single container vs Celery's 4+)
- Unit tests (19 tests) and integration tests
- Migration guide from Celery
2026-02-01 16:51:48 +01:00
Benoit Chesneau
9ece4a6873 docs: add GitHub icon to header, remove header.autohide 2026-02-01 15:04:41 +01:00
Benoit Chesneau
8652aec783 docs: update news.md with complete 25.0.0 changelog 2026-02-01 14:50:02 +01:00
Benoit Chesneau
d621aa81f9 fix: add version number to homepage hero section 2026-02-01 14:47:48 +01:00
Benoit Chesneau
617a85ea91 docs: update 25.0.0 release date to 2026-02-01 2026-02-01 14:30:56 +01:00
Benoit Chesneau
ee933f2e30 fix(asgi): quick shutdown on SIGINT/SIGQUIT, graceful on SIGTERM
- SIGINT/SIGQUIT triggers immediate shutdown, skipping connection waits
- SIGTERM triggers graceful shutdown, waiting for connections
- Arbiter forwards SIGQUIT to workers if received during graceful shutdown
- Workers have 2s to exit cleanly after quick shutdown before SIGKILL
2026-02-01 10:06:23 +01:00
Benoit Chesneau
98ef198baa docs: update security policy for maintained versions 24.1.1 and 25.0.0 2026-02-01 09:27:03 +01:00
Benoit Chesneau
911e333b4e chore: replace RST with markdown, remove docs-lint and readthedocs config 2026-02-01 09:23:15 +01:00
Benoit Chesneau
7ff671bca3 chore: replace README.rst with README.md, remove modernization-plan.md 2026-02-01 09:18:11 +01:00
Benoit Chesneau
d5ab5dc6c1
Merge pull request #3473 from benoitc/feature/per-app-worker-allocation
feat(dirty): add per-app worker allocation for memory optimization
2026-02-01 09:06:05 +01:00
Benoit Chesneau
d563a7e436 chore: bump version to 25.0.0 2026-02-01 09:05:10 +01:00
Benoit Chesneau
86264ef900 docs: add per-app worker allocation to 25.0.0 changelog 2026-02-01 08:32:46 +01:00