connect

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package connect manages a pool of reusable gRPC client connections keyed by a caller-supplied logical key, distinct from the dial target. Use NewPool to create a Pool, Set to register a connection for a key, Conn to retrieve it, ConnOrCreate to retrieve or create one on first use, and Close to shut every connection down exactly once.

Conn wraps that pool as a grpc.ClientConnInterface whose dial target is chosen per call by a Resolver: StaticResolver for a fixed upstream, or a caller-supplied dynamic Resolver that varies the target with the request.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrDuplicateKey is returned by Pool.Set when a connection is already
	// registered for the given key.
	ErrDuplicateKey = errors.New("key already defined")

	// ErrKeyNotFound is returned by Pool.Conn when no connection is registered
	// for the given key.
	ErrKeyNotFound = errors.New("no connection for key")
)
View Source
var Module = fx.Options(
	fx.Provide(NewPool),
	fx.Invoke(func(p *Pool, lc fx.Lifecycle) {
		lc.Append(fx.StopHook(func() error {
			return p.Close()
		}))
	}),
)

Module provides a *Pool and binds its lifecycle to the application, closing every pooled connection on shutdown via an fx stop hook.

Functions

This section is empty.

Types

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

Conn is a grpc.ClientConnInterface that resolves its dial target per call through a Resolver and fetches (lazily creating) the underlying pooled connection through a ConnFactory. With a dynamic Resolver a single Conn fronts many physical connections (e.g. one per namespace); with a static Resolver it always resolves to the same one. Construct one with NewConn.

func NewConn

func NewConn(f ConnFactory, r Resolver) (*Conn, error)

NewConn returns a Conn that resolves through r and dials through f. When r is static the pooled connection is created eagerly here, so a malformed target or bad dial option surfaces at construction rather than on the first request; the socket itself is not opened until first use (gRPC connects lazily). A dynamic resolver defers creation to the first call that resolves a given target.

func (*Conn) Invoke

func (c *Conn) Invoke(ctx context.Context, method string, args any, reply any, opts ...grpc.CallOption) error

Invoke resolves the connection for this call and forwards the unary RPC to it, satisfying grpc.ClientConnInterface.

func (*Conn) NewStream

func (c *Conn) NewStream(
	ctx context.Context,
	desc *grpc.StreamDesc,
	method string,
	opts ...grpc.CallOption,
) (grpc.ClientStream, error)

NewStream resolves the connection for this call and opens the stream on it, satisfying grpc.ClientConnInterface. The target is resolved from ctx before any message is sent, so streaming and unary calls share one resolution path.

type ConnFactory

type ConnFactory func(string, string, ...grpc.DialOption) (*grpc.ClientConn, error)

ConnFactory returns the pooled connection for a (key, target) pair, creating it on first use. Pool.ConnOrCreate satisfies this signature: the first argument is the logical cache key and the second is the dial address.

type Pool

type Pool struct {
	// contains filtered or unexported fields
}

Pool is a concurrency-safe set of gRPC client connections keyed by a caller-supplied logical key, which is distinct from the dial target. Callers that need two connections to the same dial target (e.g. the same host:port with different TLS server names) must use different keys, or they will collapse onto whichever connection was dialed first. The zero value is not usable; create one with NewPool.

func NewPool

func NewPool() *Pool

NewPool returns an empty Pool ready for use.

func (*Pool) Close

func (p *Pool) Close() error

Close shuts down every connection in the pool, joining any errors. It runs at most once; subsequent calls return the same result without re-closing.

func (*Pool) Conn

func (p *Pool) Conn(key string) (*grpc.ClientConn, error)

Conn returns the connection registered for key. It returns ErrKeyNotFound if no connection is registered for that key.

func (*Pool) ConnOrCreate

func (p *Pool) ConnOrCreate(key, target string, opts ...grpc.DialOption) (*grpc.ClientConn, error)

ConnOrCreate returns the connection registered for key, creating and registering one with grpc.NewClient(target, opts...) when none exists yet. key is the logical cache key and target is the dial address; callers that need distinct connections to the same target (e.g. identical host:port with different TLS server names) must pass distinct keys. If callers race to create the same key, each constructs a client but only one connection is kept; the losers are closed and every caller receives the same *grpc.ClientConn.

func (*Pool) Set

func (p *Pool) Set(key string, conn *grpc.ClientConn) error

Set registers conn for key. It returns ErrDuplicateKey if a connection is already registered for that key, leaving the existing connection untouched.

type Resolver

type Resolver interface {
	IsStatic() bool
	Resolve(context.Context) (string, string, []grpc.DialOption, error)
}

Resolver decides, per request, which connection a Conn should use. Resolve returns the pool cache key, the dial target, and the dial options for that connection. IsStatic reports whether the resolution is fixed for the life of the Conn: a static resolver is dialed eagerly when the Conn is created; a dynamic one is resolved lazily on every call.

func StaticResolver

func StaticResolver(hostPort string, opts ...grpc.DialOption) Resolver

StaticResolver returns a Resolver that always resolves to hostPort with the given dial options. It reports IsStatic as true, so a Conn built from it is created eagerly and reuses a single pooled connection keyed by hostPort.

Jump to

Keyboard shortcuts

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