fx

package module
v1.0.0-rc1 Latest Latest
Warning

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

Go to latest
Published: Jun 21, 2017 License: MIT Imports: 12 Imported by: 0

README

UberFx Service Framework

GoDoc Coverage Status Build Status Report Card

UberFx is a flexible, modularized framework for building robust and performant services. It takes care of the boilerplate code and lets you focus on your application logic.

Status

Beta. Expect minor API changes and bug fixes. See our changelog for more.

Compatibility

UberFx is compatible with Go 1.7 and above.

License

MIT

Documentation

Overview

Package fx is a modular service framework that makes it easy to create services and re-usable, composable modules.

Example
package main

import (
	"log"
	"net/http"
	"os"
	"time"

	"go.uber.org/fx"
)

func NewLogger() *log.Logger {
	logger := log.New(os.Stdout, "[Example] " /* prefix */, 0 /* flags */)
	logger.Print("Executing NewLogger.")
	return logger
}

func NewHandler(logger *log.Logger) http.Handler {
	logger.Print("Executing NewHandler.")
	return http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
		logger.Print("Got a request.")
	})
}

func NewMux(lc fx.Lifecycle, logger *log.Logger) *http.ServeMux {
	logger.Print("Executing NewMux.")
	mux := http.NewServeMux()
	server := &http.Server{
		Addr:    ":8080",
		Handler: mux,
	}
	// If NewMux is called, we know that someone is using the mux. In that case,
	// start up and shut down an HTTP server with the application.
	lc.Append(fx.Hook{
		OnStart: func() error {
			logger.Print("Starting HTTP server.")
			go server.ListenAndServe()
			return nil
		},
		OnStop: func() error {
			logger.Print("Stopping HTTP server.")
			return server.Close()
		},
	})

	return mux
}

func Register(mux *http.ServeMux, h http.Handler) {
	mux.Handle("/", h)
}

func main() {
	app := fx.New(
		// Provide all the constructors we need.
		fx.Provide(NewLogger, NewHandler, NewMux),
		// Before starting, register the handler. This forces resolution of all
		// the types in the container. Since the mux is now being used, its
		// startup hook gets registered and the application includes an HTTP
		// server.
		fx.Invoke(Register),
	)

	// In a real application, we could just use app.Run() here. Since we don't
	// want this example to run forever, we'll use Start and Stop.
	if err := app.Start(fx.Timeout(time.Second)); err != nil {
		log.Fatal(err)
	}

	// Normally, we'd block here with <-app.Done().
	http.Get("http://localhost:8080/")

	if err := app.Stop(fx.Timeout(time.Second)); err != nil {
		log.Fatal(err)
	}
}
Output:

[Example] Executing NewLogger.
[Example] Executing NewMux.
[Example] Executing NewHandler.
[Example] Starting HTTP server.
[Example] Got a request.
[Example] Stopping HTTP server.

Index

Examples

Constants

View Source
const DefaultTimeout = 15 * time.Second

DefaultTimeout is the start and stop timeout used by Run.

View Source
const Version = "1.0.0-rc1"

Version is exported for runtime compatibility checks.

Variables

This section is empty.

Functions

func Timeout

func Timeout(d time.Duration) context.Context

Timeout is a convenience function to construct a context with a timeout. It's only intended to reduce noise in the main function; since it doesn't expose context.CancelFunc, it may leak resources.

Types

type App

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

An App is a modular application built around dependency injection.

func New

func New(opts ...Option) *App

New creates and initializes an App. All applications begin with the Lifecycle type available in their dependency injection container.

func (*App) Done

func (app *App) Done() <-chan os.Signal

Done returns a channel of signals to block on after starting the application.

func (*App) Run

func (app *App) Run()

Run starts the application, blocks on the signals channel, and then gracefully shuts the application down. It uses DefaultTimeout for the start and stop timeouts.

See Start and Stop for application lifecycle details.

func (*App) Start

func (app *App) Start(ctx context.Context) error

Start starts the application.

First, Start checks whether any errors were encountered while applying Options. If so, it returns immediately.

It then executes all functions supplied via the Invoke option. Supplying arguments to these functions requires calling some of the constructors supplied by the Provide option. If any invoked function fails, an error is returned immediately.

By taking a dependency on the Lifecycle type, some of the executed constructors may register start and stop hooks. After executing all Invoke functions, Start executes all OnStart hooks registered with the application's Lifecycle, starting with the root of the dependency graph. This ensures that each constructor's start hooks aren't executed until all its dependencies' start hooks complete. If any of the start hooks return an error, start short-circuits.

func (*App) Stop

func (app *App) Stop(ctx context.Context) error

Stop gracefully stops the application. It executes any registered OnStop hooks in reverse order (from the leaves of the dependency tree to the roots), so that types are stopped before their dependencies.

If the application didn't start cleanly, only hooks whose OnStart phase was called are executed. However, all those hooks are always executed, even if some fail.

type Hook

type Hook struct {
	OnStart func() error
	OnStop  func() error
}

A Hook is a pair of start and stop callbacks, either of which can be nil. If a Hook's OnStart callback isn't executed (because a previous OnStart failure short-circuited application start), its OnStop callback won't be executed.

type Lifecycle

type Lifecycle interface {
	Append(Hook)
}

Lifecycle allows constructors to register callbacks that are executed on application start and stop.

type Option

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

An Option configures an App.

func Inject

func Inject(target interface{}) Option

Inject fills the given struct with values from the dependency injection container on application start.

The target MUST be a pointer to a struct. Only exported fields will be filled.

Example
var target struct {
	Logger *log.Logger
}

app := New(
	Provide(func() *log.Logger { return log.New(os.Stdout, "", 0) }),
	Inject(&target),
)

if err := app.Start(context.Background()); err != nil {
	log.Fatal(err)
}

target.Logger.Print("Injected!")
Output:

Injected!

func Invoke

func Invoke(funcs ...interface{}) Option

Invoke registers functions that are executed eagerly on application start. Arguments for these functions are provided from the application's dependency injection container.

Unlike constructors, invoked functions are always executed, and they're always run in order. Invoked functions may have any number of returned values. If the final returned object is an error, it's assumed to be a success indicator. All other returned values are discarded.

See the documentation for go.uber.org/dig for further details.

func Options

func Options(opts ...Option) Option

Options composes a collection of Options into a single Option.

func Provide

func Provide(constructors ...interface{}) Option

Provide registers constructors with the application's dependency injection container. Constructors provide one or more types, can depend on other types available in the container, and may optionally return an error. For example:

// Provides type *C, depends on *A and *B.
func(*A, *B) *C

// Provides type *C, depends on *A and *B, and indicates failure by
// returning an error.
func(*A, *B) (*C, error)

// Provides type *B and *C, depends on *A, and can fail.
func(*A) (*B, *C, error)

The order in which constructors are provided doesn't matter. Constructors are called lazily and their results are cached for reuse.

Taken together, these properties make it perfectly reasonable to Provide a large number of standard constructors even if only a fraction of them are used.

See the documentation for go.uber.org/dig for further details.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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