blackbull.grpc.asgi¶
blackbull.grpc.asgi
¶
ASGI bridge that serves gRPC calls over BlackBull's HTTP/2 layer.
gRPC is HTTP/2 with a fixed request shape (POST /package.Service/Method,
content-type: application/grpc) and a Length-Prefixed-Message body, where
the call result is reported in grpc-status / grpc-message trailers.
BlackBull's HTTP/2 sender already emits trailers via the
http.response.trailers ASGI event, and HTTP2Recipient already delivers
request DATA as incremental http.request events, so all four RPC kinds —
unary, server-, client-, and bidirectional-streaming — map cleanly onto the
existing (scope, receive, send) bridge; no new protocol Actor is needed
(see .claude/planning/designs/grpc-streaming-request-design.md).
serve_grpc is dispatched from :meth:BlackBull._dispatch when the request
content-type is application/grpc and a registry was installed via
app.enable_grpc(...).
GrpcContext
¶
Per-call context handed to a gRPC handler.
Exposes request metadata (the HTTP/2 headers), the call deadline and peer,
and lets the handler set the outgoing status, a human-readable message,
leading/trailing metadata, or abort the call outright — the subset of
grpcio's ServicerContext that a raw-bytes transport can honour.
The response-start machinery (_send … _started) is bound by
:func:serve_grpc just before the handler runs; handlers touch it only via
:meth:send_initial_metadata.
abort(status, details='')
¶
Raise :class:GrpcError to end the call with a non-OK status.
invocation_metadata()
¶
Return all request metadata (HTTP/2 headers) as (name, value)
pairs — grpcio's ServicerContext.invocation_metadata. Pseudo-
headers (:method, :path, …) are excluded; they are call routing,
not application metadata.
metadata(name, default=b'')
¶
Return a request header (call metadata) value, or default.
peer()
¶
Return the client address as grpcio formats it (ipv4:host:port /
ipv6:[host]:port), or '' when the transport did not supply one.
send_initial_metadata(metadata)
async
¶
Send response leading metadata now (the initial HTTP/2 HEADERS),
before the first response message — grpcio's
ServicerContext.send_initial_metadata.
Optional: if never called, the response HEADERS are still emitted lazily
(just before the first message, or with the trailers for an empty
response). Calling it flushes them early with metadata attached — used
to hand the client leading metadata (auth challenges, stream ids) up
front. Raises :class:ValueError once the HEADERS have already gone
out (grpcio's "initial metadata no longer allowed").
time_remaining()
¶
Seconds left until the call deadline (never negative), or None
when the client set no grpc-timeout — grpcio's
ServicerContext.time_remaining. Lets a handler shed work it cannot
finish in time.
trailing_metadata()
¶
The trailing metadata set so far (a copy) — lets helpers compose
with, rather than clobber, what the handler already set (e.g.
blackbull-protobuf's abort_with_details appending
grpc-status-details-bin).
serve_grpc(registry, conn, receive, send)
async
¶
Serve a single gRPC call (unary or server-streaming) through the ASGI (scope, receive, send) bridge. Never raises for handler/protocol errors: every failure path is reported as a gRPC status.