summaryrefslogtreecommitdiff
path: root/docs/beep-beep/plugin.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/beep-beep/plugin.md')
-rw-r--r--docs/beep-beep/plugin.md246
1 files changed, 0 insertions, 246 deletions
diff --git a/docs/beep-beep/plugin.md b/docs/beep-beep/plugin.md
deleted file mode 100644
index 7d5adf69..00000000
--- a/docs/beep-beep/plugin.md
+++ /dev/null
@@ -1,246 +0,0 @@
-# Writing Plugins
-
-RoadRunner uses Endure container to manage dependencies. This approach is similar to the PHP Container implementation
-with automatic method injection. You can create your own plugins, event listeners, middlewares, etc.
-
-To define your plugin, create a struct with public `Init` method with error return value (you can use `spiral/errors` as
-the `error` package):
-
-```golang
-package custom
-
-const PluginName = "custom"
-
-type Plugin struct{}
-
-func (s *Plugin) Init() error {
- return nil
-}
-```
-
-You can register your plugin by creating a custom version of `main.go` file and [building it](/beep-beep/build.md).
-
-### Dependencies
-
-You can access other RoadRunner plugins by requesting dependencies in your `Init` method:
-
-```golang
-package custom
-
-import (
- "github.com/spiral/roadrunner/v2/plugins/http"
- "github.com/spiral/roadrunner/v2/plugins/rpc"
-)
-
-type Service struct {}
-
-func (s *Service) Init(r *rpc.Plugin, rr *http.Plugin) error {
- return nil
-}
-```
-
-> Make sure to request dependency as pointer.
-
-### Configuration
-
-In most of the cases, your services would require a set of configuration values. RoadRunner can automatically populate
-and validate your configuration structure using `config` plugin (via an interface):
-
-Config sample:
-
-```yaml
-custom:
- address: tcp://localhost:8888
-```
-
-Plugin:
-
-```golang
-package custom
-
-import (
- "github.com/spiral/roadrunner/v2/plugins/config"
- "github.com/spiral/roadrunner/v2/plugins/http"
- "github.com/spiral/roadrunner/v2/plugins/rpc"
-
- "github.com/spiral/errors"
-)
-
-const PluginName = "custom"
-
-type Config struct{
- Address string `mapstructure:"address"`
-}
-
-type Plugin struct {
- cfg *Config
-}
-
-// You can also initialize some defaults values for config keys
-func (cfg *Config) InitDefaults() {
- if cfg.Address == "" {
- cfg.Address = "tcp://localhost:8088"
- }
-}
-
-func (s *Plugin) Init(r *rpc.Plugin, h *http.Plugin, cfg config.Configurer) error {
- const op = errors.Op("custom_plugin_init") // error operation name
- if !cfg.Has(PluginName) {
- return errors.E(op, errors.Disabled)
- }
-
- // unmarshall
- err := cfg.UnmarshalKey(PluginName, &s.cfg)
- if err != nil {
- // Error will stop execution
- return errors.E(op, err)
- }
-
- // Init defaults
- s.cfg.InitDefaults()
-
- return nil
-}
-
-```
-
-`errors.Disabled` is the special kind of error which indicated Endure to disable this plugin and all dependencies of
-this root. The RR2 will continue to work after this error type if at least plugin stay alive.
-
-### Serving
-
-Create `Serve` and `Stop` method in your structure to let RoadRunner start and stop your service.
-
-```golang
-type Plugin struct {}
-
-func (s *Plugin) Serve() chan error {
- const op = errors.Op("custom_plugin_serve")
- errCh := make(chan error, 1)
-
- err := s.DoSomeWork()
- err != nil {
- errCh <- errors.E(op, err)
- return errCh
- }
-
- return nil
-}
-
-func (s *Plugin) Stop() error {
- return s.stopServing()
-}
-
-func (s *Plugin) DoSomeWork() error {
- return nil
-}
-```
-
-`Serve` method is thread-safe. It runs in the separate goroutine which managed by the `Endure` container. The one note, is that you should unblock it when call `Stop` on the container. Otherwise, service will be killed after timeout (can be set in Endure).
-
-### Collecting dependencies in runtime
-
-RR2 provide a way to collect dependencies in runtime via `Collects` interface. This is very useful for the middlewares or extending plugins with additional functionality w/o changing it.
-Let's create an HTTP middleware:
-
-Steps (sample based on the actual `http` plugin and `Middleware` interface):
-
-1. Declare a required interface
-
-```go
-// Middleware interface
-type Middleware interface {
- Middleware(f http.Handler) http.HandlerFunc
-}
-```
-
-2. Implement method, which should have as an arguments name (`endure.Named` interface) and `Middleware` (step 1).
-
-```go
-// Collects collecting http middlewares
-func (s *Plugin) AddMiddleware(name endure.Named, m Middleware) {
- s.mdwr[name.Name()] = m
-}
-```
-
-3. Implement `Collects` endure interface for the required structure and return implemented on the step 2 method.
-
-```golang
-// Collects collecting http middlewares
-func (s *Plugin) Collects() []interface{} {
- return []interface{}{
- s.AddMiddleware,
- }
-}
-```
-
-Endure will automatically check that registered structure implement all the arguments for the `AddMiddleware` method (or will find a structure if argument is structure). In our case, a structure should implement `endure.Named` interface (which returns user friendly name for the plugin) and `Middleware` interface.
-
-### RPC Methods
-
-You can expose a set of RPC methods for your PHP workers also by using Endure `Collects` interface. Endure will automatically get the structure and expose RPC method under the `PluginName` name.
-
-To extend your plugin with RPC methods, plugin will not be changed at all. Only 1 thing to do is to create a file with RPC methods (let's call it `rpc.go`) and expose here all RPC methods for the plugin w/o changing plugin itself:
-Sample based on the `informer` plugin:
-
-I assume we created a file `rpc.go`. The next step is to create a structure:
-
-1. Create a structure: (logger is optional)
-
-```golang
-package custom
-
-type rpc struct {
- srv *Plugin
- log logger.Logger
-}
-```
-
-2. Create a method, which you want to expose:
-
-```go
-func (s *rpc) Hello(input string, output *string) error {
- *output = input
- return nil
-}
-```
-
-3. Use `Collects` interface to expose the RPC service to Endure:
-
-```go
-// CollectTarget resettable service.
-func (p *Plugin) CollectTarget(name endure.Named, r Informer) error {
- p.registry[name.Name()] = r
- return nil
-}
-
-// Collects declares services to be collected.
-func (p *Plugin) Collects() []interface{} {
- return []interface{}{
- p.CollectTarget,
- }
-}
-
-// Name of the service.
-func (p *Plugin) Name() string {
- return PluginName
-}
-
-// RPCService returns associated rpc service.
-func (p *Plugin) RPC() interface{} {
- return &rpc{srv: p, log: p.log}
-}
-```
-
-Let's take a look at these methods:
-
-1. `CollectTarget`: tells Endure, that we want to collect all plugins which implement `endure.Named` and `Informer` interfaces.
-2. `Collects`: Endure interface implementation.
-3. `Name`: `endure.Named` interface implementation which return a user-friendly plugin name.
-4. `RPC`: RPC plugin Collects all plugins which implement `RPC` interface and `endure.Named`. RPC interface accepts no arguments, but returns interface (plugin).
-
-To use it within PHP using `RPC` [instance](/beep-beep/rpc.md):
-
-```php
-var_dump($rpc->call('custom.Hello', 'world'));
-```