Skip to content

Commit

Permalink
Merge pull request #2 from dmcgowan/cleanup-plugin-interface
Browse files Browse the repository at this point in the history
Cleanup plugin interface
  • Loading branch information
dmcgowan authored Oct 25, 2023
2 parents 832b974 + 024f6f8 commit e13be35
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 20 deletions.
62 changes: 42 additions & 20 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ func NewContext(ctx context.Context, plugins *Set, properties map[string]string)
}
}

// Get returns the first plugin by its type
func (i *InitContext) Get(t Type) (interface{}, error) {
return i.plugins.Get(t)
}

// Meta contains information gathered from the registration and initialization
// process.
type Meta struct {
Expand Down Expand Up @@ -119,19 +114,41 @@ func (ps *Set) Add(p *Plugin) error {
return nil
}

// Get returns the first plugin by its type
func (ps *Set) Get(t Type) (interface{}, error) {
for _, v := range ps.byTypeAndID[t] {
return v.Instance()
// Get returns the plugin with the given type and id
func (ps *Set) Get(t Type, id string) *Plugin {
p, ok := ps.byTypeAndID[t]
if !ok {
return nil
}
return nil, fmt.Errorf("no plugins registered for %s: %w", t, ErrPluginNotFound)
return p[id]
}

// GetAll returns all initialized plugins
func (ps *Set) GetAll() []*Plugin {
return ps.ordered
}

// GetSingle returns a plugin instance of the given type when only a single instance
// of that type is expected. Throws an ErrPluginNotFound if no plugin is found and
// ErrPluginMultipleInstances when multiple instances are found.
// Since plugins are not ordered, if multiple instances is suported then
// GetByType should be used. If only one is expected, then to switch plugins,
// disable or remove the unused plugins of the same type.
func (i *InitContext) GetSingle(t Type) (interface{}, error) {
pt, ok := i.plugins.byTypeAndID[t]
if !ok || len(pt) == 0 {
return nil, fmt.Errorf("no plugins registered for %s: %w", t, ErrPluginNotFound)
}
if len(pt) > 1 {
return nil, fmt.Errorf("multiple plugins registered for %s: %w", t, ErrPluginMultipleInstances)
}
var p *Plugin
for _, v := range pt {
p = v
}
return p.Instance()
}

// Plugins returns plugin set
func (i *InitContext) Plugins() *Set {
return i.plugins
Expand All @@ -144,23 +161,28 @@ func (i *InitContext) GetAll() []*Plugin {

// GetByID returns the plugin of the given type and ID
func (i *InitContext) GetByID(t Type, id string) (interface{}, error) {
ps, err := i.GetByType(t)
if err != nil {
return nil, err
}
p, ok := ps[id]
if !ok {
return nil, fmt.Errorf("no %s plugins with id %s: %w", t, id, ErrPluginNotFound)
p := i.plugins.Get(t, id)
if p == nil {
return nil, fmt.Errorf("no plugins registered for %s.%s: %w", t, id, ErrPluginNotFound)
}
return p.Instance()
}

// GetByType returns all plugins with the specific type.
func (i *InitContext) GetByType(t Type) (map[string]*Plugin, error) {
p, ok := i.plugins.byTypeAndID[t]
func (i *InitContext) GetByType(t Type) (map[string]interface{}, error) {
pt, ok := i.plugins.byTypeAndID[t]
if !ok {
return nil, fmt.Errorf("no plugins registered for %s: %w", t, ErrPluginNotFound)
}

return p, nil
pi := make(map[string]interface{}, len(pt))
for id, p := range pt {
i, err := p.Instance()
if err != nil {
return nil, err
}
pi[id] = i
}

return pi, nil
}
2 changes: 2 additions & 0 deletions plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ var (
ErrPluginInitialized = errors.New("plugin: already initialized")
// ErrPluginNotFound is used when a plugin is looked up but not found
ErrPluginNotFound = errors.New("plugin: not found")
// ErrPluginMultipleInstances is used when a plugin is expected a single instance but has multiple
ErrPluginMultipleInstances = errors.New("plugin: multiple instances")

// ErrInvalidRequires will be thrown if the requirements for a plugin are
// defined in an invalid manner.
Expand Down

0 comments on commit e13be35

Please sign in to comment.