service

package
v1.0.0-beta2 Latest Latest
Warning

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

Go to latest
Published: Mar 10, 2017 License: MIT Imports: 22 Imported by: 0

README

Service

Service, being a bit of an overloaded term, requires some specific care to explain the various components in the service package in UberFx.

Core

This model results in a simple, consistent way to start a service. For example, in the case of a simple TChannel Service, main.go might look like this:

package main

import (
  "go.uber.org/fx/config"
  "go.uber.org/fx/modules/yarpc"
  "go.uber.org/fx/service"
)

func main() {
  // Create the service object
  svc, err := service.WithModule(
    // The list of module creators for this service
    yarpc.New(yarpc.ServiceCreateFunc(NewYarpcThriftHandler)),
  ).Build()

  if err != nil {
    log.Fatal("Could not initialize service: ", err)
  }

  // Start the service, with "true" meaning:
  // * Wait for service exit
  // * Report a non-zero exit code if shutdown is caused by an error
  svc.Start(true)
}
Roles

It's common for a service to handle many different workloads. For example, a service may expose RPC endpoints and also ingest Kafka messages.

In UberFX, there is a simpler model where we create a single binary, but turn its modules on and off based on roles which are specified via the command line.

For example, imagine we wanted a "worker" and a "service" role that handled Kafka and TChannel, respectively:

func main() {
  svc, err := service.WithModule(
    kafka.Module("kakfa_topic1", []string{"worker"}),
  ).WithModule(
    yarpc.New(yarpc.ServiceCreateFunc(NewYarpcThriftHandler)),
    service.WithRole("service"),
  ).Build()

  if err != nil {
    log.Fatal("Could not initialize service: ", err)
  }

  svc.Start()
}

Which then allows us to set the roles either via a command line variable:

export CONFIG__roles__0=worker

Or via the service parameters, we would activate in the following ways:

  • ./myservice or ./myservice --roles "service,worker": Runs all modules
  • ./myservice --roles "worker": Runs only the Kakfa module
  • Etc...

Options

The service builder takes a variadic Options pattern, allowing you to pick and choose which components you'd like to override. As a common theme of UberFx, specifying zero options should give you a fully working application.

Once you have a service, you call .Start() on it to begin receiving requests.

Start(bool) comes in two variants: a blocking version and a non-blocking version. In our sample apps, we use the blocking version (svc.Start(true)) and yield control to the service lifecycle manager. If you wish to do other things after starting your service, you may pass false and use the return values of svc.Start(bool) to listen on channels and trigger manual shutdowns.

Documentation

Overview

Package service is the Service.

Service, being a bit of an overloaded term, requires some specific care to explain the various components in the servicepackage in UberFx.

Core

This model results in a simple, consistent way to start a service. For example, in the case of a simple TChannel Service, main.go might look like this:

package main

import (
  "go.uber.org/fx/config"
  "go.uber.org/fx/modules/yarpc"
  "go.uber.org/fx/service"
)

func main() {
  // Create the service object
  svc, err := service.WithModule(
    // The list of module creators for this service
    yarpc.New(yarpc.ServiceCreateFunc(NewYarpcThriftHandler)),
  ).Build()

  if err != nil {
    log.Fatal("Could not initialize service: ", err)
  }

  // Start the service, with "true" meaning:
  // * Wait for service exit
  // * Report a non-zero exit code if shutdown is caused by an error
  svc.Start(true)
}

Roles

It's common for a service to handle many different workloads. For example, a service may expose RPC endpoints and also ingest Kafka messages.

In UberFX, there is a simpler model where we create a single binary, but turn its modules on and off based on roles which are specified via the command line.

For example, imagine we wanted a "worker" and a "service" role that handled Kafka and TChannel, respectively:

func main() {
  svc, err := service.WithModule(
    kafka.Module("kakfa_topic1", []string{"worker"}),
  ).WithModule(
    yarpc.New(yarpc.ServiceCreateFunc(NewYarpcThriftHandler)),
    service.WithRole("service"),
  ).Build()

  if err != nil {
    log.Fatal("Could not initialize service: ", err)
  }

  svc.Start()
}

Which then allows us to set the roles either via a command line variable:

export CONFIG__roles__0=worker

Or via the service parameters, we would activate in the following ways:

• ./myservice or ./myservice --roles "service,worker": Runs all modules

• ./myservice --roles "worker": Runs only the **Kakfa** module

• Etc...

Options

The service builder takes a variadic Optionspattern, allowing you to pick and choose which components you'd like to override. As a common theme of UberFx, specifying zero options should give you a fully working application.

Once you have a service, you call .Start() on it to begin receiving requests.

Start(bool) comes in two variants: a blocking version and a non-blocking version. In our sample apps, we use the blocking version ( svc.Start(true)) and yield control to the service lifecycle manager. If you wish to do other things after starting your service, you may pass false and use the return values of svc.Start(bool) to listen on channels and trigger manual shutdowns.

Index

Constants

View Source
const (
	// Uninitialized means a service has not yet been initialized
	Uninitialized = State(iota)
	// Initialized means a service has been initialized
	Initialized
	// Starting represents a service in the process of starting
	Starting
	// Running represents a running service
	Running
	// Stopping represents a service in the process of stopping
	Stopping
	// Stopped represents a service that has been shut down
	Stopped
)

Variables

View Source
var DefaultStubModuleCreateFunc = NewStubModuleCreateFunc(&StubModule{})

DefaultStubModuleCreateFunc is a ModuleCreateFunc that returns a StubModule with only Host set.

Functions

func NewStubModuleCreateFunc

func NewStubModuleCreateFunc(stubModule *StubModule) func(Host) (Module, error)

NewStubModuleCreateFunc returns a new Module create function for a new StubModule.

If stubModule is nil, this will return nil for the new Module.

Host will be overwritten.

Types

type Builder

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

A Builder is a helper to create a service

func WithModule

func WithModule(provider ModuleProvider, options ...ModuleOption) *Builder

WithModule is a helper to create a service without any options

func (*Builder) Build

func (b *Builder) Build() (Manager, error)

Build returns the service, or any errors encountered during build phase.

func (*Builder) WithModule

func (b *Builder) WithModule(provider ModuleProvider, options ...ModuleOption) *Builder

WithModule adds the given module to the service with the given name

func (*Builder) WithOptions

func (b *Builder) WithOptions(options ...Option) *Builder

WithOptions adds service Options to the builder

type Control

type Control struct {
	ExitChan     chan Exit
	ReadyChan    chan struct{}
	ServiceError error
}

Control keeps the listening channels from the service startup

type Exit

type Exit struct {
	Reason   string
	Error    error
	ExitCode int
}

Exit is a signal for a service that needs to exit

type ExitCallback

type ExitCallback func(shutdown Exit) int

A ExitCallback is a function to handle a service shutdown and provide an exit code

type Host

type Host interface {
	AuthClient() auth.Client
	Name() string
	Description() string
	Roles() []string
	State() State
	Metrics() tally.Scope
	RuntimeMetricsCollector() *metrics.RuntimeCollector
	Observer() Observer
	Config() config.Provider
	Tracer() opentracing.Tracer
	// TODO: Will be removed once log/metrics scoping is moved to the module provider
	ModuleName() string
}

A Host represents the hosting environment for a service instance

func NewScopedHost

func NewScopedHost(host Host, moduleName, serviceName string, roles ...string) (Host, error)

NewScopedHost returns a new Host scoped to a module. This should generally be used for testing.

func NopHost

func NopHost() Host

NopHost is to be used in tests

func NopHostAuthFailure

func NopHostAuthFailure() Host

NopHostAuthFailure is nop manager with failure auth client

func NopHostConfigured

func NopHostConfigured(client auth.Client, logger *zap.Logger, tracer opentracing.Tracer) Host

NopHostConfigured is a nop manager with set logger and tracer for tests

func NopHostWithConfig

func NopHostWithConfig(configProvider config.Provider) Host

NopHostWithConfig is to be used in tests and allows setting of config.

type HostContainer

type HostContainer struct {
	Host
}

A HostContainer is meant to be embedded in a LifecycleObserver if you want access to the underlying Host

func (*HostContainer) SetContainer

func (s *HostContainer) SetContainer(sh Host)

SetContainer sets the Host instance on the container. NOTE: This is not thread-safe, and should only be called once during startup.

type Manager

type Manager interface {
	Host

	// Start service is used for blocking the call on service start. Start will block the
	// call and yield the control to the service lifecyce manager. No code will be executed
	//after call to Start() the service.
	Start()

	// StartAsync service is used as a non-blocking the call on service start. StartAsync will
	// return the call to the caller with a Control to listen on channels
	// and trigger manual shutdown.
	StartAsync() Control
	Stop(reason string, exitCode int) error
}

A Manager encapsulates service ownership

type Module

type Module interface {
	// Start the Module. If an error is returned, the Module is assumed to be not started.
	// There is no need for this to be thread-safe, it will be called in a thread-safe manner.
	Start() error
	// Stop the Module. If an error is returned, the Module is still assumed to be stopped.
	// There is no need for this to be thread-safe, it will be called in a thread-safe manner.
	Stop() error
}

Module is the basic building block of an UberFx service.

type ModuleOption

type ModuleOption func(*moduleOptions) error

ModuleOption is a function that configures module creation.

func WithModuleName

func WithModuleName(name string) ModuleOption

WithModuleName will override the name given by the ModuleProvider.

func WithName

func WithName(name string) ModuleOption

WithName will override the root service name specified in config.

func WithRole

func WithRole(role string) ModuleOption

WithRole will add a role to the Module.

If the role was already added, this will be a no-op.

type ModuleProvider

type ModuleProvider interface {
	// DefaultName returns the default module name
	DefaultName() string
	// Create a new Module. The name of the Host and the scoping
	// of associated functions on the Host will be done using a name
	// provided by a ModuleOption, or by the DefaultName on this ModuleProvider.
	Create(Host) (Module, error)
}

ModuleProvider provides Modules.

func ModuleProviderFromFunc

func ModuleProviderFromFunc(name string, createFunc func(Host) (Module, error)) ModuleProvider

ModuleProviderFromFunc creates a new ModuleProvider from a name and create function.

type Observer

type Observer interface {
	// OnInit will be called after the service has been initialized
	OnInit(service Host) error

	// OnStateChange is called whenever the service changes
	// states
	OnStateChange(old State, curr State)

	// OnShutdown is called before the service shuts down
	OnShutdown(reason Exit)

	// OnCriticalError is called in response to a critical error.  If false
	// is returned the service will shut down, otherwise the error will be ignored.
	OnCriticalError(err error) bool
}

Observer is the interface that is implemented by user service/ code.

func AfterStart

func AfterStart(f func()) Observer

AfterStart will create an observer that will execute f() immediately after service starts.

func ObserverStub

func ObserverStub() Observer

ObserverStub returns a stub instance of an Observer

type Option

type Option func(*manager) error

A Option configures a manager

func WithConfiguration

func WithConfiguration(config config.Provider) Option

WithConfiguration adds configuration to a manager

func WithMetrics

func WithMetrics(scope tally.Scope, reporter tally.CachedStatsReporter) Option

WithMetrics configures a manager with metrics and stats reporter

func WithObserver

func WithObserver(observer Observer) Option

WithObserver configures a manager with an instance lifecycle observer

func WithTracer

func WithTracer(tracer opentracing.Tracer) Option

WithTracer configures a manager with a tracer

type SetContainerer

type SetContainerer interface {
	SetContainer(Host)
}

SetContainerer is the interface for anything that you can call SetContainer on

type State

type State int

A State represents the state of a service

type StubModule

type StubModule struct {
	Host       Host
	StartError error
	StopError  error
}

A StubModule implements the Module interface for testing

func NewStubModule

func NewStubModule(host Host) *StubModule

NewStubModule generates a Module for use in testing

func (*StubModule) Start

func (s *StubModule) Start() error

Start mimics startup

func (*StubModule) Stop

func (s *StubModule) Stop() error

Stop stops the module

type StubModuleProvider

type StubModuleProvider struct {
	NameVal   string
	CreateVal func(Host) (Module, error)
}

StubModuleProvider implements the ModuleProvider interface for testing.

func NewDefaultStubModuleProvider

func NewDefaultStubModuleProvider() *StubModuleProvider

NewDefaultStubModuleProvider returns a new StubModuleProvider with an empty StubModule.

func NewStubModuleProvider

func NewStubModuleProvider(name string, stubModule *StubModule) *StubModuleProvider

NewStubModuleProvider returns a new StubModuleProvider with the given name and create function from NewStubModuleCreateFunc.

func (*StubModuleProvider) Create

func (p *StubModuleProvider) Create(host Host) (Module, error)

Create creates a new Module.

func (*StubModuleProvider) DefaultName

func (p *StubModuleProvider) DefaultName() string

DefaultName returns the module name

type StubObserver

type StubObserver struct {
	HostContainer
	// contains filtered or unexported fields
}

StubObserver may be used for tests or demonstration apps where you wish to observe state transitions without implementing your own observer

func (*StubObserver) OnCriticalError

func (s *StubObserver) OnCriticalError(err error) bool

OnCriticalError is called whin the app is about to shut down

func (*StubObserver) OnInit

func (s *StubObserver) OnInit(svc Host) error

OnInit is called when a service is initialized

func (*StubObserver) OnShutdown

func (s *StubObserver) OnShutdown(reason Exit)

OnShutdown is called for a shutdown

func (*StubObserver) OnStateChange

func (s *StubObserver) OnStateChange(old State, curr State)

OnStateChange is called during state transitions

Directories

Path Synopsis
Package testutils is the Service test utilities.
Package testutils is the Service test utilities.

Jump to

Keyboard shortcuts

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