Documentation

Overview

Package ioc provides an Inversion of Control component container and lifecycle hooks.

This package provides the types that define and support Granitic component container, which allows your application's objects and Granitic's framework facilities to follow the inversion of control (IoC) pattern by having their lifecycle and dependencies managed for them. An in-depth discussion of Granitic IoC can be found at http://granitic.io/1.0/ref/ioc but a description of the core concepts follows.

Components

A component is defined by Granitic as an instance of a Go struct with a name that is unique within an application. Each component in your application requires a entry in the components section of your application's component definition file like:

{
  "components": {
    "componentName": {
  	  "type": "package.structType"
    }
  }
}

e.g:

{
  "components": {
    "createRecordLogic": {
  	  "type": "inventory.CreateRecordLogic"
    }
  }
}

For complete information on defining components, refer to http://granitic.io/1.0/ref/components

Granitic's documentation will use the term component and component instance interchangeably. For example, 'component field' means 'a field on the instance of the Go struct associated with that component'.

The container

When Granitic starts, it will create an instance of ioc.ComponentContainer - a structure that holds references to each of the components in your application. It is responsible for injecting dependencies and configuration into your components (see below) and managing lifecycle events (also see below). The container is also referred to as the component container or IoC container.

Framework components

For each Granitic facility that you enable in your application, one or more framework components will be created and added to the container. A framework component is exactly the same as any other component - an instance of a struct with a name. Depending on the complexity of the facility, multiple components may be created.

A very simple name-spacing is used to separate the names of framework components from application components - framework components' names all start with the string grnc

You are strongly encouraged to make sure your application components' names do not start with this string.

Dependencies and configuration

As part of its definition, your components can request that other components are injected into its fields. Your definition can also include configuration (actual values to be set when the component is instantiated) or configuration promises (values to be injected once all sources of configuration have been merged together).

{
  "components": {
    "createRecordLogic": {
  	  "type": "inventory.CreateRecordLogic",
  	  "MaxTracks": 20,
  	  "ArtistMustExist": "conf:record.disableAutoArtist",
  	  "DAO": "ref:inventoryDAO"
    }
  }
}

In the above example, the field CreateRecordLogic.MaxTracks is set to 20 when the struct is instantiated, ArtistMustExist is set to the config element 'record.disableAutoArtist' and DAO is set to a reference to another component's instance. Note that c: and r: can be used as shorthand for config: and ref: See http://granitic.io/1.0/ref/components for more information

Any error such as type mismatches or missing configuration will cause an error that will halt application startup.

Component templates

A template mechanism exists to allow multiple components that share a type, dependencies or configuration items to only have those elements defined once. This is especially useful for web service handlers. See http://granitic.io/1.0/ref/components#templates for more details.

Binding

Unlike JVM/CLR languages, Go has no runtime 'instance-for-type-name' mechanism for creating instances of a struct. As a result, unlike JVM/CLR IoC containers you may have used, the container does not instantiate the actual instances of the Go structs behind application components. Instead a 'binding' proces is used - refer to the pacakage documentation for the grnc-bind tool for more information.

Container lifecycle

The process of starting the container transitions through a number of distinct phase. It is possible for your code to be explicitly invoked during some of these phases by implementing one more lifecycle interfaces.

Populate    Application and framework components are stored in the container.

Configure   Configuration and dependencies are resolved and injected into components.

Decorate    Components implementing the ioc.ComponentDecorator are given access to all other components
            to potentially modify.

Start       Components implementing the ioc.Startable interface are invoked.

Access	    Components implementing ioc.AccessibilityBlocker and ioc.Accessible are interacted with.

Ready       Granitic application is running.

When the container is ready, a log message similar to

grncInit Ready (startup time 6.28ms)

will be logged.

There are several other possible lifecycle phases after the container is ready:

Suspend     Components implementing ioc.Suspendable  have their Suspend method invoked.

Resume      Components implementing ioc.Suspendable have their Resume method invoked.

Stop        Components implementing ioc.Stoppable are allowed to stop gracefully before the application exits.

Decorators

Decorators are special components implementing ioc.ComponentDecorator. Their main purpose is to inject dynamically created objects into other components (such as Loggers). Decorators are destroyed after the Decorate phase of container startup.

Stopping

Components that need to perform some shutdown process before an application exits should implement the Stoppable interface. See the GoDoc for ioc.Stoppable below for more detail.

Container settings

The file $GRANITIC_HOME/resource/facility-config/system.json contains configuration, that can be overridden in your application's configuration file, affecting startup, garbage collection and shutdown behaviour of the container.

More information can be found at http://granitic.io/1.0/ref/system-settings

Gaining access to the container

If your application component needs direct access to the container it should implement the ioc.ContainerAccessor. A reference to the container will be injected into your component during the decorate phase.

External interaction with the container

If your application enables the RuntimeCtl facility, you can interact with the container and its components by using the grnc-ctl command line utility. See the package documentation for grnc-ctl for more information.

Index

Constants

View Source
const (
	StoppedState = iota
	StoppingState
	StartingState
	AwaitingAccessState
	RunningState
	SuspendingState
	SuspendedState
	ResumingState
)
View Source
const (
	None = iota
	CanStart
	CanStop
	CanSuspend
	CanBlockStart
	CanBeAccessed
)

Variables

This section is empty.

Functions

This section is empty.

Types

type AccessibilityBlocker

type AccessibilityBlocker interface {

	// BlockAccess returns true if the component wants to prevent the application from becoming ready and accessible. An
	// optional error message can be returned explaining why.
	BlockAccess() (bool, error)
}

    Implemented by components that MUST be ready before an application can be made accessible. For example, a component connecting to a critical external system might implement AccessibilityBlocker to prevent an HTTP server making an API available until a connection to the critical system is established.

    See http://granitic.io/1.0/ref/system-settings for information about the number of times BlockAccess is called, and how the interval between these calls can be adjusted for your application.

    type Accessible

    type Accessible interface {
    	// AllowAccess is called by the container as the final stage of making an application ready.
    	AllowAccess() error
    }

      Implemented by components that require a final phase of initialisation to make themselves outside of the application. Typically implemented by HTTP servers and message queue listeners to start listening on TCP ports.

      type ByName

      type ByName struct{ Components }

      func (ByName) Less

      func (s ByName) Less(i, j int) bool

      type Component

      type Component struct {
      	// A pointer to a struct
      	Instance interface{}
      
      	// A name for this component that is unique within your application
      	Name string
      }

        A Component is an instance of a struct with a name that is unique within your application.

        func NewComponent

        func NewComponent(name string, instance interface{}) *Component

          NewComponent creates a new Component with the supplied name and instance

          type ComponentByNameFinder

          type ComponentByNameFinder interface {
          	// ComponentByName returns the Component with the supplied name, or nil if it does not exist.
          	ComponentByName(string) *Component
          }

            Implemented by components that need to be able to find other components by name.

            type ComponentContainer

            type ComponentContainer struct {
            	FrameworkLogger logging.Logger
            
            	Lifecycle *LifecycleManager
            	// contains filtered or unexported fields
            }

              The Granitic IoC container. See the GoDoc for the ioc package for more information on how to interact with the container.

              Most applications should never need to interact with the container programmatically.

              func NewComponentContainer

              func NewComponentContainer(logm *logging.ComponentLoggerManager, ca *config.ConfigAccessor, sys *instance.System) *ComponentContainer

                Create a new instance of a Granitic IoC container.

                func (*ComponentContainer) AddModifier

                func (cc *ComponentContainer) AddModifier(comp string, field string, dep string)

                  AddModifier is used to override a dependency on a component (normally a built-in Granitic component) during the configure phase of container startup.

                  func (*ComponentContainer) AddModifiers

                  func (cc *ComponentContainer) AddModifiers(mods map[string]map[string]string)

                    AddModifiers is used to override a dependency on set of components (normally built-in Granitic components) during the configure phase of container startup.

                    func (*ComponentContainer) AddProto

                    func (cc *ComponentContainer) AddProto(proto *ProtoComponent)

                      AddProto registers an instantiated but un-configured proto-component.

                      func (*ComponentContainer) AddProtos

                      func (cc *ComponentContainer) AddProtos(protos []*ProtoComponent)

                        AddProto regsiters a collection of proto-components (see AddProto)

                        func (*ComponentContainer) AllComponents

                        func (cc *ComponentContainer) AllComponents() []*Component

                          AllComponents returns all of the components hosted by the container.

                          func (*ComponentContainer) ByLifecycleSupport

                          func (cc *ComponentContainer) ByLifecycleSupport(ls LifecycleSupport) []*Component

                            ByLifecycleSupport returns all components hosted by the container that have specific support for a lifecycle event (i.e. implement the associated lifecycle interface

                            func (*ComponentContainer) ComponentByName

                            func (cc *ComponentContainer) ComponentByName(name string) *Component

                              See ComponentByNameFinder.ComponentByName

                              func (*ComponentContainer) ModifierExists

                              func (cc *ComponentContainer) ModifierExists(comp string, field string) bool

                                ModifierExists checks to see if a modifier (see AddModifier) has previously been registered for a field on a component.

                                func (*ComponentContainer) Modifiers

                                func (cc *ComponentContainer) Modifiers(comp string) map[string]string

                                  Modifiers returns all registered modifiers (see AddModifier)

                                  func (*ComponentContainer) ModifiersExist

                                  func (cc *ComponentContainer) ModifiersExist(comp string) bool

                                    ModifiersExist returns true if any modifiers (see AddModifier) have been registered.

                                    func (*ComponentContainer) Populate

                                    func (cc *ComponentContainer) Populate() error

                                      Populate converts all registered proto-components into components and populates them with configuration and dependencies.

                                      func (*ComponentContainer) ProtoComponents

                                      func (cc *ComponentContainer) ProtoComponents() map[string]*ProtoComponent

                                        ProtoComponents returns all components that have been registered by the container but have not yet all their dependencies resolved. If called after the container is 'Accessible' an empty slice will be returned.

                                        func (*ComponentContainer) ProtoComponentsByType

                                        func (cc *ComponentContainer) ProtoComponentsByType(tm TypeMatcher) []*ProtoComponent

                                          ProtoComponentsByType returns any ProtoComponents whose Component.Instance field matches the against the supplied TypeMatcher function. If called after the container is 'Accessible' an empty slice will be returned.

                                          func (*ComponentContainer) WrapAndAddProto

                                          func (cc *ComponentContainer) WrapAndAddProto(name string, instance interface{})

                                            WrapAndAddProto registers an instance and name as an un-configured proto-component.

                                            type ComponentDecorator

                                            type ComponentDecorator interface {
                                            	// OfInterest should return true if the ComponentDecorator decides that the supplied component needs to be decorated.
                                            	OfInterest(subject *Component) bool
                                            
                                            	// DecorateComponent modifies the subject component.
                                            	DecorateComponent(subject *Component, container *ComponentContainer)
                                            }

                                              ComponentDecorator is implemented by special temporary components that only exist while the IoC container is being populated.

                                              A ComponentDecorator's job is to examine another component (the subject) to see if it is suitable for modification by the ComponentDecorator. Typically this will involve the ComponentDecorator injecting another object into the subject if the component implements a particular interface or has a writable field of a particular name or type.

                                              A number of built-in decorators exist to accomplish tasks like automatically adding Loggers to components with a particular field.

                                              type ComponentNamer

                                              type ComponentNamer interface {
                                              	// ComponentName returns the name of the component
                                              	ComponentName() string
                                              
                                              	// SetComponentName injects the component's name
                                              	SetComponentName(name string)
                                              }

                                                Implemented by components where the component's instance needs to be aware of its own component name.

                                                type ComponentState

                                                type ComponentState int

                                                  What state (stopped, running) or transition between states (stopping, starting) a component is currently in.

                                                  type Components

                                                  type Components []*Component

                                                    Type definition for a slice of components to allow sorting.

                                                    func (Components) Len

                                                    func (s Components) Len() int

                                                    func (Components) Swap

                                                    func (s Components) Swap(i, j int)

                                                    type ContainerAccessor

                                                    type ContainerAccessor interface {
                                                    	// Container accepts a reference to the Granitic IoC container.
                                                    	Container(container *ComponentContainer)
                                                    }

                                                      An interface implemented by any component that wants direct access to the IoC container.

                                                      type ContainerDecorator

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

                                                        ContainerDecorator injects a reference to the IoC container into any component implementing the ContainerAccessor interface.

                                                        func (*ContainerDecorator) DecorateComponent

                                                        func (cd *ContainerDecorator) DecorateComponent(subject *Component, cc *ComponentContainer)

                                                          DecorateComponent injects a reference to the IoC container to a component that has alredy been determined to implement ContainerAccessor.

                                                          func (*ContainerDecorator) OfInterest

                                                          func (cd *ContainerDecorator) OfInterest(subject *Component) bool

                                                            OfInterest returns true if the subject component implements ContainerAccessor

                                                            type LifecycleManager

                                                            type LifecycleManager struct {
                                                            	FrameworkLogger logging.Logger
                                                            	// contains filtered or unexported fields
                                                            }

                                                              Provides an interface to the components to allow lifecycle methods/events to be applied to all components or a subset of the components.

                                                              func (*LifecycleManager) ResumeComponents

                                                              func (lm *LifecycleManager) ResumeComponents(comps []*Component) error

                                                                SuspendComponents invokes Resume on all of the supplied components that implement Suspendable

                                                                func (*LifecycleManager) Start

                                                                func (lm *LifecycleManager) Start(startable []*Component) error

                                                                  Start starts the supplied components, waits for any access-blocking components to be ready, then makes all components accessible. See GoDoc for Startable, AccessibilityBlocker and Accessible for more details.

                                                                  func (*LifecycleManager) StartAll

                                                                  func (lm *LifecycleManager) StartAll() error

                                                                    StartAll finds all Startable and Accessible components runs the Start/Block/Accessible cycle.

                                                                    func (*LifecycleManager) StopAll

                                                                    func (lm *LifecycleManager) StopAll() error

                                                                      StopAll finds all components implementing Stoppable and passes them to Stop

                                                                      func (*LifecycleManager) StopComponents

                                                                      func (lm *LifecycleManager) StopComponents(comps []*Component) error

                                                                        StopComponents invokes PrepareToStop on all components then waits for them to be ready to stop by calling ReadyToStop on each component. If one or more components are not ready, they are given x chances to become ready with y milliseconds between each check. See http://granitic.io/1.0/ref/system-settings

                                                                        If all components are ready, or if x has been exceeded, Stop is called on all components.

                                                                        func (*LifecycleManager) SuspendComponents

                                                                        func (lm *LifecycleManager) SuspendComponents(comps []*Component) error

                                                                          SuspendComponents invokes Suspend on all of the supplied components that implement Suspendable

                                                                          type LifecycleSupport

                                                                          type LifecycleSupport int

                                                                            Enumeration able used to categorise types by the lifecycle events they can react to.

                                                                            type ProtoComponent

                                                                            type ProtoComponent struct {
                                                                            	// The name of a component and the component instance (a pointer to an instantiated struct).
                                                                            	Component *Component
                                                                            
                                                                            	// A map of fields on the component instance and the names of other components that should be injected into those fields.
                                                                            	Dependencies map[string]string
                                                                            
                                                                            	// A map of fields on the component instance and the config-path that will contain the configuration that shoud be inject into the field.
                                                                            	ConfigPromises map[string]string
                                                                            }

                                                                              A ProtoComponent is a partially configured component that will be hosted in the Granitic IoC container once it is fully configured. Typically ProtoComponents are created using the grnc-bind tool.

                                                                              func CreateProtoComponent

                                                                              func CreateProtoComponent(componentInstance interface{}, componentName string) *ProtoComponent

                                                                                CreateProtoComponent creates a new ProtoComponent.

                                                                                func (*ProtoComponent) AddConfigPromise

                                                                                func (pc *ProtoComponent) AddConfigPromise(fieldName, configPath string)

                                                                                  AddDependency requests that the container injects the config value at the specified path into the specified field during the configure phase of container startup.

                                                                                  func (*ProtoComponent) AddDependency

                                                                                  func (pc *ProtoComponent) AddDependency(fieldName, componentName string)

                                                                                    AddDependency requests that the container injects another component into the specified field during the configure phase of container startup

                                                                                    type ProtoComponents

                                                                                    type ProtoComponents struct {
                                                                                    	// ProtoComponents to be finalised and stored in the IoC container.
                                                                                    	Components []*ProtoComponent
                                                                                    
                                                                                    	// FrameworkDependencies are instructions to inject components into built-in Granitic components to alter their behaviour.
                                                                                    	// The structure is map[
                                                                                    	FrameworkDependencies map[string]map[string]string
                                                                                    
                                                                                    	//A Base64 encoded version of the JSON files found in resource/facility-confg
                                                                                    	FrameworkConfig *string
                                                                                    }

                                                                                      A wrapping structure for a list of ProtoComponents and FrameworkDependencies that is required when starting Granitic. A ProtoComponents structure is built by the grnc-bind tool.

                                                                                      func NewProtoComponents

                                                                                      func NewProtoComponents(pc []*ProtoComponent, fd map[string]map[string]string, ser *string) *ProtoComponents

                                                                                        NewProtoComponents creates a wrapping structure for a list of ProtoComponents

                                                                                        func (*ProtoComponents) Clear

                                                                                        func (pc *ProtoComponents) Clear()

                                                                                          Clear removes the reference to the ProtoComponent objects held in this object, encouraging garbage collection.

                                                                                          type Startable

                                                                                          type Startable interface {
                                                                                          	// StartComponent performs initialisation and may start listeners/servers.
                                                                                          	StartComponent() error
                                                                                          }

                                                                                            Implemented by components that need to perform some initialisation before they are ready to run or use.

                                                                                            Components that provide services outside of the application (like HTTP servers or queue listeners) should consider implementing Accessible in addition to Startable.

                                                                                            type Stoppable

                                                                                            type Stoppable interface {
                                                                                            	// PrepareToStop gives notice to the component that the application is about to halt. The implementation of this method
                                                                                            	// should cause the component to block any new requests for work.
                                                                                            	PrepareToStop()
                                                                                            
                                                                                            	// ReadyToStop is called by the container to query whether or not the component is ready to shutdown. A component might
                                                                                            	// return false if it is still processing or running a job. If the component returns false, it may optionally return
                                                                                            	// an error to explain why it is not ready.
                                                                                            	ReadyToStop() (bool, error)
                                                                                            
                                                                                            	// Stop is an instruction by the container to immediately terminate any running processes and release any resources.
                                                                                            	// If the component is unable to do so, it may return an error, but the application will still stop.
                                                                                            	Stop() error
                                                                                            }

                                                                                              Implemented by components that need to be given the opportunity to release resources or perform shutdown activities before an application is halted.

                                                                                              See http://granitic.io/1.0/ref/system-settings for information about the number of times ReadyToStop is called, and how the interval between these calls, can be adjusted for your application.

                                                                                              type StructFactory

                                                                                              type StructFactory func() interface{}

                                                                                                A function able to return a pointer to an empty struct

                                                                                                type Suspendable

                                                                                                type Suspendable interface {
                                                                                                	// Suspend causes the component to stop performing its primary function until Resume is called.
                                                                                                	Suspend() error
                                                                                                
                                                                                                	// Resume causes the component to resume its primary function.
                                                                                                	Resume() error
                                                                                                }

                                                                                                  Implemented by components that are able to temporarily halt and then resume their activity at some later point in time.

                                                                                                  type TypeMatcher

                                                                                                  type TypeMatcher func(i interface{}) bool

                                                                                                    TypeMatcher implementations return true if the supplied interface is (or implements) an expected type