plugin: add plugin type for daemon plugins
This allows users to run multiple go-ipfs "clients" in-process. License: MIT Signed-off-by: Steven Allen <steven@stebalien.com>
Steven Allen committed
Jan 29, 2019 at 12:44 UTC
a9f2aee3fc94c904e970e3b312e24f4b87e1cf5c
3 files changed
+74
-3
cmd/ipfs/daemon.go
+15
@@ -17,6 +17,7 @@ import (
17
oldcmds "github.com/ipfs/go-ipfs/commands"
18
"github.com/ipfs/go-ipfs/core"
19
commands "github.com/ipfs/go-ipfs/core/commands"
20
+ coreapi "github.com/ipfs/go-ipfs/core/coreapi"
21
corehttp "github.com/ipfs/go-ipfs/core/corehttp"
22
corerepo "github.com/ipfs/go-ipfs/core/corerepo"
23
nodeMount "github.com/ipfs/go-ipfs/fuse/node"
@@ -25,6 +26,7 @@ import (
26
27
ma "gx/ipfs/QmNTCey11oxhb1AxDnQBRHtdhap6Ctud872NjAYPYYXPuc/go-multiaddr"
28
cmds "gx/ipfs/QmR77mMvvh8mJBBWQmBfQBu8oD38NUN4KE9SL2gDgAQNc6/go-ipfs-cmds"
29
+ goprocess "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess"
30
"gx/ipfs/QmTQuFQWHAWy4wMH6ZyPfGiawA5u9T8rs79FENoV8yXaoS/client_golang/prometheus"
31
mprome "gx/ipfs/QmVMcMs6duiwLzvhF6xWM3yc4GgjpNoctKFhvtBch5tpgo/go-metrics-prometheus"
32
"gx/ipfs/QmZcLBXKaFe8ND5YHPkJRAwmhJGrVsi1JqDZNyJ4nRK5Mj/go-multiaddr-net"
@@ -355,6 +357,18 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment
357
return node, nil
358
}
359
360
+ // Start "core" plugins. We want to do this *before* starting the HTTP
361
+ // API as the user may be relying on these plugins.
362
+ api, err := coreapi.NewCoreAPI(node)
363
+ if err != nil {
364
+ return err
365
+ }
366
+ err = cctx.Plugins.Start(api)
367
+ if err != nil {
368
+ return err
369
+ }
370
+ node.Process().AddChild(goprocess.WithTeardown(cctx.Plugins.Close))
371
+
372
// construct api endpoint - every time
373
apiErrc, err := serveHTTPApi(req, cctx)
374
if err != nil {
@@ -391,6 +405,7 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment
405
// initialize metrics collector
406
prometheus.MustRegister(&corehttp.IpfsNodeCollector{Node: node})
407
408
+ // The daemon is *finally* ready.
409
fmt.Printf("Daemon is ready\n")
410
411
// Give the user some immediate feedback when they hit C-c
plugin/daemon.go
new
+14
@@ -0,0 +1,14 @@
1
+package plugin
2
+
3
+import (
4
+ coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
5
+)
6
+
7
+// PluginDaemon is an interface for daemon plugins. These plugins will be run on
8
+// the daemon and will be given access to an implementation of the CoreAPI.
9
+type PluginDaemon interface {
10
+ Plugin
11
+
12
+ Start(coreiface.CoreAPI) error
13
+ Close() error
14
+}
plugin/loader/loader.go
+45
-3
@@ -2,10 +2,13 @@ package loader
2
3
import (
4
"fmt"
5
- "github.com/ipfs/go-ipfs/core/coredag"
6
- "github.com/ipfs/go-ipfs/plugin"
7
- "github.com/ipfs/go-ipfs/repo/fsrepo"
5
"os"
6
+ "strings"
7
+
8
+ coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
9
+ coredag "github.com/ipfs/go-ipfs/core/coredag"
10
+ plugin "github.com/ipfs/go-ipfs/plugin"
11
+ fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
12
13
ipld "gx/ipfs/QmRL22E4paat7ky7vx9MLpR97JHHbFPrg3ytFQw6qp1y1s/go-ipld-format"
14
opentracing "gx/ipfs/QmWLWmRVSiagqP15jczsGME1qpob6HDbtbHAY2he9W5iUo/opentracing-go"
@@ -106,6 +109,45 @@ func (loader *PluginLoader) Inject() error {
109
return nil
110
}
111
112
+// Start starts all long-running plugins.
113
+func (loader *PluginLoader) Start(iface coreiface.CoreAPI) error {
114
+ for i, pl := range loader.plugins {
115
+ if pl, ok := pl.(plugin.PluginDaemon); ok {
116
+ err := pl.Start(iface)
117
+ if err != nil {
118
+ closePlugins(loader.plugins[i:])
119
+ return err
120
+ }
121
+ }
122
+ }
123
+ return nil
124
+}
125
+
126
+// StopDaemon stops all long-running plugins.
127
+func (loader *PluginLoader) Close() error {
128
+ return closePlugins(loader.plugins)
129
+}
130
+
131
+func closePlugins(plugins []plugin.Plugin) error {
132
+ var errs []string
133
+ for _, pl := range plugins {
134
+ if pl, ok := pl.(plugin.PluginDaemon); ok {
135
+ err := pl.Close()
136
+ if err != nil {
137
+ errs = append(errs, fmt.Sprintf(
138
+ "error closing plugin %s: %s",
139
+ pl.Name(),
140
+ err.Error(),
141
+ ))
142
+ }
143
+ }
144
+ }
145
+ if errs != nil {
146
+ return fmt.Errorf(strings.Join(errs, "\n"))
147
+ }
148
+ return nil
149
+}
150
+
151
func injectDatastorePlugin(pl plugin.PluginDatastore) error {
152
return fsrepo.AddDatastoreConfigHandler(pl.DatastoreTypeName(), pl.DatastoreConfigParser())
153
}