Documentation
¶
Overview ¶
Package temporal provides reusable helpers for building applications with the Temporal Go SDK.
The helpers cover the parts of a Temporal service that tend to be rewritten every time: client connection and TLS configuration, authentication, Cobra and Viper flag wiring, health and readiness endpoints, Prometheus metrics, Zerolog integration and saga compensation.
It is a thin convenience layer, not a framework or an abstraction over Temporal. A connection is described by a list of Option values and produces an ordinary Temporal client, and the logging and metrics helpers remain directly compatible with the SDK's logger and metrics handler interfaces, so the SDK stays directly usable alongside anything here.
Start at NewConnection for the connection options, NewCobraOpts for CLI integration, NewHealthCheck for health endpoints, NewPrometheusHandler for metrics and Compensator for saga compensation.
Index ¶
- func NewConnection(options ...Option) (client.Client, error)
- func NewConnectionWithEnvvars(options ...Option) (client.Client, error)
- func NewHealthCheck(ctx context.Context, taskQueues []string, address string, c client.Client) error
- func NewZerologHandler(zlog *zerolog.Logger) log.Logger
- type Compensator
- type ExternalConfig
- type ExternalConfigFactory
- type Option
- func ParseCobraOpts(opts *TemporalOpts, overrides ...Option) []Option
- func WithAPICredentials(apiKey string) Option
- func WithAuthDetection(apiKey, certPath, certKey string) Option
- func WithConnectionOptions(connection *client.ConnectionOptions) Option
- func WithContextPropagators(propagators []workflow.ContextPropagator) Option
- func WithCredentials(credential client.Credentials) Option
- func WithDataAndFailureConverter(cvt converter.DataConverter) Option
- func WithDataConverter(cvt converter.DataConverter) Option
- func WithExternalStorage(st converter.ExternalStorage) Option
- func WithExternalStorageFactory(e ExternalConfig) Option
- func WithFailureConverter(cvt converter.DataConverter) Option
- func WithHostPort(hostPort string) Option
- func WithInterceptors(interceptors []interceptor.ClientInterceptor) Option
- func WithLogger(logger log.Logger) Option
- func WithMTLS(certPath, certKey string) Option
- func WithMetrics(metrics client.MetricsHandler) Option
- func WithNamespace(namespace string) Option
- func WithNoOp() Option
- func WithPrometheusMetrics(listenAddress, prefix string, registry *prom.Registry, onError ...func(error)) Option
- func WithTLS(enabled bool, tlsOpts ...TLSOption) Option
- func WithZerolog(logger *zerolog.Logger) Option
- type PrometheusHandler
- type S3Config
- type TLSOption
- type TemporalOpts
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewConnection ¶
NewConnection creates a Temporal connection from the supplied options only, starting from a zero-valued client.Options. Anything an option does not set keeps the SDK's own default.
func NewConnectionWithEnvvars ¶
NewConnectionWithEnvvars creates a Temporal connection using the Temporal SDK environment configuration as its starting point, then applies options on top, so an option always wins over the environment.
This is experimental.
@link https://docs.temporal.io/develop/environment-configuration#sdk-usage-example-go
func NewHealthCheck ¶
func NewHealthCheck(ctx context.Context, taskQueues []string, address string, c client.Client) error
NewHealthCheck starts an HTTP health server for a Temporal worker and returns once it is listening.
Three endpoints are served on address:
- /livez reports whether the Temporal service is reachable.
- /readyz reports Temporal reachability and additionally describes the workflow and activity task queues named in taskQueues.
- /health is an alias of /readyz.
A healthy check responds 200 and an unhealthy one 503, both with a JSON body describing what was checked. Each request gets its own two second timeout.
The listener is created synchronously, so an address that cannot be bound is returned as an error and nothing is started. The server then runs in the background and shuts down when ctx is cancelled. Errors from the running server, and from that shutdown, are logged rather than returned, so they are not observable through the returned error.
func NewZerologHandler ¶
NewZerologHandler adapts a Zerolog logger to the Temporal SDK's logger interface, so client and worker logs join the application's own output. Levels and structured key/value pairs are passed through, and the level configured on zlog still applies.
See WithZerolog to use the result as a client logger.
Types ¶
type Compensator ¶
type Compensator struct {
// contains filtered or unexported fields
}
Compensator is a LIFO stack of compensation functions for the saga pattern.
Usage pattern:
- Declare a Compensator at the top of the workflow function. The zero value is ready to use.
- Defer a block that calls Compensator.Compensate when the workflow is failing.
- After each forward step succeeds, call Compensator.Add to register its undo.
- If the workflow fails or is cancelled, the deferred block calls Compensate with the original workflow context, and the registered functions run in reverse order.
Compensate derives its own disconnected context, so callers never need workflow.NewDisconnectedContext themselves.
func (*Compensator) Add ¶
func (c *Compensator) Add(fn func(workflow.Context) error)
Add registers a compensation function, undoing the forward step that has just succeeded. Registration order is the order steps succeed in, and Compensator.Compensate calls the functions in reverse.
func (*Compensator) Compensate ¶
func (c *Compensator) Compensate(ctx workflow.Context)
Compensate runs every registered compensation in reverse order.
All of them are attempted even when one fails: a failure is logged through the workflow logger and the next compensation still runs. Nothing is returned, so the original workflow error is not replaced.
Pass the original workflow context. Compensate derives a disconnected context from it, which keeps the parent's configuration but not its cancellation, so compensations still run for a workflow that is being cancelled. That context is cancelled once Compensate returns, so a compensation must complete its work before returning.
type ExternalConfig ¶
type ExternalConfig struct {
Factory ExternalConfigFactory
PayloadSizeThreshold int
StorageDriverSelector converter.StorageDriverSelector
}
type ExternalConfigFactory ¶
type ExternalConfigFactory func() ([]converter.StorageDriver, error)
func ExternalConfigS3Factory ¶
func ExternalConfigS3Factory(ctx context.Context, cfg *S3Config) ExternalConfigFactory
type Option ¶
Option configures a client.Options before the connection is dialled. Options are applied in the order they are given, so a later option overwrites an earlier one that sets the same field.
func ParseCobraOpts ¶
func ParseCobraOpts(opts *TemporalOpts, overrides ...Option) []Option
ParseCobraOpts turns parsed TemporalOpts into the connection options for NewConnection: host and port, namespace, TLS with its server name, and whichever authentication WithAuthDetection selects.
Overrides are appended, so they are applied last and win over the derived options.
The health and metrics listen addresses are not included, because they configure servers rather than the client. Wire those up separately with NewHealthCheck and NewPrometheusHandler, as in the example above.
func WithAPICredentials ¶
WithAPICredentials authenticates with a Temporal API key. An empty apiKey is a no-op, so it leaves any credentials already configured in place.
func WithAuthDetection ¶
WithAuthDetection chooses an authentication method from whichever values are supplied, in precedence order:
- an API key, when apiKey is not empty
- mTLS, when both certPath and certKey are not empty
- otherwise no authentication option is applied, via WithNoOp
Only one method is ever used, and the choice is made when the option is built rather than when it is applied.
func WithConnectionOptions ¶
func WithConnectionOptions(connection *client.ConnectionOptions) Option
WithConnectionOptions replaces the whole of the client's connection options.
TLS is the exception: when connection.TLS is nil, TLS configured by WithTLS is preserved, so the two options compose in either order without silently discarding each other's settings. Set connection.TLS to override that deliberately.
func WithContextPropagators ¶ added in v0.1.1
func WithContextPropagators(propagators []workflow.ContextPropagator) Option
WithContextPropagators sets the context propagators used to carry values between the client, workflows and activities, for example a trace or tenant identifier held in the caller's context.Context.
The whole set is replaced rather than added to, so a later call overwrites an earlier one; pass every propagator in a single call. A nil or empty slice leaves no propagators configured.
Propagators run in the order they are given, and the same set must be given to every client and worker that takes part, otherwise a value injected at one end is not extracted at the other.
func WithCredentials ¶
func WithCredentials(credential client.Credentials) Option
WithCredentials sets the credentials used to authenticate with Temporal. WithAPICredentials, WithMTLS and WithAuthDetection are usually more convenient.
func WithDataAndFailureConverter ¶
func WithDataAndFailureConverter(cvt converter.DataConverter) Option
WithDataAndFailureConverter applies cvt as both the data converter and, via WithFailureConverter, the failure converter. This is normally what an encrypting or compressing converter wants, so that failure detail is covered as well as payloads.
func WithDataConverter ¶
func WithDataConverter(cvt converter.DataConverter) Option
WithDataConverter sets the converter used for workflow and activity payloads. It does not affect failures; see WithDataAndFailureConverter.
func WithExternalStorage ¶
func WithExternalStorage(st converter.ExternalStorage) Option
WithExternalStorage sets the external storage used for payloads too large to send to the Temporal server inline.
func WithExternalStorageFactory ¶
func WithExternalStorageFactory(e ExternalConfig) Option
WithExternalStorageFactory sets the external storage from an ExternalConfig by invoking e.Factory and handing the drivers it returns to WithExternalStorage, together with e.StorageDriverSelector and e.PayloadSizeThreshold.
The factory runs when the option is applied rather than when it is built, so building an option never talks to the storage backend. An ExternalConfig without a Factory is an error, and so is a factory that fails; a failing factory's error is wrapped rather than returned as it is, so the cause is still reachable with errors.Is and errors.As.
func WithFailureConverter ¶
func WithFailureConverter(cvt converter.DataConverter) Option
WithFailureConverter sets a failure converter that encodes failures with cvt. Common failure attributes, such as the message and stack trace, are encoded too, so a converter that encrypts payloads also covers failure detail.
func WithHostPort ¶
WithHostPort sets the address of the Temporal frontend. An empty hostPort falls back to the SDK default of client.DefaultHostPort.
func WithInterceptors ¶ added in v0.1.1
func WithInterceptors(interceptors []interceptor.ClientInterceptor) Option
WithInterceptors sets the interceptors applied to client calls, such as starting a workflow or sending a signal.
Earlier interceptors wrap later ones, so the first one given is the outermost. The whole set is replaced rather than added to, so a later call overwrites an earlier one; pass every interceptor in a single call. A nil or empty slice leaves no interceptors configured.
An interceptor that also implements interceptor.WorkerInterceptor is used for worker interception as well, wrapping any interceptor set in the worker's own options. The same interceptor should not be given in both places.
func WithLogger ¶
WithLogger sets the logger used by the client, and by any worker created from it. Use WithZerolog to pass an existing Zerolog logger.
func WithMTLS ¶
WithMTLS authenticates with an mTLS client certificate, loading the key pair from disk when the option is applied. A pair that cannot be loaded, or whose key does not match its certificate, is reported as an error from the connection constructor.
The SDK applies the certificate to the connection's TLS configuration when the client is dialled, creating one if none is set, so TLS is in use without also calling WithTLS. Use WithTLS when the TLS configuration itself needs customising, for example with WithTLSServerName.
func WithMetrics ¶
func WithMetrics(metrics client.MetricsHandler) Option
WithMetrics sets the client's metrics handler. Pass the handler returned by NewPrometheusHandler when the caller needs to close it; WithPrometheusMetrics is the shorter option when it does not.
func WithNamespace ¶
WithNamespace sets the Temporal namespace. An empty namespace falls back to the SDK default of client.DefaultNamespace.
func WithNoOp ¶
func WithNoOp() Option
WithNoOp does nothing. It is useful where an Option has to be returned but there is nothing to configure, as WithAuthDetection does when no credentials are supplied.
func WithPrometheusMetrics ¶
func WithPrometheusMetrics(listenAddress, prefix string, registry *prom.Registry, onError ...func(error)) Option
WithPrometheusMetrics
Convenience helper that creates a Prometheus metrics handler and attaches it to the client options in a single call.
By design, this does not expose the closer, so the metrics handler cannot be shut down by the caller - that is the trade-off for the shorter call site. If you need lifecycle control, create the handler yourself with NewPrometheusHandler, defer its Close method, and pass it to WithMetrics:
metrics, err := temporal.NewPrometheusHandler(
opts.temporal.MetricsListenAddress,
opts.temporal.MetricsPrefix,
nil,
)
if err != nil {
return err
}
defer metrics.Close()
c, err := temporal.NewConnection(
temporal.WithMetrics(metrics),
)
func WithTLS ¶
WithTLS enables TLS and builds the connection's tls.Config from tlsOpts.
When enabled is false the option is a no-op: it does not clear TLS configuration set elsewhere, so a disabled flag cannot accidentally undo mTLS credentials or WithConnectionOptions.
func WithZerolog ¶
WithZerolog uses an existing Zerolog logger as the client logger. It is shorthand for WithLogger with NewZerologHandler.
type PrometheusHandler ¶
type PrometheusHandler struct {
client.MetricsHandler
// contains filtered or unexported fields
}
PrometheusHandler is a Temporal metrics handler backed by a Prometheus reporter.
It embeds the SDK's metrics handler interface, so it can be passed straight to WithMetrics, and it owns the underlying Tally scope. The caller owns the handler, and is responsible for calling PrometheusHandler.Close.
func NewPrometheusHandler ¶
func NewPrometheusHandler( listenAddress, prefix string, registry *prom.Registry, onError ...func(error), ) (*PrometheusHandler, error)
NewPrometheusHandler creates a Prometheus-backed metrics handler for a Temporal client. The caller owns it and should call PrometheusHandler.Close when it is no longer needed, usually with defer.
Metrics are served on listenAddress under /metrics, with prefix prepended to every metric name. An empty listenAddress attaches the metrics endpoint to Go's default HTTP mux instead of starting a server of its own. A nil registry uses the Prometheus default registry. Timers are reported as histograms.
The optional onError argument decides how the reporter reports its own failures:
- not supplied: failures are logged at fatal level, terminating the process
- one function: that function is called with the error
- explicitly nil: nil is passed through to Tally, so Tally's own default behaviour applies
- more than one: an error is returned and no handler is created
Reporter failures are not returned from here. A listen address that cannot be bound, for example, is reported asynchronously through onError once the reporter is running.
func (*PrometheusHandler) Close ¶
func (h *PrometheusHandler) Close() error
Close flushes and releases the underlying Tally scope, and reports whatever the scope reports. A handler with no scope to release, such as the zero value, closes without error.
type TLSOption ¶
TLSOption configures the tls.Config built by WithTLS. TLS options are applied in order, and only when TLS is enabled.
func WithTLSServerName ¶
WithTLSServerName overrides the TLS server name (SNI) used to validate the server certificate. It is needed when the endpoint address does not match the certificate hostname, for example behind AWS PrivateLink. An empty serverName is a no-op.
type TemporalOpts ¶
type TemporalOpts struct {
Address string
APIKey string
HealthListenAddress string
MetricsListenAddress string
MetricsPrefix string
MTLSCertPath string
MTLSKeyPath string
Namespace string
ServerName string
TLSEnabled bool
}
TemporalOpts holds the values behind the flags registered by NewCobraOpts. Declare one, or embed it in a command's own options struct, and pass a pointer to NewCobraOpts.
func NewCobraOpts ¶
func NewCobraOpts(cmd *cobra.Command, opts *TemporalOpts) *TemporalOpts
NewCobraOpts registers the Temporal flags on cmd, binding each one to a field of opts, and returns opts for convenience.
Every flag takes its default from Viper, so a value can equally come from a config file or the environment. The keys are health_listen_address, metrics_listen_address, metrics_prefix, temporal_address, temporal_api_key, temporal_tls_client_cert_path, temporal_tls_client_key_path, temporal_namespace, temporal_server_name and temporal_tls. The two listen addresses, the address and the namespace have defaults; the rest default to empty.
The API key's default is hidden from the help output, so a key already in the configuration is not printed to the terminal.