yuu

module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Aug 2, 2020 License: MIT

README

tests GoDoc

Yuu

Yuu is a lightweight module in its early stages of development/testing. Its aim is to aid in using plugin/event driven architecture within go. There are probably alternatives out there, I just started doing something small and it turned into this.

There are 2 main parts to this module, the Plugin and Handler. The Handler can register any Plugin's it is asked to load, this can be through .so file(s) (built using go build -buildmode=plugin) or any struct that implements the pkg/plugin.Plugin interface, example of this here.

Handler

The Handler is used to manage any loaded plugins. Plugins can be loaded via any stuct that implements the pkg/plugin.Plugin interface, or .so files. This should be used in any main application and not really in the plugins themselves. The handler will pass itself to the plugins when they are registered via the Register function on the Plugins interface, this allows them to store the managers pointer reference and use it for communicating with other plugins.

Example use of the handler:

import (
    "github.com/weavc/yuu/pkg"
    "github.com/weavc/yuu/pkg/plugin"
)

type RegisterAPI interface {
	RegisterRoutes(mux *http.ServeMux)
}

func main() {

    var s *http.ServeMux = http.DefaultServeMux

    // build plugins from source to examples/.bin
	pkg.BuildPlugins("examples/.bin/", []string{"examples/plugins/hello-world", "examples/plugins/api"})

	// create/get new Handler structure & load plugins from examples/.bin
	m := pkg.NewHandler()
	m.LoadPluginDir("examples/.bin/")

    // recieve api events, these are emitted in the api plugin
	m.On("api", func(v interface{}) {
		s := v.(string)
		log.Print(s)
	})

	// walk through plugins (foreach registered plugin)
	m.Walk(func(man *plugin.Manifest, plgin plugin.Plugin) {
		// check if plugin implements RegisterAPI interface defined above
		p, e := plgin.(RegisterAPI)
		if e == true {
			// let plugin register handlers
			p.RegisterRoutes(s)
		}
	})

	log.Fatal(http.ListenAndServe(":8080", nil))
}

Plugins

Plugins should only ever import "github.com/weavc/yuu/pkg/plugin", this helps reduce circular reference issues and also the need to rebuild for any minor releases. If the plugin is being built & distibuted via the .so file (built using go build -buildmode=plugin), there should be an exported variable named Plugin in the main package, this is how the handler will find the Plugin in the binary, see below example for what this should look like.

Example plugin:

package main

import (
	"encoding/json"
	"net/http"

	"github.com/weavc/yuu/pkg/plugin"
)

// Plugin variable that implements github.com/weavc/yuu/pkg/plugin.Plugin
// must be exported if building into a .so file.
//This is how the Plugin is found within the binary plugin
var Plugin ApiPlugin = ApiPlugin{}

// ApiPlugin is the struct that implements plugin.Plugin & more
type ApiPlugin struct {
	handler plugin.Handler

	plugin.Plugin
}

// Manifest gives the handler & other plugins an idea of what this plugin is
func (p *ApiPlugin) Manifest() *plugin.Manifest {
	return &plugin.Manifest{Name: "Api", Description: "Api plugin", Events: []string{"api"}}
}

// Register is used to initialize & setup the plugin
func (p *ApiPlugin) Register(m plugin.Handler) error {
	// store Handler pointer
	p.handler = m

	return nil
}

// RegisterRoutes implements an interface defined in examples/main.go
// An example of how plugins can be extended to provide additional
// communication with different applications.
func (p ApiPlugin) RegisterRoutes(mux *http.ServeMux) {
	mux.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
		p.handler.Emit("api", r.URL.String())
		w.WriteHeader(200)
		json.NewEncoder(w).Encode(map[string]string{"status": "success"})
	})
}

Directories

Path Synopsis
cmd
pkg

Jump to

Keyboard shortcuts

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