Documentation
¶
Overview ¶
Package weaver provides the interface for building single-image distributed programs.
A program is composed of a set of Go interfaces called components. Components are recognized by "weaver generate" (typically invoked via "go generate"). "weaver generate" generates code that allows a component to be invoked over the network. This flexibility allows Service Weaver to decompose the program execution across many processes and machines.
Index ¶
- Variables
- func Get(requester Instance) (T, error)
- func InstrumentHandler(label string, handler http.Handler) http.Handler
- func InstrumentHandlerFunc(label string, f func(http.ResponseWriter, *http.Request)) http.Handler
- type AutoMarshal
- type Implements
- type Instance
- type Listener
- type ListenerOptions
- type Logger
- type WithConfig
- type WithRouter
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrRetriable = errors.New("retriable")
ErrRetriable indicates a component method call failed but may succeed if retried. You can use ErrRetriable in conjunction with errors.Is to detect and retry failed operations. For example:
// Retry the foo.Foo call up to three times. var err error for i := 0; i < 3; i++ { err = foo.Foo(ctx) if errors.Is(err, weaver.ErrRetriable) { time.Sleep(delay) // Backoff continue } break }
Functions ¶
func Get ¶
Get returns the distributed component of type T, creating it if necessary. The actual implementation may be local, or in another process, or perhaps even replicated across many processes. requester represents the component that is fetching the component of type T. For example:
func main() { root := weaver.Init(context.Background()) foo := weaver.Get[Foo](root) // Get the Foo component. // ... }
Components are constructed the first time you call Get. Constructing a component can sometimes be expensive. When deploying a Service Weaver application on the cloud, for example, constructing a component may involve launching a container. For this reason, we recommend you call Get proactively to incur this overhead at initialization time rather than on the critical path of serving a client request.
func InstrumentHandler ¶
InstrumentHandler instruments the provided HTTP handler to maintain the following metrics about HTTP request execution. Every metric is labelled with the supplied label.
- serviceweaver_http_request_count: Total number of requests.
- serviceweaver_http_error_count: Total number of 4XX and 5XX replies.
- serviceweaver_http_request_latency_micros: Execution latency in microseconds.
Example ¶
package main import ( "net/http" "github.com/ServiceWeaver/weaver" ) func main() { var mux http.ServeMux mux.Handle("/foo", weaver.InstrumentHandler("foo", http.HandlerFunc(func(http.ResponseWriter, *http.Request) { /*...*/ }))) mux.Handle("/bar", weaver.InstrumentHandler("bar", http.HandlerFunc(func(http.ResponseWriter, *http.Request) { /*...*/ }))) http.ListenAndServe(":9000", &mux) }
Output:
func InstrumentHandlerFunc ¶
InstrumentHandlerFunc is identical to InstrumentHandler but takes a function instead of an http.Handler.
Types ¶
type AutoMarshal ¶
type AutoMarshal struct{}
AutoMarshal is a type that can be embedded within a struct to indicate that "weaver generate" should generate serialization methods for the struct.
Named struct types are not serializable by default. However, they can trivially be made serializable by embedding AutoMarshal. For example:
type Pair struct { weaver.AutoMarshal x, y int }
The AutoMarshal embedding instructs "weaver generate" to generate serialization methods for the struct, Pair in this example.
Note, however, that AutoMarshal cannot magically make any type serializable. For example, "weaver generate" will raise an error for the following code because the NotSerializable struct is fundamentally not serializable.
// ERROR: NotSerializable cannot be made serializable. type NotSerializable struct { weaver.AutoMarshal f func() // functions are not serializable c chan int // chans are not serializable }
func (AutoMarshal) WeaverMarshal ¶
func (AutoMarshal) WeaverMarshal(enc *codegen.Encoder)
func (AutoMarshal) WeaverUnmarshal ¶
func (AutoMarshal) WeaverUnmarshal(dec *codegen.Decoder)
type Implements ¶
type Implements[T any] struct { // contains filtered or unexported fields }
Implements[T] is a type that can be embedded inside a component implementation struct to indicate that the struct implements a component of type T. E.g., consider a Cache component.
type Cache interface { Get(ctx context.Context, key string) (string, error) Put(ctx context.Context, key, value string) error }
A concrete type that implements the Cache component will be marked as follows:
type lruCache struct { weaver.Implements[Cache] ... }
Implements is embedded inside the component implementation, and therefore methods of Implements (as well as methods of weaver.Instance) are available as methods of the implementation type and can be invokded directly on an implementation type instance.
type Instance ¶
type Instance interface { // Logger returns a logger that associates its log entries with this component. Logger() Logger // Listener returns a network listener with the given name that is suitable // for hosting an HTTP server. // // Name may be used by the Service Weaver framework to route client traffic to the // corresponding network listener. As such, listener names should follow the // DNS format for names. // // HTTP servers constructed using this listener are expected to perform health // checks on the reserved "/healthz" URL prefix. (Note that this URL prefix // is configured to never receive any user traffic.) // // If different processes in an application call Listener() multiple times // with the same listener name but different options, the options value from // one of those calls will be used when constructing the listener. // // TODO(mwhittaker): Return the address of the proxy somehow. Right now, if a // user specifies a LocalAddress like ":0", they don't have a way to know what // address the proxy is listening on. Listener(name string, options ListenerOptions) (*Listener, error) // contains filtered or unexported methods }
Instance is the interface implemented by all component implementations (by virtue of weaver.Implements being embedded inside the component implementation). An Instance for a particular component only exists in processes that are hosting that component.
func Init ¶
Init initializes the execution of a process involved in a Service Weaver application.
Components in a Service Weaver application are executed in a set of processes, potentially spread across many machines. Each process executes the same binary and must call weaver.Init. If this process is hosting the "main" component, Init will return a handle to the main component implementation for this process.
If this process is not hosting the "main" component, Init will never return and will just serve requests directed at the components being hosted inside the process.
type Listener ¶
type Listener struct { net.Listener // underlying listener // contains filtered or unexported fields }
A Listener is Service Weaver's implementation of a net.Listener.
A Listener implements the net.Listener interface, so you can use a Listener wherever you use a net.Listener. For example,
func main() { root := weaver.Init(context.Background()) lis, err := root.Listener("hello", weaver.ListenerOptions{}) if err != nil { log.Fatal(err) } root.Logger().Info("Listener available at %v", lis) http.HandleFunc("/a", func(http.ResponseWriter, *http.Request) {...}) http.HandleFunc("/b", func(http.ResponseWriter, *http.Request) {...}) http.HandleFunc("/c", func(http.ResponseWriter, *http.Request) {...}) http.Serve(lis, nil) }
type ListenerOptions ¶
type ListenerOptions struct { // LocalAddress will be used as the address where the listener is // created for local executions (i.e., for single, multi, and weavertest // deployments). // // The value must have the form :port or host:port, or it may // be the empty string, which is treated as ":0". // // If the port number is zero, an unused port number is picked. // // If the host portion is missing, the listener is bound to all // available addresses. // // Examples: // // "" System picked port on all available addresses // :0 System picked port on all available addresses // :1234 Port 1234 on all available addresses // localhost:1234 Port 1234 on loopback address // example.com:1234 Port 1234 on external addresses for host LocalAddress string // contains filtered or unexported fields }
ListenerOptions specifies optional configuration for a listener.
type Logger ¶
type Logger interface { // Debug logs an entry for debugging purposes that contains msg and attributes. Debug(msg string, attributes ...any) // Info logs an informational entry that contains msg and attributes. Info(msg string, attributes ...any) // Error logs an error entry that contains msg and attributes. // If err is not nil, it will be used as the value of a attribute // named "err". Error(msg string, err error, attributes ...any) // With returns a logger that will automatically add the // pre-specified attributes to all logged entries. With(attributes ...any) Logger }
Logger can be used to log messages at different levels (Debug, Info, Error). It can safely be used concurrently from multiple goroutines.
A Service Weaver component implementation can get a logger for the component by calling the Logger() method on itself. Log messages written to such a logger will be automatically augmented with the component identity and location.
func (f *foo) SomeMethod() { logger := Logger() logger.Debug("This is a debug log!") logger.Info("This is an info log!") logger.Error("This is an error log!", io.EOF) return &foo{logger: logger}, nil }
You can also get a Logger from the root component returned by weaver.Init.
func main() { root := weaver.Init(context.Background()) logger := root.Logger() logger.Info("main started", "pid", os.Getpid()) // ... }
Attributes ¶
Loggers methods can be passed a list of key value pair attributes as trailing arguments. These attributes can be used for identifying and filtering log entries.
An attribute is formed by two consecutive items in the attribute list, where the first item is a string containing the attribute name, and the second item is a value that can be converted to a string. If the preceding expectations are not met, the logged message will contain appropriate error markers.
Examples:
var c weaver.Instance = ... logger := c.Logger() // No attributes added logger.Debug("hello") // Attributes added: {"host":"example.com", "port":12345} logger.Info("ready", "host", "example.com", "port", 12345)
Pre-attached attributes ¶
If the same attributes will be used repeatedly, a logger can be created with those attributes pre-attached.
hostPortLogger := logger.With("host", "example.com", "port", 12345) // Attributes added: {"host":"example.com", "port":12345, "method": "Put"} hostPortLogger.Info("call", "method", "Put") // Attributes added: {"host":"example.com", "port":12345, "method": "Get"} hostPortLogger.Info("call", "method", "Get")
type WithConfig ¶
type WithConfig[T any] struct { // contains filtered or unexported fields }
WithConfig[T] is a type that can be embedded inside a component implementation. Service Weaver runtime will take per-component configuration information found in the application config file and use it to initialize the contents of T.
For example: consider a cache component where the cache size should be configurable. Define a struct that includes the size, associate it with the component implementation, and use it inside the component methods.
type cacheConfig struct Size int } type cache struct { weaver.Implements[...] weaver.WithConfig[cacheConfig] .. } func (c *cache) Init(context.Context) error { ... use c.Config.Size ... return nil }
The application config file can specify these values as keys under the full component path.
["example.com/mypkg/MyComponent"] Size = 1000
func (*WithConfig[T]) Config ¶
func (wc *WithConfig[T]) Config() *T
Config returns the configuration information for the component that embeds this weaver.WithConfig.
Any fields in T that were not present in the application config file will have their default values.
Any fields in the application config file that are not present in T will be flagged as an error at application startup.
type WithRouter ¶
type WithRouter[T any] struct{}
WithRouter[T] is a type that can be embedded inside a component implementation struct to indicate that calls to a method M on the component must be routed according to the the value returned by T.M().
An Example ¶
For example, consider a Cache component that maintains an in-memory cache.
type Cache interface { Get(ctx context.Context, key string) (string, error) Put(ctx context.Context, key, value string) error }
We can create a router for the Cache component like this.
type cacheRouter struct{} func (cacheRouter) Get(_ context.Context, key string) string { return key } func (cacheRouter) Put(_ context.Context, key, value string) string { return key }
To associate a router with its component, embed weaver.WithRouter in the component implementation.
type lruCache struct { weaver.Implements[Cache] weaver.WithRouter[cacheRouter] }
For every component method that needs to be routed (e.g., Get and Put), the associated router should implement an equivalent method (i.e., same name and argument types) whose return type is the routing key. When a component's routed method is invoked, its corresponding router method is invoked to produce a routing key. Method invocations that produce the same key are routed to the same replica.
Routing Keys ¶
A routing key can be any integer (e.g., int, int32), float (i.e. float32, float64), or string; or a struct where every field is an integer, float, or string (e.g., struct{x int; y string}). Every router method must return the same routing key type. The following, for example, is invalid:
// ERROR: Get returns a string, but Put returns an int. func (cacheRouter) Get(_ context.Context, key string) string { return key } func (cacheRouter) Put(_ context.Context, key, value string) int { return 42 }
Semantics ¶
NOTE that routing is done on a best-effort basis. Service Weaver will try to route method invocations with the same key to the same replica, but this is not guaranteed. As a corollary, you should never depend on routing for correctness. Only use routing to increase performance in the common case.
Source Files
¶
Directories
¶
Path | Synopsis |
---|---|
cmd
|
|
weaver
Weaver deploys and manages Weaver applications.
|
Weaver deploys and manages Weaver applications. |
dev
|
|
docgen
docgen generates a static web site from markdown and other files.
|
docgen generates a static web site from markdown and other files. |
examples
|
|
collatz
Package main implements a service that explores the Collatz conjecture.
|
Package main implements a service that explores the Collatz conjecture. |
factors
Package main implements a service to compute the factors of an integer.
|
Package main implements a service to compute the factors of an integer. |
onlineboutique
Package main implements a demo shopping application called Online Boutique.
|
Package main implements a demo shopping application called Online Boutique. |
onlineboutique/types
Package types stores common types shared between services.
|
Package types stores common types shared between services. |
Package runtime contains code suitable for deployer implementers but not Service Weaver application developers.
|
Package runtime contains code suitable for deployer implementers but not Service Weaver application developers. |
codegen
Package codegen contains functions and types used by the weaver_gen.go files generated by "weaver generate".
|
Package codegen contains functions and types used by the weaver_gen.go files generated by "weaver generate". |
colors
Package colors contains color-related utilities.
|
Package colors contains color-related utilities. |
envelope
Package envelope implements a sidecar-like process that connects a weavelet to its environment.
|
Package envelope implements a sidecar-like process that connects a weavelet to its environment. |
logging
Package logging contains logging related utilities.
|
Package logging contains logging related utilities. |
metrics
Package metrics implements Service Weaver metrics.
|
Package metrics implements Service Weaver metrics. |
perfetto
Package perfetto contains libraries for displaying trace information in the Perfetto UI.
|
Package perfetto contains libraries for displaying trace information in the Perfetto UI. |
protomsg
Package protomsg contains protobuf-related utilities.
|
Package protomsg contains protobuf-related utilities. |
retry
Package retry contains code to perform retries with exponential backoff.
|
Package retry contains code to perform retries with exponential backoff. |
tool
Package tool contains utilities for creating Service Weaver tools similar to weaver-multi, weaver-gke, and weaver-gke-local.
|
Package tool contains utilities for creating Service Weaver tools similar to weaver-multi, weaver-gke, and weaver-gke-local. |
Package weavertest provides a way to test Service Weaver components.
|
Package weavertest provides a way to test Service Weaver components. |
internal
|
|
cond
Package cond implements a context-aware condition variable.
|
Package cond implements a context-aware condition variable. |
env
Package env implements helper functions for dealing with environment variables.
|
Package env implements helper functions for dealing with environment variables. |
envelope/conn
Package conn implements a bi-directional communication channel between an envelope and a weavelet.
|
Package conn implements a bi-directional communication channel between an envelope and a weavelet. |
files
Package files contains file-related utilities.
|
Package files contains file-related utilities. |
heap
Package heap provide a min-heap implementation called Heap.
|
Package heap provide a min-heap implementation called Heap. |
net/call
Package call implements an RPC mechanism.
|
Package call implements an RPC mechanism. |
pipe
Package pipe extends os.exec, making it easier to create pipes to subcommands.
|
Package pipe extends os.exec, making it easier to create pipes to subcommands. |
status
Package status contains code for implementing status related commands like "weaver multi status" and "weaver single dashboard".
|
Package status contains code for implementing status related commands like "weaver multi status" and "weaver single dashboard". |