transport

package
v0.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 24, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package transport defines the contract between the application lifecycle and the servers it runs, and the call-scoped view middleware gets of the transport underneath it.

Server is all the lifecycle requires: Start and Stop. Everything else is an optional capability discovered by type assertion — Endpointer for the address to publish to a registry, Healthzer for readiness, GracefulStopper for draining, ReplyHeaderer for a mutable reply header. A server that does not implement one makes no claim, and consumers must not require more than they need.

Transporter is what middleware sees: the transport Kind, the opaque Operation string, the endpoint, and the request header. It travels in the context — FromServerContext on the serving side, FromClientContext on the calling side. Kind is an open type: transports outside this module declare their own.

MarkNotSent and WasNotSent carry delivery evidence: a transport marks an error only when it can prove the request never left the process, which is what the retry middleware needs to retry safely without an idempotence declaration (see docs/design/retry.md).

The concrete transports live in the subpackages http, grpc, and message.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MarkNotSent

func MarkNotSent(err error) error

MarkNotSent records that the request reporting err was never written to the wire, making the failure safe to retry regardless of whether the operation is idempotent. It returns err unchanged when err is nil or already marked.

A transport MUST mark only what it can prove. "The connection never opened" and "no connection was available to write to" are proof; "the request was written and no response came back" is not — a server may have executed it and lost the reply. When a transport cannot tell the two apart, it leaves the error unmarked: the absence of the mark reads as "the request may have executed", which is the safe assumption.

func NewClientContext

func NewClientContext(ctx context.Context, tr Transporter) context.Context

NewClientContext returns a new Context that carries value.

func NewServerContext

func NewServerContext(ctx context.Context, tr Transporter) context.Context

NewServerContext returns a new Context that carries value.

func WasNotSent

func WasNotSent(err error) bool

WasNotSent reports whether err carries the MarkNotSent evidence anywhere in its chain, meaning a transport proved the request never reached a server.

A false result is not proof of the opposite. It means no transport claimed the request was withheld — either because it was sent, or because the transport could not tell.

Types

type Endpointer

type Endpointer interface {
	Endpoint() (*url.URL, error)
}

Endpointer is registry endpoint.

type GracefulStopper

type GracefulStopper interface {
	// GracefulStop stops accepting new work, waits for in-flight work to
	// finish, and returns nil once the server has stopped. When ctx ends
	// first, it abandons the wait and returns the context's error; the drain
	// keeps running in the background, and the caller decides whether to
	// force termination with Stop.
	//
	// Stop keeps its own contract — terminate within the bounds the context
	// allows, by force if necessary. A lifecycle manager shutting down a
	// server that implements GracefulStopper prefers it and falls back to
	// Stop when the drain is abandoned or fails.
	GracefulStop(context.Context) error
}

GracefulStopper is implemented by servers that can drain in-flight work before stopping. It is an optional capability alongside Server: consumers type-assert for it.

type Header interface {
	Get(key string) string
	Set(key string, value string)
	Add(key string, value string)
	Keys() []string
	Values(key string) []string
}

Header is the storage medium used by a Header.

type Healthzer

type Healthzer interface {
	// Healthz reports readiness, not liveness: whether the server can accept
	// new work right now. It is false before the server starts accepting
	// traffic, true while it accepts, and false again as soon as shutdown or
	// draining begins — before the listener actually closes. Liveness — is
	// the process running at all — is expressed by the process itself and
	// needs no method.
	//
	// Healthz must be safe to call concurrently with the server lifecycle
	// and must not block.
	Healthz() bool
}

Healthzer is implemented by servers that can report whether they are ready to accept new work. Like Endpointer and ReplyHeaderer it is an optional capability: consumers type-assert for it, and a Server that does not implement it makes no readiness claim.

type Kind

type Kind string

Kind defines the type of Transport. It is an open type: a transport outside this module may declare its own constant rather than extending the set below.

const (
	KindGRPC Kind = "grpc"
	KindHTTP Kind = "http"
)

Defines a set of transport kind

func (Kind) String

func (k Kind) String() string

type ReplyHeaderer

type ReplyHeaderer interface {
	// ReplyHeader returns the transport reply header. Only valid for a server
	// transport.
	// http: http.Header
	// grpc: metadata.MD
	ReplyHeader() Header
}

ReplyHeaderer is implemented by transports that expose a mutable reply header. Request/response transports do; message and stream transports need not. Consumers type-assert for it.

type Server

type Server interface {
	Start(context.Context) error
	Stop(context.Context) error
}

Server is transport server.

type Transporter

type Transporter interface {
	// Kind returns the transport kind, such as KindHTTP or KindGRPC. The set
	// is open: a transport outside this module may declare its own Kind.
	Kind() Kind
	// Endpoint returns the server or client endpoint.
	// Server Transport: grpc://127.0.0.1:9000
	// Client Transport: discovery:///provider-demo
	Endpoint() string
	// Operation identifies the call in flight. The format belongs to the
	// transport: gRPC reports the protobuf method selector
	// (/helloworld.Greeter/SayHello), a message transport reports the
	// destination (orders.created), a JSON-RPC transport reports the method
	// name.
	//
	// Callers MUST treat the value as opaque and MUST NOT parse it. It is
	// meant for labeling and keying — span names, rate-limit dimensions,
	// selector matching, log fields. Dispatch on Kind and read the concrete
	// transport type when structure is required.
	Operation() string
	// RequestHeader returns the transport request header.
	// http: http.Header
	// grpc: metadata.MD
	RequestHeader() Header
}

Transporter carries what middleware needs to know about the call in flight.

Its methods describe what every transport has, not the shape of a request/response exchange. A transport that has no meaningful reply header — a message queue, a bidirectional stream — implements this interface and, if it does expose one, ReplyHeaderer as well.

func FromClientContext

func FromClientContext(ctx context.Context) (tr Transporter, ok bool)

FromClientContext returns the Transport value stored in ctx, if any.

func FromServerContext

func FromServerContext(ctx context.Context) (tr Transporter, ok bool)

FromServerContext returns the Transport value stored in ctx, if any.

Directories

Path Synopsis
Package grpc provides Forge's gRPC transport: a server wrapping google.golang.org/grpc with Forge's lifecycle and middleware contracts, and a client constructor that wires the same contracts into a *grpc.ClientConn.
Package grpc provides Forge's gRPC transport: a server wrapping google.golang.org/grpc with Forge's lifecycle and middleware contracts, and a client constructor that wires the same contracts into a *grpc.ClientConn.
Package http provides Forge's HTTP transport: a server that generated service code registers routes on, and a client that generated code calls through.
Package http provides Forge's HTTP transport: a server that generated service code registers routes on, and a client that generated code calls through.
healthz
Package healthz serves a readiness probe over HTTP for anything that implements transport.Healthzer — one server, or an App aggregating all of its servers.
Package healthz serves a readiness probe over HTTP for anything that implements transport.Healthzer — one server, or an App aggregating all of its servers.
transcoding
Package transcoding carries the Protobuf half of Forge's HTTP transport: Google HTTP transcoding, ProtoJSON projection, path and query binding, raw HTTP bodies, and stream body fields.
Package transcoding carries the Protobuf half of Forge's HTTP transport: Google HTTP transcoding, ProtoJSON projection, path and query binding, raw HTTP bodies, and stream body fields.
Package message defines the protocol-neutral contract for asynchronous message transports.
Package message defines the protocol-neutral contract for asynchronous message transports.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL