WIP: extension feature
This commit is contained in:
8
extension/error.go
Normal file
8
extension/error.go
Normal file
@ -0,0 +1,8 @@
|
||||
package extension
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrInvalidRegisterFunc = errors.New("invalid register func")
|
||||
ErrInvalidExtension = errors.New("invalid extension")
|
||||
)
|
6
extension/extension.go
Normal file
6
extension/extension.go
Normal file
@ -0,0 +1,6 @@
|
||||
package extension
|
||||
|
||||
type Extension interface {
|
||||
ExtensionName() string
|
||||
ExtensionVersion() string
|
||||
}
|
101
extension/registry.go
Normal file
101
extension/registry.go
Normal file
@ -0,0 +1,101 @@
|
||||
package extension
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"plugin"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Registry struct {
|
||||
extensions map[string]Extension
|
||||
mutex sync.RWMutex
|
||||
}
|
||||
|
||||
func (r *Registry) Load(ctx context.Context, path string) (Extension, error) {
|
||||
p, err := plugin.Open(path)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
registerFuncSymbol, err := p.Lookup("RegisterExtension")
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
register, ok := registerFuncSymbol.(func(context.Context) (Extension, error))
|
||||
if !ok {
|
||||
return nil, errors.WithStack(ErrInvalidRegisterFunc)
|
||||
}
|
||||
|
||||
ext, err := register(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
if ext == nil {
|
||||
return nil, errors.WithStack(ErrInvalidExtension)
|
||||
}
|
||||
|
||||
r.mutex.Lock()
|
||||
r.extensions[ext.ExtensionName()] = ext
|
||||
r.mutex.Unlock()
|
||||
|
||||
return ext, nil
|
||||
}
|
||||
|
||||
func (r *Registry) LoadAll(ctx context.Context, pattern string) ([]Extension, error) {
|
||||
extensions := make([]Extension, 0)
|
||||
|
||||
matches, err := filepath.Glob(pattern)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
for _, m := range matches {
|
||||
ext, err := r.Load(ctx, m)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
extensions = append(extensions, ext)
|
||||
}
|
||||
|
||||
return extensions, nil
|
||||
}
|
||||
|
||||
func (r *Registry) Extensions() []Extension {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
|
||||
extensions := make([]Extension, 0, len(r.extensions))
|
||||
for _, e := range r.extensions {
|
||||
extensions = append(extensions, e)
|
||||
}
|
||||
|
||||
return extensions
|
||||
}
|
||||
|
||||
type ExtensionFilterFunc func(ext Extension) bool
|
||||
|
||||
func (r *Registry) Filter(filter ExtensionFilterFunc) []Extension {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
|
||||
extensions := make([]Extension, 0, len(r.extensions))
|
||||
for _, e := range r.extensions {
|
||||
if filter(e) {
|
||||
extensions = append(extensions, e)
|
||||
}
|
||||
}
|
||||
|
||||
return extensions
|
||||
}
|
||||
|
||||
func NewRegistry() *Registry {
|
||||
return &Registry{
|
||||
extensions: make(map[string]Extension),
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user