weaver

package module
v0.15.0 Latest Latest
Warning

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

Go to latest
Published: Jun 14, 2023 License: Apache-2.0 Imports: 54 Imported by: 127

README

Service Weaver Go Reference

Service Weaver is a programming framework for writing, deploying, and managing distributed applications. You can run, test, and debug a Service Weaver application locally on your machine, and then deploy it to the cloud with a single command.

$ go run .                      # Run locally.
$ weaver gke deploy weaver.toml # Run in the cloud.

Visit https://serviceweaver.dev to learn more about Service Weaver.

Installation and Getting Started

Visit https://serviceweaver.dev/docs.html for installation instructions and information on getting started.

Contributing

Please read our contribution guide for details on how to contribute.

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

Examples

Constants

View Source
const (
	// HealthzURL is the URL path on which Service Weaver performs health
	// checks. Every application HTTP server must register a handler for this
	// URL path, e.g.:
	//
	//   mux := http.NewServeMux()
	//   mux.HandleFunc(weaver.HealthzURL, func(http.ResponseWriter, *http.Request) {
	//	   ...
	//   })
	//
	// As a convenience, Service Weaver registers HealthzHandler under
	// this URL path in the default ServerMux, i.e.:
	//
	//  http.HandleFunc(weaver.HealthzURL, weaver.HealthzHandler)
	HealthzURL = "/debug/weaver/healthz"
)

Variables

View Source
var (
	// RemoteCallError indicates that a remote component method call failed to
	// execute properly. This can happen, for example, because of a failed
	// machine or a network partition. Here's an illustrative example:
	//
	//	// Call the foo.Foo method.
	//	err := foo.Foo(ctx)
	//	if errors.Is(err, weaver.RemoteCallError) {
	//	    // foo.Foo did not execute properly.
	//	} else if err != nil {
	//	    // foo.Foo executed properly, but returned an error.
	//	} else {
	//	    // foo.Foo executed properly and did not return an error.
	//	}
	//
	// Note that if a method call returns an error with an embedded
	// RemoteCallError, it does NOT mean that the method never executed. The
	// method may have executed partially or fully. Thus, you must be careful
	// retrying method calls that result in a RemoteCallError. Ensuring that all
	// methods are either read-only or idempotent is one way to ensure safe
	// retries, for example.
	RemoteCallError = errors.New("Service Weaver remote call error")

	// HealthzHandler is a health-check handler that returns an OK status for
	// all incoming HTTP requests.
	HealthzHandler = func(w http.ResponseWriter, _ *http.Request) {
		fmt.Fprintf(w, "OK")
	}
)

Functions

func InstrumentHandler

func InstrumentHandler(label string, handler http.Handler) http.Handler

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

func InstrumentHandlerFunc(label string, f func(http.ResponseWriter, *http.Request)) http.Handler

InstrumentHandlerFunc is identical to InstrumentHandler but takes a function instead of an http.Handler.

func Run added in v0.6.0

func Run(ctx context.Context) error

Run runs app as a Service Weaver application.

The application is composed of a set of components that include weaver.Main as well as any components transitively needed by weaver.Main. An instance that implement weaver.Main is automatically created by weaver.Run and its Main method called. Note: other replicas in which weaver.Run is called may also create instances of weaver.Main.

If this process is hosting the `weaver.Main` component, Run will call its Main method and will return when that method returns. If this process is not hosting `weaver.Main`, it will never return. Most callers of Run will not do anything (other than possibly logging any returned error) after Run returns.

func main() {
    if err := weaver.Run(context.Background()); err != nil {
        log.Fatal(err)
    }
}

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(*codegen.Encoder)

func (AutoMarshal) WeaverUnmarshal

func (AutoMarshal) WeaverUnmarshal(*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 invoked directly on an implementation type instance.

func (Implements) Logger

func (c Implements) Logger() *slog.Logger

Logger returns a logger that associates its log entries with this component.

type Instance

type Instance interface {
	// Logger returns a logger that associates its log entries with this component.
	Logger() *slog.Logger
	// 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.

type InstanceOf added in v0.11.0

type InstanceOf[T any] interface {
	Instance
	// contains filtered or unexported methods
}

InstanceOf[T] is the interface implemented by a struct that embeds weaver.Implements[T].

type Listener

type Listener struct {
	net.Listener // underlying listener
	// contains filtered or unexported fields
}

Listener is a network listener that can be placed as a field inside a component implementation struct. Once placed, Service Weaver automatically initializes the Listener and makes it suitable for receiving network traffic. For example:

type myComponentImpl struct {
  weaver.Implements[MyComponent]
  myListener      weaver.Listener
  myOtherListener weaver.Listener
}

By default, all listeners listen on address ":0". This behavior can be modified by passing options for individual listeners in the application config. For example, to specify local addresses for the above two listeners, the user can add the following lines to the application config file:

	[listeners]
 mylistener      = {local_address = "localhost:9000"}
 myotherlistener = {local_address = "localhost:9001"}

Listeners are identified by the lowercased form of their field names in the component implementation structs (e.g., mylistener and myotherlistener). If the user wishes to assign different names to their listeners, they may do so by adding a `weaver:"name"` struct tag to their listener fields, e.g.:

type myComponentImpl struct {
  weaver.Implements[MyComponent]
  myListener      weaver.Listener
  myOtherListener weaver.Listener `weaver:"mylistener2"`
}

Listener names must be unique inside a given application binary, regardless of which components they are specified in. For example, it is illegal to declare a Listener field "foo" in two different component implementation structs, unless one is renamed using the `weaver:"name"` struct tag. Because some deployers may use listener names to route client traffic to the application, listener names should follow a DNS format for names [1] (i.e., include only characters [-.a-zA-Z0-9]).

HTTP servers constructed using this listener are expected to perform health checks on the reserved HealthzURL path. (Note that this URL path is configured to never receive any user traffic.)

[1] https://en.wikipedia.org/wiki/Domain_name

func (*Listener) ProxyAddr

func (l *Listener) ProxyAddr() string

ProxyAddr returns the dialable address of the proxy that forwards traffic to this listener, or returns the empty string if there is no such proxy.

func (Listener) String

func (l Listener) String() string

String returns the address clients should dial to connect to the listener; this will be the proxy address if available, otherwise the <host>:<port> for this listener.

type Main added in v0.6.0

type Main interface {
	// Main contains the application main. It typically loops
	// forever, e.g., inside http.Serve.
	Main(context.Context) error
}

Main is interface implemented by an application's main component. This component is instantiated and its Main() method called by `weaver.Run`.

type Ref added in v0.7.0

type Ref[T any] struct {
	// contains filtered or unexported fields
}

Ref[T] is a field that can be placed inside a component implementation struct. T must be a component type. Service Weaver will automatically fill such a field with a handle to the corresponding component.

func (Ref[T]) Get added in v0.7.0

func (r Ref[T]) Get() T

Get returns a handle to the component of type T.

type RoutedBy added in v0.11.0

type RoutedBy[T any] interface {
	// contains filtered or unexported methods
}

RoutedBy[T] is the interface implemented by a struct that embeds weaver.RoutedBy[T].

type Unrouted added in v0.11.0

type Unrouted interface {
	// contains filtered or unexported methods
}

Unrouted is the interface implemented by instances that don't embed weaver.WithRouter[T].

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.

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.
internal
cond
Package cond implements a context-aware condition variable.
Package cond implements a context-aware condition variable.
config
Package config contains config related utilities.
Package config contains config related utilities.
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.
must
Package must provides a generic Must function.
Package must provides a generic Must function.
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.
private
Package private is an internal holder of state that different Service Weaver packages share without exposing it externally.
Package private is an internal holder of state that different Service Weaver packages share without exposing it externally.
reflection
Package reflection implements helpers for reflection code.
Package reflection implements helpers for reflection code.
register
Package register implements a write-once register.
Package register implements a write-once register.
routing
Package routing includes utilities for routing and assignments.
Package routing includes utilities for routing and assignments.
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".
Package metrics provides an API for counters, gauges, and histograms.
Package metrics provides an API for counters, gauges, and histograms.
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.
bin
bin/testprogram
testprogram is used by bin tests.
testprogram is used by bin tests.
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.
version
Package version contains code related to deployer API versioning.
Package version contains code related to deployer API versioning.
version/testprogram
testprogram is used by version tests.
testprogram is used by version tests.
Package weavertest provides a way to test Service Weaver components.
Package weavertest provides a way to test Service Weaver components.
internal/generate
Package generate tests that "weaver generate"-generated code *executes* correctly.
Package generate tests that "weaver generate"-generated code *executes* correctly.
internal/simple
Package simple is used for a trivial test of code that uses Service Weaver.
Package simple is used for a trivial test of code that uses Service Weaver.
website
blog/deployers/multi
Package main implements a simple multiprocess deployer.
Package main implements a simple multiprocess deployer.
blog/deployers/pipes
Package main implements a trivial deployer that demonstrates the raw envelope-weavelet API.
Package main implements a trivial deployer that demonstrates the raw envelope-weavelet API.
blog/deployers/single
Package main implements a simple singleprocess deployer.
Package main implements a simple singleprocess deployer.

Jump to

Keyboard shortcuts

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