Skip to content

Commit

Permalink
add initialize, stop
Browse files Browse the repository at this point in the history
  • Loading branch information
sters committed May 21, 2021
1 parent e9a630d commit b4694aa
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 15 deletions.
2 changes: 2 additions & 0 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ func main() {
}

runHTTPServerMode(ctx, server)

onstatic.CleanupLoadedPlugins(ctx)
}

func runHTTPServerMode(ctx context.Context, server *http.Server) {
Expand Down
2 changes: 1 addition & 1 deletion onstatic/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func handleAll(res http.ResponseWriter, req *http.Request) {
return
}

handler := handlePlugin(req.URL.Path)
handler := handlePlugin(req.Context(), req.URL.Path)
if handler != nil {
handler(res, req)
return
Expand Down
25 changes: 21 additions & 4 deletions onstatic/plugin.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package onstatic

import (
"context"
"fmt"
"net/http"
"os"
Expand All @@ -27,14 +28,15 @@ type repoPlugins struct {
type repoPlugin struct {
lastModified time.Time
handlers oplugin.Handlers
api oplugin.API
}

var loadedPlugins = &loadedPluginsStruct{
m: sync.RWMutex{},
plugins: map[string]repoPlugins{},
}

func handlePlugin(requestPath string) http.HandlerFunc {
func handlePlugin(ctx context.Context, requestPath string) http.HandlerFunc {
pathes := strings.Split(requestPath, "/")
if len(pathes) < 2 {
return nil
Expand All @@ -49,7 +51,7 @@ func handlePlugin(requestPath string) http.HandlerFunc {
return nil
}

loadPluginIfPossible(repoName, repoFs, fsInfos)
loadPluginIfPossible(ctx, repoName, repoFs, fsInfos)

loadedPlugins.m.RLock()
defer loadedPlugins.m.RUnlock()
Expand All @@ -70,7 +72,7 @@ func handlePlugin(requestPath string) http.HandlerFunc {
return nil
}

func loadPluginIfPossible(repoName string, repoFs billy.Filesystem, fsInfos []os.FileInfo) {
func loadPluginIfPossible(ctx context.Context, repoName string, repoFs billy.Filesystem, fsInfos []os.FileInfo) {
for _, fsInfo := range fsInfos {
if err := checkLastModTime(fsInfo, repoName); err != nil {
zap.L().Warn("failed to load plugin, skip", zap.Error(err))
Expand All @@ -85,7 +87,9 @@ func loadPluginIfPossible(repoName string, repoFs billy.Filesystem, fsInfos []os
continue
}

handlers := ep(zap.L()).Register()
api := ep(ctx, zap.L())
api.Initialize(ctx)
handlers := api.Handlers()

loadedPlugins.m.Lock()
defer loadedPlugins.m.Unlock()
Expand All @@ -99,6 +103,7 @@ func loadPluginIfPossible(repoName string, repoFs billy.Filesystem, fsInfos []os
loadedPlugins.plugins[repoName].plugins[pluginName] = repoPlugin{
lastModified: fsInfo.ModTime(),
handlers: handlers,
api: api,
}

handlePaths := make([]string, len(handlers))
Expand Down Expand Up @@ -162,3 +167,15 @@ func loadPluginActual(repoFs billy.Filesystem, filename string) (oplugin.EntryPo

return ep, nil
}

func CleanupLoadedPlugins(ctx context.Context) {
loadedPlugins.m.Lock()
defer loadedPlugins.m.Unlock()

for _, repoPlugins := range loadedPlugins.plugins {
for _, p := range repoPlugins.plugins {
p.api.Stop(ctx)
}
}
loadedPlugins.plugins = make(map[string]repoPlugins)
}
18 changes: 13 additions & 5 deletions onstatic/plugin/api.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package plugin

import (
"context"
"net/http"

"go.uber.org/zap"
Expand All @@ -11,14 +12,21 @@ const (
PluginExportVariableName = "EntryPoint"
)

type Handler func(res http.ResponseWriter, req *http.Request)

// Endpoint definition that should start "/"
type Endpoint string

type Handlers map[Endpoint]Handler
// Handlers is Endpoint-HandlerFunc collection
type Handlers map[Endpoint]http.HandlerFunc

// API is main structure of this plugin
type API interface {
Register() Handlers
// Initialize this API
Initialize(context.Context)
// Start this API handling
Stop(context.Context)
// Handlers returns it for this API
Handlers() Handlers
}

type EntryPoint func(*zap.Logger) API
// EntryPoint is plugin entry point. First, call this function.
type EntryPoint func(context.Context, *zap.Logger) API
13 changes: 10 additions & 3 deletions onstatic/plugin_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package onstatic

import (
"context"
"fmt"
"net/http"
"os"
Expand Down Expand Up @@ -33,14 +34,20 @@ var testAPI1HandlerBar = func(res http.ResponseWriter, req *http.Request) {

type testAPI1 struct{}

func (*testAPI1) Register() oplugin.Handlers {
func (*testAPI1) Handlers() oplugin.Handlers {
return oplugin.Handlers{
"/foo": testAPI1HandlerFoo,
"/bar": testAPI1HandlerBar,
}
}
func (*testAPI1) Initialize(context.Context) {}
func (*testAPI1) Stop(context.Context) {}

var _ plugin.API = (*testAPI1)(nil)

func Test_handlePlugin(t *testing.T) {
ctx := context.Background()

// prepare
fs := map[string]billy.Filesystem{}
fsNew = func(dirpath string) billy.Filesystem {
Expand Down Expand Up @@ -84,7 +91,7 @@ func Test_handlePlugin(t *testing.T) {
}

loadPlugin = func(repoFs billy.Filesystem, filename string) (oplugin.EntryPoint, error) {
return func(l *zap.Logger) oplugin.API {
return func(_ context.Context, l *zap.Logger) oplugin.API {
return &testAPI1{}
}, nil
}
Expand All @@ -94,7 +101,7 @@ func Test_handlePlugin(t *testing.T) {
testAPI1HandlerFoo(want, nil)

got := &fakeHttpResponseWriter{}
f := handlePlugin(fmt.Sprintf("/%s/foo", dirname))
f := handlePlugin(ctx, fmt.Sprintf("/%s/foo", dirname))
f(got, nil)
if want.header != got.header {
t.Fatalf("failed to wrong handle function: want = %+v, got = %+v", want, got)
Expand Down
9 changes: 7 additions & 2 deletions plugins/example/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"context"
"fmt"
"net/http"
"os"
Expand All @@ -13,7 +14,11 @@ type greeting struct{}

var _ plugin.API = (*greeting)(nil)

func (g *greeting) Register() plugin.Handlers {
func (g *greeting) Initialize(context.Context) {}

func (g *greeting) Stop(context.Context) {}

func (g *greeting) Handlers() plugin.Handlers {
return plugin.Handlers{
"/greeting": func(res http.ResponseWriter, req *http.Request) {
_, err := res.Write([]byte("Hello, greeting!"))
Expand All @@ -25,6 +30,6 @@ func (g *greeting) Register() plugin.Handlers {
}

// nolint
var EntryPoint = plugin.EntryPoint(func(*zap.Logger) plugin.API {
var EntryPoint = plugin.EntryPoint(func(context.Context, *zap.Logger) plugin.API {
return &greeting{}
})

0 comments on commit b4694aa

Please sign in to comment.