From b4694aac64ef83e973fd6dd50318829d1b9526b2 Mon Sep 17 00:00:00 2001 From: sters Date: Fri, 21 May 2021 12:24:10 +0900 Subject: [PATCH] add initialize, stop --- cmd/server/main.go | 2 ++ onstatic/handler.go | 2 +- onstatic/plugin.go | 25 +++++++++++++++++++++---- onstatic/plugin/api.go | 18 +++++++++++++----- onstatic/plugin_test.go | 13 ++++++++++--- plugins/example/main.go | 9 +++++++-- 6 files changed, 54 insertions(+), 15 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 62d23cd..4456a01 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -31,6 +31,8 @@ func main() { } runHTTPServerMode(ctx, server) + + onstatic.CleanupLoadedPlugins(ctx) } func runHTTPServerMode(ctx context.Context, server *http.Server) { diff --git a/onstatic/handler.go b/onstatic/handler.go index 41ca485..4ed2655 100644 --- a/onstatic/handler.go +++ b/onstatic/handler.go @@ -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 diff --git a/onstatic/plugin.go b/onstatic/plugin.go index 5341038..4cc8291 100644 --- a/onstatic/plugin.go +++ b/onstatic/plugin.go @@ -1,6 +1,7 @@ package onstatic import ( + "context" "fmt" "net/http" "os" @@ -27,6 +28,7 @@ type repoPlugins struct { type repoPlugin struct { lastModified time.Time handlers oplugin.Handlers + api oplugin.API } var loadedPlugins = &loadedPluginsStruct{ @@ -34,7 +36,7 @@ var loadedPlugins = &loadedPluginsStruct{ 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 @@ -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() @@ -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)) @@ -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() @@ -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)) @@ -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) +} diff --git a/onstatic/plugin/api.go b/onstatic/plugin/api.go index 280c205..fa09d41 100644 --- a/onstatic/plugin/api.go +++ b/onstatic/plugin/api.go @@ -1,6 +1,7 @@ package plugin import ( + "context" "net/http" "go.uber.org/zap" @@ -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 diff --git a/onstatic/plugin_test.go b/onstatic/plugin_test.go index f034c9d..8436f4e 100644 --- a/onstatic/plugin_test.go +++ b/onstatic/plugin_test.go @@ -1,6 +1,7 @@ package onstatic import ( + "context" "fmt" "net/http" "os" @@ -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 { @@ -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 } @@ -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) diff --git a/plugins/example/main.go b/plugins/example/main.go index 4aee0a7..b64dc89 100644 --- a/plugins/example/main.go +++ b/plugins/example/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "net/http" "os" @@ -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!")) @@ -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{} })