Update go-pluggable

- Update vendor and run go mod tidy
This commit is contained in:
Ettore Di Giacinto
2021-05-11 14:02:15 +02:00
parent e5d6d21178
commit bdc24b84a4
14 changed files with 63 additions and 409 deletions

View File

@@ -1,6 +1,7 @@
# go-pluggable
# :bento: go-pluggable
[![PkgGoDev](https://pkg.go.dev/badge/github.com/mudler/go-pluggable)](https://pkg.go.dev/github.com/mudler/go-pluggable) [![Go Report Card](https://goreportcard.com/badge/github.com/mudler/go-pluggable)](https://goreportcard.com/report/github.com/mudler/go-pluggable) [![Test](https://github.com/mudler/go-pluggable/workflows/Test/badge.svg)](https://github.com/mudler/go-pluggable/actions?query=workflow%3ATest)
light Bus-event driven plugin library for Golang.
:bento: *go-pluggable* is a light Bus-event driven plugin library for Golang.
`go-pluggable` implements the event/sub pattern to extend your Golang project with external binary plugins that can be written in any language.
@@ -24,8 +25,24 @@ func main() {
m.Autoload("test", temp)
m.Register()
// ...
m.Publish(myEv, map[string]string{"foo": "bar"}) // test-foo, will receive our data as json payload
// Optionally process plugin results response
// The plugins has to return as output a json in stdout in the format { 'state': "somestate", data: "some data", error: "some error" }
// e.g. with jq:
// jq --arg key0 'state' \
// --arg value0 '' \
// --arg key1 'data' \
// --arg value1 "" \
// --arg key2 'error' \
// --arg value2 '' \
// '. | .[$key0]=$value0 | .[$key1]=$value1 | .[$key2]=$value2' \
// <<<'{}'
m.Response(myEv, func(p *pluggable.Plugin, r *pluggable.EventResponse) { ... })
// Emit events, they are encoded and passed as JSON payloads to the plugins.
// In our case, test-foo will receive the map as JSON
m.Publish(myEv, map[string]string{"foo": "bar"})
}
```
```

View File

@@ -1,73 +0,0 @@
// Copyright © 2020 Ettore Di Giacinto <mudler@mocaccino.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/>.
package pluggable
import (
"sync"
"github.com/chuckpreslar/emission"
"github.com/codegangsta/inject"
)
// Bus represent the bus event system
type Bus struct {
inject.Injector
emission.Emitter
sync.Mutex
}
// NewBus returns a new Bus instance
func NewBus() *Bus {
return &Bus{
Injector: inject.New(),
Emitter: *emission.NewEmitter(),
}
}
// Listen Binds a callback to an event, mapping the arguments on a global level
func (a *Bus) Listen(event EventType, listener interface{}) *Bus {
a.Lock()
defer a.Unlock()
a.On(string(event), func() { a.Invoke(listener) })
return a
}
// Publish publishes an event, it does accept only the event as argument, since
// the callback will have access to the service mapped by the injector
func (a *Bus) Publish(e *Event) *Bus {
a.Lock()
defer a.Unlock()
a.Map(e)
a.Emit(string(e.Name))
return a
}
// OnlyOnce Binds a callback to an event, mapping the arguments on a global level
// It is fired only once.
func (a *Bus) OnlyOnce(event EventType, listener interface{}) *Bus {
a.Lock()
defer a.Unlock()
a.Once(string(event), func() { a.Invoke(listener) })
return a
}
func (a *Bus) propagateEvent(p Plugin) func(e *Event) {
return func(e *Event) {
resp, _ := p.Run(*e)
a.Map(&resp)
a.Emit(p.Name)
}
}

View File

@@ -15,7 +15,10 @@
package pluggable
import "encoding/json"
import (
"encoding/json"
"fmt"
)
// EventType describes an event type
type EventType string
@@ -42,6 +45,10 @@ func (e Event) JSON() (string, error) {
return string(dat), err
}
func (e Event) ResponseEventName(s string) EventType {
return EventType(fmt.Sprintf("%s-%s", e.Name, s))
}
// Unmarshal decodes the json payload in the given parameteer
func (r EventResponse) Unmarshal(i interface{}) error {
return json.Unmarshal([]byte(r.Data), i)
@@ -52,7 +59,7 @@ func (r EventResponse) Errored() bool {
return len(r.Error) != 0
}
// NewEvent retuns a new event which can be used for publishing
// NewEvent returns a new event which can be used for publishing
// the obj gets automatically serialized in json.
func NewEvent(name EventType, obj interface{}) (*Event, error) {
dat, err := json.Marshal(obj)

View File

@@ -4,7 +4,6 @@ go 1.14
require (
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0
github.com/onsi/ginkgo v1.14.2
github.com/onsi/gomega v1.10.3
github.com/pkg/errors v0.9.1

View File

@@ -1,7 +1,5 @@
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9 h1:xz6Nv3zcwO2Lila35hcb0QloCQsc38Al13RNEzWRpX4=
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9/go.mod h1:2wSM9zJkl1UQEFZgSd68NfCgRz1VL1jzy/RjCg+ULrs=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=

View File

@@ -21,6 +21,7 @@ import (
"path/filepath"
"strings"
"github.com/chuckpreslar/emission"
"github.com/pkg/errors"
)
@@ -29,14 +30,14 @@ import (
type Manager struct {
Plugins []Plugin
Events []EventType
Bus *Bus
Bus *emission.Emitter
}
// NewManager returns a manager instance with a new bus and
func NewManager(events []EventType) *Manager {
return &Manager{
Events: events,
Bus: NewBus(),
Bus: emission.NewEmitter(),
}
}
@@ -47,19 +48,41 @@ func (m *Manager) Register() *Manager {
}
// Publish is a wrapper around NewEvent and the Manager internal Bus publishing system
// It accepts optionally a list of functions that are called with the plugin result (only once)
func (m *Manager) Publish(event EventType, obj interface{}) (*Manager, error) {
ev, err := NewEvent(event, obj)
if err == nil && ev != nil {
m.Bus.Publish(ev)
m.Bus.Emit(string(ev.Name), ev)
}
return m, err
}
// Response binds a set of listeners to an event type. The listeners are called for each result from
// every plugin when Publish is called.
func (m *Manager) Response(event EventType, listener ...func(p *Plugin, r *EventResponse)) *Manager {
ev, _ := NewEvent(event, nil)
for _, l := range listener {
m.Bus.On(string(ev.ResponseEventName("results")), l)
}
return m
}
func (m *Manager) propagateEvent(p Plugin) func(e *Event) {
return func(e *Event) {
resp, err := p.Run(*e)
r := &resp
if err != nil && !resp.Errored() {
resp.Error = err.Error()
}
m.Bus.Emit(string(e.ResponseEventName("results")), &p, r)
}
}
// Subscribe subscribes the plugin to the events in the given bus
func (m *Manager) Subscribe(b *Bus) *Manager {
func (m *Manager) Subscribe(b *emission.Emitter) *Manager {
for _, p := range m.Plugins {
for _, e := range m.Events {
b.Listen(e, b.propagateEvent(p))
b.On(string(e), m.propagateEvent(p))
}
}
return m
@@ -74,13 +97,6 @@ func relativeToCwd(p string) (string, error) {
return filepath.Join(cwd, p), nil
}
// ListenAll Binds a callback to all plugins event
func (m *Manager) ListenAll(event EventType, listener interface{}) {
for _, p := range m.Plugins {
m.Bus.Listen(EventType(p.Name), listener)
}
}
// Autoload automatically loads plugins binaries prefixed by 'prefix' in the current path
// optionally takes a list of paths to look also into
func (m *Manager) Autoload(prefix string, extensionpath ...string) *Manager {