summaryrefslogtreecommitdiff
path: root/transport
diff options
context:
space:
mode:
authorValery Piashchynski <[email protected]>2022-01-12 00:19:48 +0300
committerValery Piashchynski <[email protected]>2022-01-12 00:19:48 +0300
commit215c7c91937bf65704db18a59a327a3c64e43530 (patch)
tree85d2b32ddf7230064e620bb59f76ef4bfd6b24cf /transport
parent7b5d220f0f1be155d83d887cd4996bdf4394c570 (diff)
pass logger from the factory
Signed-off-by: Valery Piashchynski <[email protected]>
Diffstat (limited to 'transport')
-rw-r--r--transport/interface.go20
-rwxr-xr-xtransport/pipe/pipe_factory.go173
-rw-r--r--transport/pipe/pipe_factory_spawn_test.go427
-rwxr-xr-xtransport/pipe/pipe_factory_test.go511
-rwxr-xr-xtransport/socket/socket_factory.go248
-rw-r--r--transport/socket/socket_factory_spawn_test.go482
-rwxr-xr-xtransport/socket/socket_factory_test.go609
7 files changed, 0 insertions, 2470 deletions
diff --git a/transport/interface.go b/transport/interface.go
deleted file mode 100644
index 0d6c8e8b..00000000
--- a/transport/interface.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package transport
-
-import (
- "context"
- "os/exec"
-
- "github.com/spiral/roadrunner/v2/worker"
-)
-
-// Factory is responsible for wrapping given command into tasks WorkerProcess.
-type Factory interface {
- // SpawnWorkerWithTimeout creates new WorkerProcess process based on given command with context.
- // Process must not be started.
- SpawnWorkerWithTimeout(context.Context, *exec.Cmd) (*worker.Process, error)
- // SpawnWorker creates new WorkerProcess process based on given command.
- // Process must not be started.
- SpawnWorker(*exec.Cmd) (*worker.Process, error)
- // Close the factory and underlying connections.
- Close() error
-}
diff --git a/transport/pipe/pipe_factory.go b/transport/pipe/pipe_factory.go
deleted file mode 100755
index c70b3f65..00000000
--- a/transport/pipe/pipe_factory.go
+++ /dev/null
@@ -1,173 +0,0 @@
-package pipe
-
-import (
- "context"
- "os/exec"
-
- "github.com/spiral/goridge/v3/pkg/pipe"
- "github.com/spiral/roadrunner/v2/internal"
- "github.com/spiral/roadrunner/v2/worker"
-)
-
-// Factory connects to stack using standard
-// streams (STDIN, STDOUT pipes).
-type Factory struct{}
-
-// NewPipeFactory returns new factory instance and starts
-// listening
-func NewPipeFactory() *Factory {
- return &Factory{}
-}
-
-type sr struct {
- w *worker.Process
- err error
-}
-
-// SpawnWorkerWithTimeout creates new Process and connects it to goridge relay,
-// method Wait() must be handled on level above.
-func (f *Factory) SpawnWorkerWithTimeout(ctx context.Context, cmd *exec.Cmd) (*worker.Process, error) {
- spCh := make(chan sr)
- go func() {
- w, err := worker.InitBaseWorker(cmd)
- if err != nil {
- select {
- case spCh <- sr{
- w: nil,
- err: err,
- }:
- return
- default:
- return
- }
- }
-
- in, err := cmd.StdoutPipe()
- if err != nil {
- select {
- case spCh <- sr{
- w: nil,
- err: err,
- }:
- return
- default:
- return
- }
- }
-
- out, err := cmd.StdinPipe()
- if err != nil {
- select {
- case spCh <- sr{
- w: nil,
- err: err,
- }:
- return
- default:
- return
- }
- }
-
- // Init new PIPE relay
- relay := pipe.NewPipeRelay(in, out)
- w.AttachRelay(relay)
-
- // Start the worker
- err = w.Start()
- if err != nil {
- select {
- case spCh <- sr{
- w: nil,
- err: err,
- }:
- return
- default:
- return
- }
- }
-
- // used as a ping
- _, err = internal.Pid(relay)
- if err != nil {
- _ = w.Kill()
- select {
- case spCh <- sr{
- w: nil,
- err: err,
- }:
- return
- default:
- _ = w.Kill()
- return
- }
- }
-
- select {
- case
- // return worker
- spCh <- sr{
- w: w,
- err: nil,
- }:
- // everything ok, set ready state
- w.State().Set(worker.StateReady)
- return
- default:
- _ = w.Kill()
- return
- }
- }()
-
- select {
- case <-ctx.Done():
- return nil, ctx.Err()
- case res := <-spCh:
- if res.err != nil {
- return nil, res.err
- }
- return res.w, nil
- }
-}
-
-func (f *Factory) SpawnWorker(cmd *exec.Cmd) (*worker.Process, error) {
- w, err := worker.InitBaseWorker(cmd)
- if err != nil {
- return nil, err
- }
-
- in, err := cmd.StdoutPipe()
- if err != nil {
- return nil, err
- }
-
- out, err := cmd.StdinPipe()
- if err != nil {
- return nil, err
- }
-
- // Init new PIPE relay
- relay := pipe.NewPipeRelay(in, out)
- w.AttachRelay(relay)
-
- // Start the worker
- err = w.Start()
- if err != nil {
- return nil, err
- }
-
- // errors bundle
- _, err = internal.Pid(relay)
- if err != nil {
- _ = w.Kill()
- return nil, err
- }
-
- // everything ok, set ready state
- w.State().Set(worker.StateReady)
- return w, nil
-}
-
-// Close the factory.
-func (f *Factory) Close() error {
- return nil
-}
diff --git a/transport/pipe/pipe_factory_spawn_test.go b/transport/pipe/pipe_factory_spawn_test.go
deleted file mode 100644
index 9aa12564..00000000
--- a/transport/pipe/pipe_factory_spawn_test.go
+++ /dev/null
@@ -1,427 +0,0 @@
-package pipe
-
-import (
- "os/exec"
- "sync"
- "testing"
- "time"
-
- "github.com/spiral/errors"
- "github.com/spiral/roadrunner/v2/payload"
- "github.com/spiral/roadrunner/v2/worker"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-)
-
-func Test_GetState2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, err := NewPipeFactory().SpawnWorker(cmd)
- go func() {
- assert.NoError(t, w.Wait())
- assert.Equal(t, worker.StateStopped, w.State().Value())
- }()
-
- assert.NoError(t, err)
- assert.NotNil(t, w)
-
- assert.Equal(t, worker.StateReady, w.State().Value())
- assert.NoError(t, w.Stop())
-}
-
-func Test_Kill2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, err := NewPipeFactory().SpawnWorker(cmd)
- wg := &sync.WaitGroup{}
- wg.Add(1)
- go func() {
- defer wg.Done()
- assert.Error(t, w.Wait())
- assert.Equal(t, worker.StateErrored, w.State().Value())
- }()
-
- assert.NoError(t, err)
- assert.NotNil(t, w)
-
- assert.Equal(t, worker.StateReady, w.State().Value())
- err = w.Kill()
- if err != nil {
- t.Errorf("error killing the Process: error %v", err)
- }
- wg.Wait()
-}
-
-func Test_Pipe_Start2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, err := NewPipeFactory().SpawnWorker(cmd)
- assert.NoError(t, err)
- assert.NotNil(t, w)
-
- go func() {
- assert.NoError(t, w.Wait())
- }()
-
- assert.NoError(t, w.Stop())
-}
-
-func Test_Pipe_StartError2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- err := cmd.Start()
- if err != nil {
- t.Errorf("error running the command: error %v", err)
- }
-
- w, err := NewPipeFactory().SpawnWorker(cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Pipe_PipeError3(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- _, err := cmd.StdinPipe()
- if err != nil {
- t.Errorf("error creating the STDIN pipe: error %v", err)
- }
-
- w, err := NewPipeFactory().SpawnWorker(cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Pipe_PipeError4(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- _, err := cmd.StdinPipe()
- if err != nil {
- t.Errorf("error creating the STDIN pipe: error %v", err)
- }
-
- w, err := NewPipeFactory().SpawnWorker(cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Pipe_Failboot2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/failboot.php")
- w, err := NewPipeFactory().SpawnWorker(cmd)
- assert.Nil(t, w)
- assert.Error(t, err)
-}
-
-func Test_Pipe_Invalid2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/invalid.php")
- w, err := NewPipeFactory().SpawnWorker(cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Pipe_Echo2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- w, err := NewPipeFactory().SpawnWorker(cmd)
- assert.NoError(t, err)
-
- sw := worker.From(w)
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
-
- assert.NoError(t, err)
- assert.NotNil(t, res)
- assert.NotNil(t, res.Body)
- assert.Empty(t, res.Context)
-
- go func() {
- if w.Wait() != nil {
- t.Fail()
- }
- }()
-
- assert.Equal(t, "hello", res.String())
- err = w.Stop()
- assert.NoError(t, err)
-}
-
-func Test_Pipe_Broken2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "broken", "pipes")
- w, err := NewPipeFactory().SpawnWorker(cmd)
- assert.NoError(t, err)
- require.NotNil(t, w)
-
- sw := worker.From(w)
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
- assert.Error(t, err)
- assert.Nil(t, res)
-
- time.Sleep(time.Second)
- err = w.Stop()
- assert.Error(t, err)
-}
-
-func Benchmark_Pipe_SpawnWorker_Stop2(b *testing.B) {
- f := NewPipeFactory()
- for n := 0; n < b.N; n++ {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- w, _ := f.SpawnWorker(cmd)
- go func() {
- if w.Wait() != nil {
- b.Fail()
- }
- }()
-
- err := w.Stop()
- if err != nil {
- b.Errorf("error stopping the worker: error %v", err)
- }
- }
-}
-
-func Benchmark_Pipe_Worker_ExecEcho2(b *testing.B) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, _ := NewPipeFactory().SpawnWorker(cmd)
- sw := worker.From(w)
-
- b.ReportAllocs()
- b.ResetTimer()
- go func() {
- err := w.Wait()
- if err != nil {
- b.Errorf("error waiting the worker: error %v", err)
- }
- }()
- defer func() {
- err := w.Stop()
- if err != nil {
- b.Errorf("error stopping the worker: error %v", err)
- }
- }()
-
- for n := 0; n < b.N; n++ {
- if _, err := sw.Exec(&payload.Payload{Body: []byte("hello")}); err != nil {
- b.Fail()
- }
- }
-}
-
-func Benchmark_Pipe_Worker_ExecEcho4(b *testing.B) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- w, err := NewPipeFactory().SpawnWorker(cmd)
- if err != nil {
- b.Fatal(err)
- }
-
- defer func() {
- err = w.Stop()
- if err != nil {
- b.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- for n := 0; n < b.N; n++ {
- if _, err := sw.Exec(&payload.Payload{Body: []byte("hello")}); err != nil {
- b.Fail()
- }
- }
-}
-
-func Benchmark_Pipe_Worker_ExecEchoWithoutContext2(b *testing.B) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- w, err := NewPipeFactory().SpawnWorker(cmd)
- if err != nil {
- b.Fatal(err)
- }
-
- defer func() {
- err = w.Stop()
- if err != nil {
- b.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- for n := 0; n < b.N; n++ {
- if _, err := sw.Exec(&payload.Payload{Body: []byte("hello")}); err != nil {
- b.Fail()
- }
- }
-}
-
-func Test_Echo2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, err := NewPipeFactory().SpawnWorker(cmd)
- if err != nil {
- t.Fatal(err)
- }
-
- sw := worker.From(w)
-
- go func() {
- assert.NoError(t, sw.Wait())
- }()
- defer func() {
- err = sw.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
-
- assert.Nil(t, err)
- assert.NotNil(t, res)
- assert.NotNil(t, res.Body)
- assert.Empty(t, res.Context)
-
- assert.Equal(t, "hello", res.String())
-}
-
-func Test_BadPayload2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, _ := NewPipeFactory().SpawnWorker(cmd)
-
- sw := worker.From(w)
-
- go func() {
- assert.NoError(t, sw.Wait())
- }()
- defer func() {
- err := sw.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- res, err := sw.Exec(&payload.Payload{})
- assert.Error(t, err)
- assert.Nil(t, res)
-
- assert.Contains(t, err.Error(), "payload can not be empty")
-}
-
-func Test_String2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, _ := NewPipeFactory().SpawnWorker(cmd)
- go func() {
- assert.NoError(t, w.Wait())
- }()
- defer func() {
- err := w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- assert.Contains(t, w.String(), "php ../../tests/client.php echo pipes")
- assert.Contains(t, w.String(), "ready")
- assert.Contains(t, w.String(), "num_execs: 0")
-}
-
-func Test_Echo_Slow2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/slow-client.php", "echo", "pipes", "10", "10")
-
- w, _ := NewPipeFactory().SpawnWorker(cmd)
- go func() {
- assert.NoError(t, w.Wait())
- }()
- defer func() {
- err := w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
-
- assert.Nil(t, err)
- assert.NotNil(t, res)
- assert.NotNil(t, res.Body)
- assert.Empty(t, res.Context)
-
- assert.Equal(t, "hello", res.String())
-}
-
-func Test_Broken2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "broken", "pipes")
-
- w, err := NewPipeFactory().SpawnWorker(cmd)
- if err != nil {
- t.Fatal(err)
- }
-
- sw := worker.From(w)
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
- assert.NotNil(t, err)
- assert.Nil(t, res)
-
- time.Sleep(time.Second * 3)
- assert.Error(t, w.Stop())
-}
-
-func Test_Error2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "error", "pipes")
-
- w, _ := NewPipeFactory().SpawnWorker(cmd)
- go func() {
- assert.NoError(t, w.Wait())
- }()
-
- defer func() {
- err := w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
- assert.NotNil(t, err)
- assert.Nil(t, res)
-
- if errors.Is(errors.SoftJob, err) == false {
- t.Fatal("error should be of type errors.ErrSoftJob")
- }
- assert.Contains(t, err.Error(), "hello")
-}
-
-func Test_NumExecs2(t *testing.T) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, _ := NewPipeFactory().SpawnWorker(cmd)
- go func() {
- assert.NoError(t, w.Wait())
- }()
- defer func() {
- err := w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- _, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
- if err != nil {
- t.Errorf("fail to execute payload: error %v", err)
- }
- assert.Equal(t, uint64(1), w.State().NumExecs())
-
- _, err = sw.Exec(&payload.Payload{Body: []byte("hello")})
- if err != nil {
- t.Errorf("fail to execute payload: error %v", err)
- }
- assert.Equal(t, uint64(2), w.State().NumExecs())
-
- _, err = sw.Exec(&payload.Payload{Body: []byte("hello")})
- if err != nil {
- t.Errorf("fail to execute payload: error %v", err)
- }
- assert.Equal(t, uint64(3), w.State().NumExecs())
-}
diff --git a/transport/pipe/pipe_factory_test.go b/transport/pipe/pipe_factory_test.go
deleted file mode 100755
index cbf1431a..00000000
--- a/transport/pipe/pipe_factory_test.go
+++ /dev/null
@@ -1,511 +0,0 @@
-package pipe
-
-import (
- "context"
- "os/exec"
- "sync"
- "testing"
- "time"
-
- "github.com/spiral/errors"
- "github.com/spiral/roadrunner/v2/payload"
- "github.com/spiral/roadrunner/v2/worker"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-)
-
-func Test_GetState(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- go func() {
- assert.NoError(t, w.Wait())
- assert.Equal(t, worker.StateStopped, w.State().Value())
- }()
-
- assert.NoError(t, err)
- assert.NotNil(t, w)
-
- assert.Equal(t, worker.StateReady, w.State().Value())
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
-}
-
-func Test_Kill(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- wg := &sync.WaitGroup{}
- wg.Add(1)
- go func() {
- defer wg.Done()
- assert.Error(t, w.Wait())
- assert.Equal(t, worker.StateErrored, w.State().Value())
- }()
-
- assert.NoError(t, err)
- assert.NotNil(t, w)
-
- assert.Equal(t, worker.StateReady, w.State().Value())
- err = w.Kill()
- if err != nil {
- t.Errorf("error killing the Process: error %v", err)
- }
- wg.Wait()
-}
-
-func Test_Pipe_Start(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- assert.NoError(t, err)
- assert.NotNil(t, w)
-
- go func() {
- assert.NoError(t, w.Wait())
- }()
-
- assert.NoError(t, w.Stop())
-}
-
-func Test_Pipe_StartError(t *testing.T) {
- t.Parallel()
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- err := cmd.Start()
- if err != nil {
- t.Errorf("error running the command: error %v", err)
- }
-
- ctx := context.Background()
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Pipe_PipeError(t *testing.T) {
- t.Parallel()
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- _, err := cmd.StdinPipe()
- if err != nil {
- t.Errorf("error creating the STDIN pipe: error %v", err)
- }
-
- ctx := context.Background()
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Pipe_PipeError2(t *testing.T) {
- t.Parallel()
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- // error cause
- _, err := cmd.StdinPipe()
- if err != nil {
- t.Errorf("error creating the STDIN pipe: error %v", err)
- }
-
- ctx := context.Background()
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Pipe_Failboot(t *testing.T) {
- cmd := exec.Command("php", "../../tests/failboot.php")
- ctx := context.Background()
-
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
-
- assert.Nil(t, w)
- assert.Error(t, err)
-}
-
-func Test_Pipe_Invalid(t *testing.T) {
- t.Parallel()
- cmd := exec.Command("php", "../../tests/invalid.php")
- ctx := context.Background()
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Pipe_Echo(t *testing.T) {
- t.Parallel()
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- ctx := context.Background()
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- if err != nil {
- t.Fatal(err)
- }
-
- defer func() {
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
- assert.NoError(t, err)
- assert.NotNil(t, res)
- assert.NotNil(t, res.Body)
- assert.Empty(t, res.Context)
-
- go func() {
- if w.Wait() != nil {
- t.Fail()
- }
- }()
-
- assert.Equal(t, "hello", res.String())
-}
-
-func Test_Pipe_Echo_Script(t *testing.T) {
- t.Parallel()
- cmd := exec.Command("sh", "../../tests/pipes_test_script.sh")
- ctx := context.Background()
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- if err != nil {
- t.Fatal(err)
- }
- defer func() {
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
- assert.NoError(t, err)
- assert.NotNil(t, res)
- assert.NotNil(t, res.Body)
- assert.Empty(t, res.Context)
-
- go func() {
- if w.Wait() != nil {
- t.Fail()
- }
- }()
-
- assert.Equal(t, "hello", res.String())
-}
-
-func Test_Pipe_Broken(t *testing.T) {
- t.Parallel()
- cmd := exec.Command("php", "../../tests/client.php", "broken", "pipes")
- ctx := context.Background()
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- require.NoError(t, err)
- require.NotNil(t, w)
-
- go func() {
- errW := w.Wait()
- require.Error(t, errW)
- }()
-
- sw := worker.From(w)
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
- assert.Error(t, err)
- assert.Nil(t, res)
-
- time.Sleep(time.Second)
- err = w.Stop()
- assert.NoError(t, err)
-}
-
-func Benchmark_Pipe_SpawnWorker_Stop(b *testing.B) {
- f := NewPipeFactory()
- for n := 0; n < b.N; n++ {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- w, _ := f.SpawnWorkerWithTimeout(context.Background(), cmd)
- go func() {
- if w.Wait() != nil {
- b.Fail()
- }
- }()
-
- err := w.Stop()
- if err != nil {
- b.Errorf("error stopping the worker: error %v", err)
- }
- }
-}
-
-func Benchmark_Pipe_Worker_ExecEcho(b *testing.B) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, _ := NewPipeFactory().SpawnWorkerWithTimeout(context.Background(), cmd)
- sw := worker.From(w)
-
- b.ReportAllocs()
- b.ResetTimer()
- go func() {
- err := w.Wait()
- if err != nil {
- b.Errorf("error waiting the worker: error %v", err)
- }
- }()
- defer func() {
- err := w.Stop()
- if err != nil {
- b.Errorf("error stopping the worker: error %v", err)
- }
- }()
-
- for n := 0; n < b.N; n++ {
- if _, err := sw.Exec(&payload.Payload{Body: []byte("hello")}); err != nil {
- b.Fail()
- }
- }
-}
-
-func Benchmark_Pipe_Worker_ExecEcho3(b *testing.B) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- ctx := context.Background()
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- if err != nil {
- b.Fatal(err)
- }
-
- defer func() {
- err = w.Stop()
- if err != nil {
- b.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- for n := 0; n < b.N; n++ {
- if _, err := sw.Exec(&payload.Payload{Body: []byte("hello")}); err != nil {
- b.Fail()
- }
- }
-}
-
-func Benchmark_Pipe_Worker_ExecEchoWithoutContext(b *testing.B) {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- ctx := context.Background()
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- if err != nil {
- b.Fatal(err)
- }
-
- defer func() {
- err = w.Stop()
- if err != nil {
- b.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- for n := 0; n < b.N; n++ {
- if _, err := sw.Exec(&payload.Payload{Body: []byte("hello")}); err != nil {
- b.Fail()
- }
- }
-}
-
-func Test_Echo(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- if err != nil {
- t.Fatal(err)
- }
-
- sw := worker.From(w)
- go func() {
- assert.NoError(t, sw.Wait())
- }()
- defer func() {
- err = sw.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
-
- assert.Nil(t, err)
- assert.NotNil(t, res)
- assert.NotNil(t, res.Body)
- assert.Empty(t, res.Context)
-
- assert.Equal(t, "hello", res.String())
-}
-
-func Test_BadPayload(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, _ := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
-
- sw := worker.From(w)
-
- go func() {
- assert.NoError(t, sw.Wait())
- }()
- defer func() {
- err := sw.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- res, err := sw.Exec(&payload.Payload{})
-
- assert.Error(t, err)
- assert.Nil(t, res)
-
- assert.Contains(t, err.Error(), "payload can not be empty")
-}
-
-func Test_String(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, _ := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- go func() {
- assert.NoError(t, w.Wait())
- }()
- defer func() {
- err := w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- assert.Contains(t, w.String(), "php ../../tests/client.php echo pipes")
- assert.Contains(t, w.String(), "ready")
- assert.Contains(t, w.String(), "num_execs: 0")
-}
-
-func Test_Echo_Slow(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- cmd := exec.Command("php", "../../tests/slow-client.php", "echo", "pipes", "10", "10")
-
- w, _ := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- go func() {
- assert.NoError(t, w.Wait())
- }()
- defer func() {
- err := w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
-
- assert.Nil(t, err)
- assert.NotNil(t, res)
- assert.NotNil(t, res.Body)
- assert.Empty(t, res.Context)
-
- assert.Equal(t, "hello", res.String())
-}
-
-func Test_Broken(t *testing.T) {
- ctx := context.Background()
- cmd := exec.Command("php", "../../tests/client.php", "broken", "pipes")
-
- w, err := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- if err != nil {
- t.Fatal(err)
- }
-
- sw := worker.From(w)
-
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
- assert.NotNil(t, err)
- assert.Nil(t, res)
-
- time.Sleep(time.Second * 3)
- assert.Error(t, w.Stop())
-}
-
-func Test_Error(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- cmd := exec.Command("php", "../../tests/client.php", "error", "pipes")
-
- w, _ := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- go func() {
- assert.NoError(t, w.Wait())
- }()
-
- defer func() {
- err := w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
- assert.NotNil(t, err)
- assert.Nil(t, res)
-
- if errors.Is(errors.SoftJob, err) == false {
- t.Fatal("error should be of type errors.ErrSoftJob")
- }
- assert.Contains(t, err.Error(), "hello")
-}
-
-func Test_NumExecs(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
-
- w, _ := NewPipeFactory().SpawnWorkerWithTimeout(ctx, cmd)
- go func() {
- assert.NoError(t, w.Wait())
- }()
- defer func() {
- err := w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- _, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
- if err != nil {
- t.Errorf("fail to execute payload: error %v", err)
- }
- assert.Equal(t, uint64(1), w.State().NumExecs())
-
- _, err = sw.Exec(&payload.Payload{Body: []byte("hello")})
- if err != nil {
- t.Errorf("fail to execute payload: error %v", err)
- }
- assert.Equal(t, uint64(2), w.State().NumExecs())
-
- _, err = sw.Exec(&payload.Payload{Body: []byte("hello")})
- if err != nil {
- t.Errorf("fail to execute payload: error %v", err)
- }
- assert.Equal(t, uint64(3), w.State().NumExecs())
-}
diff --git a/transport/socket/socket_factory.go b/transport/socket/socket_factory.go
deleted file mode 100755
index 06d7000d..00000000
--- a/transport/socket/socket_factory.go
+++ /dev/null
@@ -1,248 +0,0 @@
-package socket
-
-import (
- "context"
- "fmt"
- "net"
- "os/exec"
- "sync"
- "time"
-
- "github.com/shirou/gopsutil/process"
- "github.com/spiral/errors"
- "github.com/spiral/goridge/v3/pkg/relay"
- "github.com/spiral/goridge/v3/pkg/socket"
- "github.com/spiral/roadrunner/v2/internal"
- "github.com/spiral/roadrunner/v2/worker"
-
- "golang.org/x/sync/errgroup"
-)
-
-// Factory connects to external stack using socket server.
-type Factory struct {
- // listens for incoming connections from underlying processes
- ls net.Listener
-
- // relay connection timeout
- tout time.Duration
-
- // sockets which are waiting for process association
- relays sync.Map
-}
-
-// NewSocketServer returns Factory attached to a given socket listener.
-// tout specifies for how long factory should serve for incoming relay connection
-func NewSocketServer(ls net.Listener, tout time.Duration) *Factory {
- f := &Factory{
- ls: ls,
- tout: tout,
- relays: sync.Map{},
- }
-
- // Be careful
- // https://github.com/go101/go101/wiki/About-memory-ordering-guarantees-made-by-atomic-operations-in-Go
- // https://github.com/golang/go/issues/5045
- go func() {
- err := f.listen()
- // there is no logger here, use fmt
- if err != nil {
- fmt.Printf("[WARN]: socket server listen, error: %v\n", err)
- }
- }()
-
- return f
-}
-
-// blocking operation, returns an error
-func (f *Factory) listen() error {
- errGr := &errgroup.Group{}
- errGr.Go(func() error {
- for {
- conn, err := f.ls.Accept()
- if err != nil {
- return err
- }
-
- rl := socket.NewSocketRelay(conn)
- pid, err := internal.Pid(rl)
- if err != nil {
- return err
- }
-
- f.attachRelayToPid(pid, rl)
- }
- })
-
- return errGr.Wait()
-}
-
-type socketSpawn struct {
- w *worker.Process
- err error
-}
-
-// SpawnWorkerWithTimeout creates Process and connects it to appropriate relay or return an error
-func (f *Factory) SpawnWorkerWithTimeout(ctx context.Context, cmd *exec.Cmd) (*worker.Process, error) {
- c := make(chan socketSpawn)
- go func() {
- ctxT, cancel := context.WithTimeout(ctx, f.tout)
- defer cancel()
- w, err := worker.InitBaseWorker(cmd)
- if err != nil {
- select {
- case c <- socketSpawn{
- w: nil,
- err: err,
- }:
- return
- default:
- return
- }
- }
-
- err = w.Start()
- if err != nil {
- select {
- case c <- socketSpawn{
- w: nil,
- err: err,
- }:
- return
- default:
- return
- }
- }
-
- rl, err := f.findRelayWithContext(ctxT, w)
- if err != nil {
- _ = w.Kill()
- select {
- // try to write result
- case c <- socketSpawn{
- w: nil,
- err: err,
- }:
- return
- // if no receivers - return
- default:
- return
- }
- }
-
- w.AttachRelay(rl)
- w.State().Set(worker.StateReady)
-
- select {
- case c <- socketSpawn{
- w: w,
- err: nil,
- }:
- return
- default:
- _ = w.Kill()
- return
- }
- }()
-
- select {
- case <-ctx.Done():
- return nil, ctx.Err()
- case res := <-c:
- if res.err != nil {
- return nil, res.err
- }
-
- return res.w, nil
- }
-}
-
-func (f *Factory) SpawnWorker(cmd *exec.Cmd) (*worker.Process, error) {
- w, err := worker.InitBaseWorker(cmd)
- if err != nil {
- return nil, err
- }
-
- err = w.Start()
- if err != nil {
- return nil, err
- }
-
- rl, err := f.findRelay(w)
- if err != nil {
- _ = w.Kill()
- return nil, err
- }
-
- w.AttachRelay(rl)
-
- // errors bundle
- _, err = internal.Pid(rl)
- if err != nil {
- _ = w.Kill()
- return nil, err
- }
-
- w.State().Set(worker.StateReady)
-
- return w, nil
-}
-
-// Close socket factory and underlying socket connection.
-func (f *Factory) Close() error {
- return f.ls.Close()
-}
-
-// waits for Process to connect over socket and returns associated relay of timeout
-func (f *Factory) findRelayWithContext(ctx context.Context, w worker.BaseProcess) (*socket.Relay, error) {
- ticker := time.NewTicker(time.Millisecond * 10)
- for {
- select {
- case <-ctx.Done():
- return nil, ctx.Err()
- case <-ticker.C:
- // check for the process exists
- _, err := process.NewProcess(int32(w.Pid()))
- if err != nil {
- return nil, err
- }
- default:
- // find first pid and attach relay to it
- var r *socket.Relay
- f.relays.Range(func(k, val interface{}) bool {
- r = val.(*socket.Relay)
- f.relays.Delete(k)
- return false
- })
-
- // no relay exists
- if r == nil {
- continue
- }
-
- return r, nil
- }
- }
-}
-
-func (f *Factory) findRelay(w worker.BaseProcess) (*socket.Relay, error) {
- const op = errors.Op("factory_find_relay")
- // poll every 1ms for the relay
- pollDone := time.NewTimer(f.tout)
- for {
- select {
- case <-pollDone.C:
- return nil, errors.E(op, errors.Str("relay timeout"))
- default:
- tmp, ok := f.relays.Load(w.Pid())
- if !ok {
- continue
- }
- return tmp.(*socket.Relay), nil
- }
- }
-}
-
-// chan to store relay associated with specific pid
-func (f *Factory) attachRelayToPid(pid int64, relay relay.Relay) {
- f.relays.Store(pid, relay)
-}
diff --git a/transport/socket/socket_factory_spawn_test.go b/transport/socket/socket_factory_spawn_test.go
deleted file mode 100644
index 7fc6f4a5..00000000
--- a/transport/socket/socket_factory_spawn_test.go
+++ /dev/null
@@ -1,482 +0,0 @@
-package socket
-
-import (
- "net"
- "os/exec"
- "sync"
- "syscall"
- "testing"
- "time"
-
- "github.com/spiral/roadrunner/v2/payload"
- "github.com/spiral/roadrunner/v2/worker"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-)
-
-func Test_Tcp_Start2(t *testing.T) {
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- errC := ls.Close()
- if errC != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "tcp")
-
- w, err := NewSocketServer(ls, time.Minute).SpawnWorker(cmd)
- assert.NoError(t, err)
- assert.NotNil(t, w)
-
- go func() {
- assert.NoError(t, w.Wait())
- }()
-
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
-}
-
-func Test_Tcp_StartCloseFactory2(t *testing.T) {
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "tcp")
- f := NewSocketServer(ls, time.Minute)
- defer func() {
- err = ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
-
- w, err := f.SpawnWorker(cmd)
- assert.NoError(t, err)
- assert.NotNil(t, w)
-
- go func() {
- require.NoError(t, w.Wait())
- }()
-
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
-}
-
-func Test_Tcp_StartError2(t *testing.T) {
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- errC := ls.Close()
- if errC != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- err = cmd.Start()
- if err != nil {
- t.Errorf("error executing the command: error %v", err)
- }
-
- w, err := NewSocketServer(ls, time.Minute).SpawnWorker(cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Tcp_Failboot2(t *testing.T) {
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- err3 := ls.Close()
- if err3 != nil {
- t.Errorf("error closing the listener: error %v", err3)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/failboot.php")
-
- w, err2 := NewSocketServer(ls, time.Second*5).SpawnWorker(cmd)
- assert.Nil(t, w)
- assert.Error(t, err2)
-}
-
-func Test_Tcp_Invalid2(t *testing.T) {
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- errC := ls.Close()
- if errC != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/invalid.php")
-
- w, err := NewSocketServer(ls, time.Second*1).SpawnWorker(cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Tcp_Broken2(t *testing.T) {
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- errC := ls.Close()
- if errC != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "broken", "tcp")
-
- w, err := NewSocketServer(ls, time.Minute).SpawnWorker(cmd)
- if err != nil {
- t.Fatal(err)
- }
- wg := sync.WaitGroup{}
- wg.Add(1)
- go func() {
- defer wg.Done()
- errW := w.Wait()
- assert.Error(t, errW)
- }()
-
- sw := worker.From(w)
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
- assert.Error(t, err)
- assert.Nil(t, res)
- wg.Wait()
-
- time.Sleep(time.Second)
- err2 := w.Stop()
- // write tcp 127.0.0.1:9007->127.0.0.1:34204: use of closed network connection
- // but process exited
- assert.NoError(t, err2)
-}
-
-func Test_Tcp_Echo2(t *testing.T) {
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- errC := ls.Close()
- if errC != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "tcp")
-
- w, _ := NewSocketServer(ls, time.Minute).SpawnWorker(cmd)
- go func() {
- assert.NoError(t, w.Wait())
- }()
- defer func() {
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
-
- assert.NoError(t, err)
- assert.NotNil(t, res)
- assert.NotNil(t, res.Body)
- assert.Empty(t, res.Context)
-
- assert.Equal(t, "hello", res.String())
-}
-
-func Test_Unix_Start2(t *testing.T) {
- ls, err := net.Listen("unix", "sock.unix")
- assert.NoError(t, err)
- defer func() {
- err = ls.Close()
- assert.NoError(t, err)
- }()
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "unix")
-
- w, err := NewSocketServer(ls, time.Minute).SpawnWorker(cmd)
- assert.NoError(t, err)
- assert.NotNil(t, w)
-
- go func() {
- assert.NoError(t, w.Wait())
- }()
-
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
-}
-
-func Test_Unix_Failboot2(t *testing.T) {
- ls, err := net.Listen("unix", "sock.unix")
- assert.NoError(t, err)
- defer func() {
- err = ls.Close()
- assert.NoError(t, err)
- }()
-
- cmd := exec.Command("php", "../../tests/failboot.php")
-
- w, err := NewSocketServer(ls, time.Second*5).SpawnWorker(cmd)
- assert.Nil(t, w)
- assert.Error(t, err)
-}
-
-func Test_Unix_Timeout2(t *testing.T) {
- ls, err := net.Listen("unix", "sock.unix")
- assert.NoError(t, err)
- defer func() {
- err = ls.Close()
- assert.NoError(t, err)
- }()
-
- cmd := exec.Command("php", "../../tests/slow-client.php", "echo", "unix", "200", "0")
-
- w, err := NewSocketServer(ls, time.Millisecond*100).SpawnWorker(cmd)
- assert.Nil(t, w)
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "relay timeout")
-}
-
-func Test_Unix_Invalid2(t *testing.T) {
- ls, err := net.Listen("unix", "sock.unix")
- assert.NoError(t, err)
- defer func() {
- err = ls.Close()
- assert.NoError(t, err)
- }()
-
- cmd := exec.Command("php", "../../tests/invalid.php")
-
- w, err := NewSocketServer(ls, time.Second*10).SpawnWorker(cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Unix_Broken2(t *testing.T) {
- ls, err := net.Listen("unix", "sock.unix")
- assert.NoError(t, err)
- defer func() {
- errC := ls.Close()
- assert.NoError(t, errC)
- }()
-
- cmd := exec.Command("php", "../../tests/client.php", "broken", "unix")
-
- w, err := NewSocketServer(ls, time.Minute).SpawnWorker(cmd)
- if err != nil {
- t.Fatal(err)
- }
- wg := &sync.WaitGroup{}
- wg.Add(1)
- go func() {
- defer wg.Done()
- errW := w.Wait()
- assert.Error(t, errW)
- }()
-
- sw := worker.From(w)
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
-
- assert.Error(t, err)
- assert.Nil(t, res)
- wg.Wait()
-
- time.Sleep(time.Second)
- err = w.Stop()
- assert.NoError(t, err)
-}
-
-func Test_Unix_Echo2(t *testing.T) {
- ls, err := net.Listen("unix", "sock.unix")
- assert.NoError(t, err)
- defer func() {
- err = ls.Close()
- assert.NoError(t, err)
- }()
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "unix")
-
- w, err := NewSocketServer(ls, time.Minute).SpawnWorker(cmd)
- if err != nil {
- t.Fatal(err)
- }
- go func() {
- assert.NoError(t, w.Wait())
- }()
- defer func() {
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
-
- assert.NoError(t, err)
- assert.NotNil(t, res)
- assert.NotNil(t, res.Body)
- assert.Empty(t, res.Context)
-
- assert.Equal(t, "hello", res.String())
-}
-
-func Benchmark_Tcp_SpawnWorker_Stop2(b *testing.B) {
- ls, err := net.Listen("unix", "sock.unix")
- assert.NoError(b, err)
- defer func() {
- err = ls.Close()
- assert.NoError(b, err)
- }()
-
- f := NewSocketServer(ls, time.Minute)
- for n := 0; n < b.N; n++ {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "tcp")
-
- w, err := f.SpawnWorker(cmd)
- if err != nil {
- b.Fatal(err)
- }
- go func() {
- assert.NoError(b, w.Wait())
- }()
-
- err = w.Stop()
- if err != nil {
- b.Errorf("error stopping the Process: error %v", err)
- }
- }
-}
-
-func Benchmark_Tcp_Worker_ExecEcho2(b *testing.B) {
- ls, err := net.Listen("unix", "sock.unix")
- assert.NoError(b, err)
- defer func() {
- err = ls.Close()
- assert.NoError(b, err)
- }()
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "tcp")
-
- w, err := NewSocketServer(ls, time.Minute).SpawnWorker(cmd)
- if err != nil {
- b.Fatal(err)
- }
- defer func() {
- err = w.Stop()
- if err != nil {
- b.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- for n := 0; n < b.N; n++ {
- if _, err := sw.Exec(&payload.Payload{Body: []byte("hello")}); err != nil {
- b.Fail()
- }
- }
-}
-
-func Benchmark_Unix_SpawnWorker_Stop2(b *testing.B) {
- defer func() {
- _ = syscall.Unlink("sock.unix")
- }()
- ls, err := net.Listen("unix", "sock.unix")
- if err == nil {
- defer func() {
- errC := ls.Close()
- if errC != nil {
- b.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- b.Skip("socket is busy")
- }
-
- f := NewSocketServer(ls, time.Minute)
- for n := 0; n < b.N; n++ {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "unix")
-
- w, err := f.SpawnWorker(cmd)
- if err != nil {
- b.Fatal(err)
- }
- err = w.Stop()
- if err != nil {
- b.Errorf("error stopping the Process: error %v", err)
- }
- }
-}
-
-func Benchmark_Unix_Worker_ExecEcho2(b *testing.B) {
- defer func() {
- _ = syscall.Unlink("sock.unix")
- }()
- ls, err := net.Listen("unix", "sock.unix")
- if err == nil {
- defer func() {
- errC := ls.Close()
- if errC != nil {
- b.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- b.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "unix")
-
- w, err := NewSocketServer(ls, time.Minute).SpawnWorker(cmd)
- if err != nil {
- b.Fatal(err)
- }
- defer func() {
- err = w.Stop()
- if err != nil {
- b.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- for n := 0; n < b.N; n++ {
- if _, err := sw.Exec(&payload.Payload{Body: []byte("hello")}); err != nil {
- b.Fail()
- }
- }
-}
diff --git a/transport/socket/socket_factory_test.go b/transport/socket/socket_factory_test.go
deleted file mode 100755
index 5a078be4..00000000
--- a/transport/socket/socket_factory_test.go
+++ /dev/null
@@ -1,609 +0,0 @@
-package socket
-
-import (
- "context"
- "net"
- "os/exec"
- "sync"
- "testing"
- "time"
-
- "github.com/spiral/roadrunner/v2/payload"
- "github.com/spiral/roadrunner/v2/worker"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-)
-
-func Test_Tcp_Start(t *testing.T) {
- ctx := context.Background()
- time.Sleep(time.Millisecond * 10) // to ensure free socket
-
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- err = ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "tcp")
-
- w, err := NewSocketServer(ls, time.Minute).SpawnWorkerWithTimeout(ctx, cmd)
- assert.NoError(t, err)
- assert.NotNil(t, w)
-
- go func() {
- assert.NoError(t, w.Wait())
- }()
-
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
-}
-
-func Test_Tcp_StartCloseFactory(t *testing.T) {
- time.Sleep(time.Millisecond * 10) // to ensure free socket
- ctx := context.Background()
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "tcp")
- f := NewSocketServer(ls, time.Minute)
- defer func() {
- err = ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
-
- w, err := f.SpawnWorkerWithTimeout(ctx, cmd)
- assert.NoError(t, err)
- assert.NotNil(t, w)
-
- go func() {
- require.NoError(t, w.Wait())
- }()
-
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
-}
-
-func Test_Tcp_StartError(t *testing.T) {
- time.Sleep(time.Millisecond * 10) // to ensure free socket
- ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
- defer cancel()
-
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- err = ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "pipes")
- err = cmd.Start()
- if err != nil {
- t.Errorf("error executing the command: error %v", err)
- }
-
- serv := NewSocketServer(ls, time.Minute)
- time.Sleep(time.Second * 2)
- w, err := serv.SpawnWorkerWithTimeout(ctx, cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Tcp_Failboot(t *testing.T) {
- time.Sleep(time.Millisecond * 10) // to ensure free socket
- ctx := context.Background()
-
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- err3 := ls.Close()
- if err3 != nil {
- t.Errorf("error closing the listener: error %v", err3)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/failboot.php")
-
- w, err2 := NewSocketServer(ls, time.Second*5).SpawnWorkerWithTimeout(ctx, cmd)
- assert.Nil(t, w)
- assert.Error(t, err2)
-}
-
-func Test_Tcp_Timeout(t *testing.T) {
- time.Sleep(time.Millisecond * 10) // to ensure free socket
- ctx := context.Background()
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- err = ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/slow-client.php", "echo", "tcp", "200", "0")
-
- w, err := NewSocketServer(ls, time.Millisecond*1).SpawnWorkerWithTimeout(ctx, cmd)
- assert.Nil(t, w)
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "context deadline exceeded")
-}
-
-func Test_Tcp_Invalid(t *testing.T) {
- time.Sleep(time.Millisecond * 10) // to ensure free socket
- ctx := context.Background()
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- err = ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/invalid.php")
-
- w, err := NewSocketServer(ls, time.Second*1).SpawnWorkerWithTimeout(ctx, cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Tcp_Broken(t *testing.T) {
- time.Sleep(time.Millisecond * 10) // to ensure free socket
- ctx := context.Background()
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- errC := ls.Close()
- if errC != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "broken", "tcp")
-
- w, err := NewSocketServer(ls, time.Second*10).SpawnWorkerWithTimeout(ctx, cmd)
- if err != nil {
- t.Fatal(err)
- }
- wg := sync.WaitGroup{}
- wg.Add(1)
- go func() {
- defer wg.Done()
- errW := w.Wait()
- assert.Error(t, errW)
- }()
-
- sw := worker.From(w)
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
- assert.Error(t, err)
- assert.Nil(t, res)
- wg.Wait()
-
- time.Sleep(time.Second)
- err2 := w.Stop()
- // write tcp 127.0.0.1:9007->127.0.0.1:34204: use of closed network connection
- // but process is stopped
- assert.NoError(t, err2)
-}
-
-func Test_Tcp_Echo(t *testing.T) {
- time.Sleep(time.Millisecond * 10) // to ensure free socket
- ctx := context.Background()
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- err = ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "tcp")
-
- w, _ := NewSocketServer(ls, time.Minute).SpawnWorkerWithTimeout(ctx, cmd)
- go func() {
- assert.NoError(t, w.Wait())
- }()
- defer func() {
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
-
- assert.NoError(t, err)
- assert.NotNil(t, res)
- assert.NotNil(t, res.Body)
- assert.Empty(t, res.Context)
-
- assert.Equal(t, "hello", res.String())
-}
-
-func Test_Tcp_Echo_Script(t *testing.T) {
- time.Sleep(time.Millisecond * 10) // to ensure free socket
- ctx := context.Background()
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if assert.NoError(t, err) {
- defer func() {
- err = ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("sh", "../../tests/socket_test_script.sh")
-
- w, _ := NewSocketServer(ls, time.Minute).SpawnWorkerWithTimeout(ctx, cmd)
- go func() {
- assert.NoError(t, w.Wait())
- }()
- defer func() {
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
-
- assert.NoError(t, err)
- assert.NotNil(t, res)
- assert.NotNil(t, res.Body)
- assert.Empty(t, res.Context)
-
- assert.Equal(t, "hello", res.String())
-}
-
-func Test_Unix_Start(t *testing.T) {
- ctx := context.Background()
- ls, err := net.Listen("unix", "sock.unix")
- if err == nil {
- defer func() {
- err = ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "unix")
-
- w, err := NewSocketServer(ls, time.Minute).SpawnWorkerWithTimeout(ctx, cmd)
- assert.NoError(t, err)
- assert.NotNil(t, w)
-
- go func() {
- assert.NoError(t, w.Wait())
- }()
-
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
-}
-
-func Test_Unix_Failboot(t *testing.T) {
- ls, err := net.Listen("unix", "sock.unix")
- ctx := context.Background()
- if err == nil {
- defer func() {
- err = ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/failboot.php")
-
- w, err := NewSocketServer(ls, time.Second*5).SpawnWorkerWithTimeout(ctx, cmd)
- assert.Nil(t, w)
- assert.Error(t, err)
-}
-
-func Test_Unix_Timeout(t *testing.T) {
- ls, err := net.Listen("unix", "sock.unix")
- ctx := context.Background()
- if err == nil {
- defer func() {
- err = ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/slow-client.php", "echo", "unix", "200", "0")
-
- w, err := NewSocketServer(ls, time.Millisecond*100).SpawnWorkerWithTimeout(ctx, cmd)
- assert.Nil(t, w)
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "context deadline exceeded")
-}
-
-func Test_Unix_Invalid(t *testing.T) {
- ctx := context.Background()
- ls, err := net.Listen("unix", "sock.unix")
- if err == nil {
- defer func() {
- err = ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/invalid.php")
-
- w, err := NewSocketServer(ls, time.Second*10).SpawnWorkerWithTimeout(ctx, cmd)
- assert.Error(t, err)
- assert.Nil(t, w)
-}
-
-func Test_Unix_Broken(t *testing.T) {
- ctx := context.Background()
- ls, err := net.Listen("unix", "sock.unix")
- if err == nil {
- defer func() {
- errC := ls.Close()
- if errC != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "broken", "unix")
- w, err := NewSocketServer(ls, time.Minute).SpawnWorkerWithTimeout(ctx, cmd)
- if err != nil {
- t.Fatal(err)
- }
- wg := &sync.WaitGroup{}
- wg.Add(1)
- go func() {
- defer wg.Done()
- errW := w.Wait()
- assert.Error(t, errW)
- }()
-
- sw := worker.From(w)
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
-
- assert.Error(t, err)
- assert.Nil(t, res)
-
- time.Sleep(time.Second)
- err = w.Stop()
- assert.NoError(t, err)
-
- wg.Wait()
-}
-
-func Test_Unix_Echo(t *testing.T) {
- ctx := context.Background()
- ls, err := net.Listen("unix", "sock.unix")
- if err == nil {
- defer func() {
- err = ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- t.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "unix")
-
- w, err := NewSocketServer(ls, time.Minute).SpawnWorkerWithTimeout(ctx, cmd)
- if err != nil {
- t.Fatal(err)
- }
- go func() {
- assert.NoError(t, w.Wait())
- }()
- defer func() {
- err = w.Stop()
- if err != nil {
- t.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- res, err := sw.Exec(&payload.Payload{Body: []byte("hello")})
-
- assert.NoError(t, err)
- assert.NotNil(t, res)
- assert.NotNil(t, res.Body)
- assert.Empty(t, res.Context)
-
- assert.Equal(t, "hello", res.String())
-}
-
-func Benchmark_Tcp_SpawnWorker_Stop(b *testing.B) {
- ctx := context.Background()
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if err == nil {
- defer func() {
- err = ls.Close()
- if err != nil {
- b.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- b.Skip("socket is busy")
- }
-
- f := NewSocketServer(ls, time.Minute)
- for n := 0; n < b.N; n++ {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "tcp")
-
- w, err := f.SpawnWorkerWithTimeout(ctx, cmd)
- if err != nil {
- b.Fatal(err)
- }
- go func() {
- assert.NoError(b, w.Wait())
- }()
-
- err = w.Stop()
- if err != nil {
- b.Errorf("error stopping the Process: error %v", err)
- }
- }
-}
-
-func Benchmark_Tcp_Worker_ExecEcho(b *testing.B) {
- ctx := context.Background()
- ls, err := net.Listen("tcp", "127.0.0.1:9007")
- if err == nil {
- defer func() {
- err = ls.Close()
- if err != nil {
- b.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- b.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "tcp")
-
- w, err := NewSocketServer(ls, time.Minute).SpawnWorkerWithTimeout(ctx, cmd)
- if err != nil {
- b.Fatal(err)
- }
- defer func() {
- err = w.Stop()
- if err != nil {
- b.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- for n := 0; n < b.N; n++ {
- if _, err := sw.Exec(&payload.Payload{Body: []byte("hello")}); err != nil {
- b.Fail()
- }
- }
-}
-
-func Benchmark_Unix_SpawnWorker_Stop(b *testing.B) {
- ctx := context.Background()
- ls, err := net.Listen("unix", "sock.unix")
- if err == nil {
- defer func() {
- err = ls.Close()
- if err != nil {
- b.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- b.Skip("socket is busy")
- }
-
- f := NewSocketServer(ls, time.Minute)
- for n := 0; n < b.N; n++ {
- cmd := exec.Command("php", "../../tests/client.php", "echo", "unix")
-
- w, err := f.SpawnWorkerWithTimeout(ctx, cmd)
- if err != nil {
- b.Fatal(err)
- }
- err = w.Stop()
- if err != nil {
- b.Errorf("error stopping the Process: error %v", err)
- }
- }
-}
-
-func Benchmark_Unix_Worker_ExecEcho(b *testing.B) {
- ctx := context.Background()
- ls, err := net.Listen("unix", "sock.unix")
- if err == nil {
- defer func() {
- err = ls.Close()
- if err != nil {
- b.Errorf("error closing the listener: error %v", err)
- }
- }()
- } else {
- b.Skip("socket is busy")
- }
-
- cmd := exec.Command("php", "../../tests/client.php", "echo", "unix")
-
- w, err := NewSocketServer(ls, time.Minute).SpawnWorkerWithTimeout(ctx, cmd)
- if err != nil {
- b.Fatal(err)
- }
- defer func() {
- err = w.Stop()
- if err != nil {
- b.Errorf("error stopping the Process: error %v", err)
- }
- }()
-
- sw := worker.From(w)
-
- for n := 0; n < b.N; n++ {
- if _, err := sw.Exec(&payload.Payload{Body: []byte("hello")}); err != nil {
- b.Fail()
- }
- }
-}