Documentation
¶
Overview ¶
Package protoutil provides helpers for working with Temporal's protobuf request types at the gRPC boundary, without the caller needing to know the concrete message type for a given method.
Extractor reads the namespace from an encoded request by resolving its message type from a descriptor registry and a type registry.
Translator rewrites namespace names inside decoded messages, driven by a direction function, using a per-message-type plan cache that WarmService pre-populates. The package is free of any gRPC dependency; callers apply a Translator on a connection themselves.
Module wires both an Extractor and a Translator into an fx application, defaulting the descriptor and type registries to google.golang.org/protobuf/reflect/protoregistry.GlobalFiles and google.golang.org/protobuf/reflect/protoregistry.GlobalTypes when they are not supplied, and warming the translator for the services the application lists in ExtractorParams.TranslatorServices.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var Module = fx.Options( fx.Provide( func(p ExtractorParams) *Translator { return NewTranslator(filesOrGlobal(p.Files)) }, func(p ExtractorParams) *Extractor { return NewExtractor(filesOrGlobal(p.Files), typesOrGlobal(p.Types)) }, ), fx.Invoke(func(t *Translator, p ExtractorParams) error { for _, svc := range p.TranslatorServices { if err := t.WarmService(svc); err != nil { return fmt.Errorf("failed to set up translations for %s: %w", svc, err) } } return nil }), )
Module provides an *Extractor and a *Translator, and warms the translator's plan cache for every service in TranslatorServices at startup. Files and Types default to the global protobuf registries when the application supplies neither. TranslatorServices is optional: when empty, no plans are pre-populated and the translator builds them lazily on first use.
Functions ¶
This section is empty.
Types ¶
type Extractor ¶
type Extractor struct {
// contains filtered or unexported fields
}
Extractor reads the namespace from an encoded gRPC request. It resolves the concrete request message type for a full method name from the descriptor and type registries it was given, decodes the payload into it, and reads the namespace via the generated accessor. Resolved types are cached per method, so repeat calls for the same method skip the lookup. Construct one with NewExtractor; an Extractor is safe for concurrent use.
func NewExtractor ¶
NewExtractor returns an Extractor that resolves request types using files and types. Production callers pass protoregistry.GlobalFiles and protoregistry.GlobalTypes; tests may pass fakes. Resolution only succeeds for message types registered in the given registries, so the relevant service packages (e.g. go.temporal.io/api/workflowservice/v1) must be imported into the binary.
type ExtractorParams ¶
type ExtractorParams struct {
fx.In
Files Files `optional:"true"`
Types Types `optional:"true"`
TranslatorServices []protoreflect.FullName `optional:"true"`
}
ExtractorParams collects the dependencies used to build the *Extractor and the Translator. Files and Types are optional: when absent, Module falls back to the global protobuf registries. TranslatorServices is optional and lists the gRPC services whose request and response types are pre-warmed at startup.
type Files ¶
type Files interface {
FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error)
}
Files resolves a descriptor by its fully qualified name. *protoregistry.Files, and in particular protoregistry.GlobalFiles, implements it.
type Translator ¶
type Translator struct {
// contains filtered or unexported fields
}
Translator rewrites namespace names inside decoded protobuf messages. It caches a translation plan per message type, so repeat translations of the same type skip descriptor traversal. Plans may be pre-populated with WarmService or built lazily on first use. A Translator is safe for concurrent use.
func NewTranslator ¶
func NewTranslator(files Files) *Translator
NewTranslator returns a Translator that resolves service descriptors for warming through files. Production callers pass protoregistry.GlobalFiles.
func (*Translator) IsWarm ¶
func (t *Translator) IsWarm(name protoreflect.FullName) bool
IsWarm reports whether a plan for the named message type is already cached.
func (*Translator) Translate ¶
func (t *Translator) Translate(m proto.Message, fn func(string) string)
Translate rewrites every namespace name in m using fn. It is a no-op when m is nil, invalid, or carries no namespace field. fn maps a namespace name to its translated form (local to remote, or remote to local).
func (*Translator) WarmService ¶
func (t *Translator) WarmService(name protoreflect.FullName) error
WarmService pre-computes and caches the plan for every method input and output type of the named gRPC service, so no request pays first-touch plan construction. It fails when the name does not resolve to a service.
type Types ¶
type Types interface {
FindMessageByName(protoreflect.FullName) (protoreflect.MessageType, error)
}
Types resolves a message type by its fully qualified name. *protoregistry.Types, and in particular protoregistry.GlobalTypes, implements it.