summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorWolfy-J <[email protected]>2018-09-10 16:42:15 +0400
committerGitHub <[email protected]>2018-09-10 16:42:15 +0400
commita554a98dda0d793da09db17314ef3977a2f3a465 (patch)
tree64b506898d283c39babc48da5a29df203cb57b49 /service
parentea97c188a4a74c00b585cb50fa1ed4db7d190e09 (diff)
parent46a06a4d104802fb4271e06da487f74f23edd10c (diff)
Merge pull request #33 from spiral/feature/env-setterv1.2.0
Feature/env setter
Diffstat (limited to 'service')
-rw-r--r--service/container.go11
-rw-r--r--service/env/environment.go (renamed from service/env/provider.go)5
-rw-r--r--service/env/service.go23
-rw-r--r--service/env/service_test.go27
-rw-r--r--service/http/config.go24
-rw-r--r--service/http/handler_test.go58
-rw-r--r--service/http/rpc.go4
-rw-r--r--service/http/rpc_test.go7
-rw-r--r--service/http/service.go4
-rw-r--r--service/http/service_test.go4
-rw-r--r--service/rpc/service.go17
-rw-r--r--service/rpc/service_test.go10
-rw-r--r--service/static/config.go8
13 files changed, 157 insertions, 45 deletions
diff --git a/service/container.go b/service/container.go
index 3450a18c..861e1aac 100644
--- a/service/container.go
+++ b/service/container.go
@@ -133,7 +133,7 @@ func (c *container) Init(cfg Config) error {
if ok, err := c.initService(e.svc, cfg.Get(e.name)); err != nil {
// soft error (skipping)
if err == errNoConfig {
- c.log.Warningf("[%s]: no config has been provided", e.name)
+ c.log.Debugf("[%s]: no config has been provided", e.name)
continue
}
@@ -152,7 +152,7 @@ func (c *container) Init(cfg Config) error {
// Serve all configured services. Non blocking.
func (c *container) Serve() error {
var (
- numServing int
+ numServing = 0
done = make(chan interface{}, len(c.services))
)
@@ -213,7 +213,7 @@ func (c *container) Stop() {
func (c *container) initService(s interface{}, segment Config) (bool, error) {
r := reflect.TypeOf(s)
- m, ok := r.MethodByName("Init")
+ m, ok := r.MethodByName(InitMethod)
if !ok {
// no Init method is presented, assuming service does not need initialization.
return true, nil
@@ -251,6 +251,11 @@ func (c *container) resolveValues(s interface{}, m reflect.Method, cfg Config) (
case v.Implements(reflect.TypeOf((*Container)(nil)).Elem()): // container
values = append(values, reflect.ValueOf(c))
+ case v.Implements(reflect.TypeOf((*logrus.StdLogger)(nil)).Elem()),
+ v.Implements(reflect.TypeOf((*logrus.FieldLogger)(nil)).Elem()),
+ v.ConvertibleTo(reflect.ValueOf(c.log).Type()): // logger
+ values = append(values, reflect.ValueOf(c.log))
+
case v.Implements(reflect.TypeOf((*HydrateConfig)(nil)).Elem()): // injectable config
if cfg == nil {
return nil, errNoConfig
diff --git a/service/env/provider.go b/service/env/environment.go
index 2918f18c..8e89d2c8 100644
--- a/service/env/provider.go
+++ b/service/env/environment.go
@@ -2,7 +2,10 @@ package env
// Provider aggregates list of environment variables. This interface can be used in custom implementation to drive
// values from external sources.
-type Provider interface {
+type Environment interface {
// GetEnv must return list of env variables.
GetEnv() (map[string]string, error)
+
+ // SetEnv sets or creates environment value.
+ SetEnv(key, value string)
}
diff --git a/service/env/service.go b/service/env/service.go
index 0822d55a..41e70bee 100644
--- a/service/env/service.go
+++ b/service/env/service.go
@@ -1,7 +1,12 @@
package env
-// ID contains default svc name.
-const ID = "env"
+const (
+ // ID contains default service name.
+ ID = "env"
+
+ // rrKey contains default env key to indicate than php running in RR mode.
+ rrKey = "rr"
+)
// Service provides ability to map _ENV values from config file.
type Service struct {
@@ -12,16 +17,17 @@ type Service struct {
// NewService creates new env service instance for given rr version.
func NewService(defaults map[string]string) *Service {
s := &Service{values: defaults}
- if s.values == nil {
- s.values = make(map[string]string)
- }
-
return s
}
// Init must return configure svc and return true if svc hasStatus enabled. Must return error in case of
// misconfiguration. Services must not be used without proper configuration pushed first.
func (s *Service) Init(cfg *Config) (bool, error) {
+ if s.values == nil {
+ s.values = make(map[string]string)
+ s.values[rrKey] = "yes"
+ }
+
for k, v := range cfg.Values {
s.values[k] = v
}
@@ -33,3 +39,8 @@ func (s *Service) Init(cfg *Config) (bool, error) {
func (s *Service) GetEnv() (map[string]string, error) {
return s.values, nil
}
+
+// SetEnv sets or creates environment value.
+func (s *Service) SetEnv(key, value string) {
+ s.values[key] = value
+}
diff --git a/service/env/service_test.go b/service/env/service_test.go
index 69a2a375..28e0d15b 100644
--- a/service/env/service_test.go
+++ b/service/env/service_test.go
@@ -10,6 +10,16 @@ func Test_NewService(t *testing.T) {
assert.Len(t, s.values, 1)
}
+func Test_Init(t *testing.T) {
+ s := &Service{}
+ s.Init(&Config{})
+ assert.Len(t, s.values, 1)
+
+ values, err := s.GetEnv()
+ assert.NoError(t, err)
+ assert.Equal(t, "yes", values["rr"])
+}
+
func Test_Extend(t *testing.T) {
s := NewService(map[string]string{"rr": "version"})
@@ -22,3 +32,20 @@ func Test_Extend(t *testing.T) {
assert.Equal(t, "version", values["rr"])
assert.Equal(t, "value", values["key"])
}
+
+func Test_Set(t *testing.T) {
+ s := NewService(map[string]string{"rr": "version"})
+
+ s.Init(&Config{Values: map[string]string{"key": "value"}})
+ assert.Len(t, s.values, 2)
+
+ s.SetEnv("key", "value-new")
+ s.SetEnv("other", "new")
+
+ values, err := s.GetEnv()
+ assert.NoError(t, err)
+ assert.Len(t, values, 3)
+ assert.Equal(t, "version", values["rr"])
+ assert.Equal(t, "value-new", values["key"])
+ assert.Equal(t, "new", values["other"])
+}
diff --git a/service/http/config.go b/service/http/config.go
index 20a247fb..5be42ae6 100644
--- a/service/http/config.go
+++ b/service/http/config.go
@@ -5,12 +5,11 @@ import (
"github.com/spiral/roadrunner"
"github.com/spiral/roadrunner/service"
"strings"
- "time"
)
// Config configures RoadRunner HTTP server.
type Config struct {
- // Enable enables http svc.
+ // Enable enables http service.
Enable bool
// Address and port to handle as http server.
@@ -32,25 +31,16 @@ func (c *Config) Hydrate(cfg service.Config) error {
return err
}
- if err := c.Valid(); err != nil {
- return err
+ if !c.Enable {
+ return nil
}
- if c.Workers.Relay == "" {
- c.Workers.Relay = "pipes"
- }
-
- if c.Workers.RelayTimeout < time.Microsecond {
- c.Workers.RelayTimeout = time.Second * time.Duration(c.Workers.RelayTimeout.Nanoseconds())
- }
-
- if c.Workers.Pool.AllocateTimeout < time.Microsecond {
- c.Workers.Pool.AllocateTimeout = time.Second * time.Duration(c.Workers.Pool.AllocateTimeout.Nanoseconds())
+ if err := c.Valid(); err != nil {
+ return err
}
- if c.Workers.Pool.DestroyTimeout < time.Microsecond {
- c.Workers.Pool.DestroyTimeout = time.Second * time.Duration(c.Workers.Pool.DestroyTimeout.Nanoseconds())
- }
+ c.Workers.SetDefaults()
+ c.Workers.UpscaleDurations()
return nil
}
diff --git a/service/http/handler_test.go b/service/http/handler_test.go
index 59a4c7c0..b82fc938 100644
--- a/service/http/handler_test.go
+++ b/service/http/handler_test.go
@@ -14,6 +14,7 @@ import (
"strings"
"testing"
"time"
+ "net/http/httptest"
)
// get request and return body
@@ -63,6 +64,63 @@ func TestServer_Echo(t *testing.T) {
assert.Equal(t, "WORLD", body)
}
+func Test_HandlerErrors(t *testing.T) {
+ st := &Handler{
+ cfg: &Config{
+ MaxRequest: 1024,
+ Uploads: &UploadsConfig{
+ Dir: os.TempDir(),
+ Forbid: []string{},
+ },
+ },
+ rr: roadrunner.NewServer(&roadrunner.ServerConfig{
+ Command: "php ../../php-src/tests/http/client.php echo pipes",
+ Relay: "pipes",
+ Pool: &roadrunner.Config{
+ NumWorkers: 1,
+ AllocateTimeout: 10000000,
+ DestroyTimeout: 10000000,
+ },
+ }),
+ }
+
+ wr := httptest.NewRecorder()
+ rq := httptest.NewRequest("POST", "/", bytes.NewBuffer([]byte("data")))
+
+ st.ServeHTTP(wr, rq)
+ assert.Equal(t, 500, wr.Code)
+}
+
+func Test_Handler_JSON_error(t *testing.T) {
+ st := &Handler{
+ cfg: &Config{
+ MaxRequest: 1024,
+ Uploads: &UploadsConfig{
+ Dir: os.TempDir(),
+ Forbid: []string{},
+ },
+ },
+ rr: roadrunner.NewServer(&roadrunner.ServerConfig{
+ Command: "php ../../php-src/tests/http/client.php echo pipes",
+ Relay: "pipes",
+ Pool: &roadrunner.Config{
+ NumWorkers: 1,
+ AllocateTimeout: 10000000,
+ DestroyTimeout: 10000000,
+ },
+ }),
+ }
+
+ wr := httptest.NewRecorder()
+ rq := httptest.NewRequest("POST", "/", bytes.NewBuffer([]byte("{sd")))
+ rq.Header.Add("Content-Type","application/json")
+ rq.Header.Add("Content-Size","3")
+
+ st.ServeHTTP(wr, rq)
+ assert.Equal(t, 500, wr.Code)
+}
+
+
func TestServer_Headers(t *testing.T) {
st := &Handler{
cfg: &Config{
diff --git a/service/http/rpc.go b/service/http/rpc.go
index aebc5903..9dfe718e 100644
--- a/service/http/rpc.go
+++ b/service/http/rpc.go
@@ -29,7 +29,7 @@ type Worker struct {
// Reset resets underlying RR worker pool and restarts all of it's workers.
func (rpc *rpcServer) Reset(reset bool, r *string) error {
- if rpc.svc.srv == nil {
+ if rpc.svc == nil || rpc.svc.srv == nil {
return errors.New("http server is not running")
}
@@ -39,7 +39,7 @@ func (rpc *rpcServer) Reset(reset bool, r *string) error {
// Workers returns list of active workers and their stats.
func (rpc *rpcServer) Workers(list bool, r *WorkerList) error {
- if rpc.svc.srv == nil {
+ if rpc.svc == nil || rpc.svc.srv == nil {
return errors.New("http server is not running")
}
diff --git a/service/http/rpc_test.go b/service/http/rpc_test.go
index c392b060..32bb776c 100644
--- a/service/http/rpc_test.go
+++ b/service/http/rpc_test.go
@@ -177,3 +177,10 @@ func Test_Workers(t *testing.T) {
assert.Equal(t, *ss.rr.Workers()[0].Pid, r.Workers[0].Pid)
}
+
+func Test_Errors(t *testing.T) {
+ r := &rpcServer{nil}
+
+ assert.Error(t, r.Reset(true, nil))
+ assert.Error(t, r.Workers(true, nil))
+}
diff --git a/service/http/service.go b/service/http/service.go
index 9f62f5af..f988a843 100644
--- a/service/http/service.go
+++ b/service/http/service.go
@@ -20,7 +20,7 @@ type middleware func(f http.HandlerFunc) http.HandlerFunc
// Service manages rr, http servers.
type Service struct {
cfg *Config
- env env.Provider
+ env env.Environment
lsns []func(event int, ctx interface{})
mdws []middleware
mu sync.Mutex
@@ -42,7 +42,7 @@ func (s *Service) AddListener(l func(event int, ctx interface{})) {
// Init must return configure svc and return true if svc hasStatus enabled. Must return error in case of
// misconfiguration. Services must not be used without proper configuration pushed first.
-func (s *Service) Init(cfg *Config, r *rpc.Service, e env.Provider) (bool, error) {
+func (s *Service) Init(cfg *Config, r *rpc.Service, e env.Environment) (bool, error) {
if !cfg.Enable {
return false, nil
}
diff --git a/service/http/service_test.go b/service/http/service_test.go
index 4e572335..8dab7cd4 100644
--- a/service/http/service_test.go
+++ b/service/http/service_test.go
@@ -6,6 +6,7 @@ import (
"github.com/sirupsen/logrus/hooks/test"
"github.com/spiral/roadrunner"
"github.com/spiral/roadrunner/service"
+ "github.com/spiral/roadrunner/service/env"
"github.com/spiral/roadrunner/service/rpc"
"github.com/stretchr/testify/assert"
"io/ioutil"
@@ -13,7 +14,6 @@ import (
"os"
"testing"
"time"
- "github.com/spiral/roadrunner/service/env"
)
type testCfg struct {
@@ -49,7 +49,7 @@ func Test_Service_NoConfig(t *testing.T) {
c := service.NewContainer(logger)
c.Register(ID, &Service{})
- assert.Error(t, c.Init(&testCfg{httpCfg: `{}`}))
+ assert.Error(t, c.Init(&testCfg{httpCfg: `{"Enable":true}`}))
s, st := c.Get(ID)
assert.NotNil(t, s)
diff --git a/service/rpc/service.go b/service/rpc/service.go
index 6e231048..3ea6c5fc 100644
--- a/service/rpc/service.go
+++ b/service/rpc/service.go
@@ -3,12 +3,19 @@ package rpc
import (
"errors"
"github.com/spiral/goridge"
+ "github.com/spiral/roadrunner/service/env"
"net/rpc"
"sync"
)
-// ID contains default service name.
-const ID = "rpc"
+const (
+ // ID contains default service name.
+ ID = "rpc"
+
+ // rrKey defines environment key to be used to store information about
+ // rpc server connection.
+ envKey = "rr_rpc"
+)
// Service is RPC service.
type Service struct {
@@ -20,7 +27,7 @@ type Service struct {
}
// Init rpc service. Must return true if service is enabled.
-func (s *Service) Init(cfg *Config) (bool, error) {
+func (s *Service) Init(cfg *Config, env env.Environment) (bool, error) {
if !cfg.Enable {
return false, nil
}
@@ -28,6 +35,10 @@ func (s *Service) Init(cfg *Config) (bool, error) {
s.cfg = cfg
s.rpc = rpc.NewServer()
+ if env != nil {
+ env.SetEnv(envKey, cfg.Listen)
+ }
+
return true, nil
}
diff --git a/service/rpc/service_test.go b/service/rpc/service_test.go
index fc88d38d..59e0e05d 100644
--- a/service/rpc/service_test.go
+++ b/service/rpc/service_test.go
@@ -12,7 +12,7 @@ func (ts *testService) Echo(msg string, r *string) error { *r = msg; return nil
func Test_Disabled(t *testing.T) {
s := &Service{}
- ok, err := s.Init(&Config{Enable: false})
+ ok, err := s.Init(&Config{Enable: false}, nil)
assert.NoError(t, err)
assert.False(t, ok)
@@ -30,7 +30,7 @@ func Test_RegisterNotConfigured(t *testing.T) {
func Test_Enabled(t *testing.T) {
s := &Service{}
- ok, err := s.Init(&Config{Enable: true, Listen: "tcp://localhost:9008"})
+ ok, err := s.Init(&Config{Enable: true, Listen: "tcp://localhost:9008"}, nil)
assert.NoError(t, err)
assert.True(t, ok)
@@ -38,7 +38,7 @@ func Test_Enabled(t *testing.T) {
func Test_StopNonServing(t *testing.T) {
s := &Service{}
- ok, err := s.Init(&Config{Enable: true, Listen: "tcp://localhost:9008"})
+ ok, err := s.Init(&Config{Enable: true, Listen: "tcp://localhost:9008"}, nil)
assert.NoError(t, err)
assert.True(t, ok)
@@ -47,7 +47,7 @@ func Test_StopNonServing(t *testing.T) {
func Test_Serve_Errors(t *testing.T) {
s := &Service{}
- ok, err := s.Init(&Config{Enable: true, Listen: "mailformed"})
+ ok, err := s.Init(&Config{Enable: true, Listen: "mailformed"}, nil)
assert.NoError(t, err)
assert.True(t, ok)
@@ -60,7 +60,7 @@ func Test_Serve_Errors(t *testing.T) {
func Test_Serve_Client(t *testing.T) {
s := &Service{}
- ok, err := s.Init(&Config{Enable: true, Listen: "tcp://localhost:9018"})
+ ok, err := s.Init(&Config{Enable: true, Listen: "tcp://localhost:9018"}, nil)
assert.NoError(t, err)
assert.True(t, ok)
diff --git a/service/static/config.go b/service/static/config.go
index a6931907..be0ac3ed 100644
--- a/service/static/config.go
+++ b/service/static/config.go
@@ -1,7 +1,7 @@
package static
import (
- "github.com/pkg/errors"
+ "fmt"
"github.com/spiral/roadrunner/service"
"os"
"path"
@@ -35,18 +35,18 @@ func (c *Config) Valid() error {
if !c.Enable {
return nil
}
-
+
st, err := os.Stat(c.Dir)
if err != nil {
if os.IsNotExist(err) {
- return errors.New("root directory does not exists")
+ return fmt.Errorf("root directory '%s' does not exists", c.Dir)
}
return err
}
if !st.IsDir() {
- return errors.New("invalid root directory")
+ return fmt.Errorf("invalid root directory '%s'", c.Dir)
}
return nil