# _drain

URL: /pounce/api/_drain/
Section: api
Description: Shared drain-503 wire format and write helpers.

Single source of truth for the HTTP 503 response that every worker mode
emits to *new* connections while the server is draining (SIGTERM / SIGHUP).
Keeping the bytes in one place means the async ``Worker``, the blocking
``SyncWorker`` and the ``AcceptDistributor`` answer byte-identically:

    HTTP/1.1 503 Service Unavailable
    Connection: close
    Retry-After: 1
    Content-Type: text/plain; charset=utf-8
    Content-Length: 23

    Server shutting down...

The body is short and actionable; ``Retry-After`` tells well-behaved
clients (and load balancers) to come back, while ``Connection: close``
guarantees the socket is torn down after the single response.

---

> For a complete page index, fetch /pounce/llms.txt.

Open LLM text
(/pounce/api/_drain/index.txt)

Share with AI

Ask Claude
(https://claude.ai/new?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fpounce%2Fapi%2F_drain%2Findex.txt)

Ask ChatGPT
(https://chatgpt.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fpounce%2Fapi%2F_drain%2Findex.txt)

Ask Gemini
(https://gemini.google.com/app?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fpounce%2Fapi%2F_drain%2Findex.txt)

Ask Copilot
(https://copilot.microsoft.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fpounce%2Fapi%2F_drain%2Findex.txt)

Module

#
`_drain`

Shared drain-503 wire format and write helpers.

Single source of truth for the HTTP 503 response that every worker mode
emits to new connections while the server is draining (SIGTERM / SIGHUP).
Keeping the bytes in one place means the async`Worker`, the blocking
`SyncWorker` and the `AcceptDistributor`answer byte-identically:

```
HTTP/1.1 503 Service Unavailable
Connection: close
Retry-After: 1
Content-Type: text/plain; charset=utf-8
Content-Length: 23

Server shutting down...
```

The body is short and actionable;`Retry-After`tells well-behaved
clients (and load balancers) to come back, while`Connection: close`
guarantees the socket is torn down after the single response.

8Functions

## Functions

`_draining_health_method`

2

`bytes | None`

▼

Return GET/HEAD when *request_head* targets the configured health path.

`def _draining_health_method(request_head: bytes, health_check_path: str | None) -> bytes | None`

##### Parameters

Name
Type
Description

`request_head`
`bytes`

`health_check_path`
`str | None`

##### Returns

`bytes | None`

`_draining_health_response`

3

`bytes`

▼

Serialize the configured readiness response for the drain boundary.

`def _draining_health_response(method: bytes, *, worker_id: int, active_connections: int) -> bytes`

##### Parameters

Name
Type
Description

`method`
`bytes`

`worker_id`
`int`

`active_connections`
`int`

##### Returns

`bytes`

`_read_request_head_sync`

3

`bytes`

▼

Read one bounded HTTP/1 header block from a draining socket.

`def _read_request_head_sync(conn: socket.socket, config: ServerConfig, *, timeout: float | None) -> bytes`

##### Parameters

Name
Type
Description

`conn`
`socket.socket`

`config`
`ServerConfig (/pounce/api/config/#ServerConfig)`

`timeout`
`float | None`

##### Returns

`bytes`

`_read_request_head_async`

3

`bytes`

▼

Read one bounded HTTP/1 header block from a draining stream.

async

`async def _read_request_head_async(reader: asyncio.StreamReader, config: ServerConfig, *, timeout: float | None) -> bytes`

##### Parameters

Name
Type
Description

`reader`
`asyncio.StreamReader`

`config`
`ServerConfig (/pounce/api/config/#ServerConfig)`

`timeout`
`float | None`

##### Returns

`bytes`

`write_drain_503_sync`

1

`None`

▼

Send the drain 503 on a blocking socket; the caller still owns the close.

Tole…

`def write_drain_503_sync(conn: socket.socket) -> None`

Send the drain 503 on a blocking socket; the caller still owns the close.

Tolerates a client that has already gone away — a dropped connection
during shutdown is expected, not exceptional.

##### Parameters

Name
Type
Description

`conn`
`socket.socket`

`write_drain_response_sync`

5

`None`

▼

Inspect one bounded request and write the matching drain response.

`def write_drain_response_sync(conn: socket.socket, config: ServerConfig, *, worker_id: int, active_connections: int, timeout: float | None = None) -> None`

##### Parameters

Name
Type
Description

`conn`
`socket.socket`

`config`
`ServerConfig (/pounce/api/config/#ServerConfig)`

`worker_id`
`int`

`active_connections`
`int`

`timeout`
`float | None`

Default:`None`

`write_drain_503_async`

2

`None`

▼

Send the drain 503 on an asyncio writer and close it.

Tolerates a client that …

async

`async def write_drain_503_async(writer: asyncio.StreamWriter, *, timeout: float = 30.0) -> None`

Send the drain 503 on an asyncio writer and close it.

Tolerates a client that has already gone away — a dropped connection
during shutdown is expected, not exceptional.

##### Parameters

Name
Type
Description

`writer`
`asyncio.StreamWriter`

`timeout`
`float`

Default:`30.0`

`write_drain_response_async`

6

`None`

▼

Inspect one bounded request, write its drain response, and close.

async

`async def write_drain_response_async(reader: asyncio.StreamReader, writer: asyncio.StreamWriter, config: ServerConfig, *, worker_id: int, active_connections: int, timeout: float | None = None) -> None`

##### Parameters

Name
Type
Description

`reader`
`asyncio.StreamReader`

`writer`
`asyncio.StreamWriter`

`config`
`ServerConfig (/pounce/api/config/#ServerConfig)`

`worker_id`
`int`

`active_connections`
`int`

`timeout`
`float | None`

Default:`None`
