resolve

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 23, 2018 License: MIT Imports: 4 Imported by: 1

README

go-resolve

GoDoc Travis Coveralls

Why write this? Isn't dependency injection bad?

After messing with plugin systems for a while, one of the hardest problems to solve is plugin dependencies and loading things in a certain order. For generic systems, it can be hard to handle this properly in a safe manner.

go-resolve is intended to be a small wrapper around dependency injection to determine the proper load order of factory-like plugins and load them.

Dependency injection is generally frowned upon in go, but I view this as an acceptable trade-off to make writing plugin systems simpler. Additionally, running dependency injection once on startup, rather than every time an event happens, makes this simpler to manage and reduces the problem surface to the point where it should be testable.

But empty interfaces are bad!

Yes, this is true. Using empty interfaces in too many places is generally a code smell. However, in order to accept a function with any signature, this is a requirement.

We work around this by checking that the function will be valid for injection at the time it's added.

How does it work?

The actual concept behind ordering dependencies is fairly simple. Essentially, a dependency graph needs to be created, then you can just run a topological sort on the graph. The order of the nodes from that sort is the order items needs to be loaded in.

When we add a function to a resolver, we generate a graph node which contains a list of all the types needed to run that function as well as which types are returned. Any error types are ignored until the function itself is run.

After all nodes are added, simply call Resolve. This will determine the load order, load all plugins, and add any non-error return values to an Injector for use after plugins are loaded. If any function returns a non-nil error value, that will be returned as soon as it happens.

Other stuff

Be sure to check out go-plugin, which was my main reason for writing this.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EnsureValidFactory

func EnsureValidFactory(item interface{}) error

EnsureValidFactory will return nil if a factory is valid and an error if the factory cannot be used.

Types

type Resolver

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

Resolver is a set of values which, when called in the proper order, contain all the requirements as return values of other functions.

func NewResolver

func NewResolver() *Resolver

NewResolver returns an empty resolve set which can be used for resolving function calls.

func (*Resolver) AddNode

func (r *Resolver) AddNode(name string, item interface{}) error

AddNode adds a function to an internal graph of dependencies. The resolution will be done when Resolve is called.

func (*Resolver) Resolve

func (r *Resolver) Resolve() (inject.Injector, error)

Resolve will walk the graph of constructor nodes, run the constructors in the order they need to be run, and return an injector with all the return values from these constructors. Any error returned by these constructors will be returned by Resolve if the constructor returns them and is non nil. Note that because this requires a topological sort every time this is run, it is recommended to not use this often. Additionally, all nodes must be added before this method is called.

Jump to

Keyboard shortcuts

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