Example #1
0
// TestRouting verifies a registered endpoint receives messages destined for it, and that responses are sent
// appropriately
func (suite *serverSuite) TestRouting() {
	srv := suite.server
	srv.AddEndpoints(Endpoint{
		Name:     "dummy",
		Request:  new(testproto.DummyRequest),
		Response: new(testproto.DummyResponse),
		Handler: func(req mercury.Request) (mercury.Response, error) {
			request := req.Body().(*testproto.DummyRequest)
			rsp := req.Response(&testproto.DummyResponse{
				Pong: request.Ping,
			})
			rsp.SetHeader("X-Ping-Pong", request.Ping)
			return rsp, nil
		}})

	req := mercury.NewRequest()
	req.SetService(testServiceName)
	req.SetEndpoint("dummy")
	req.SetBody(&testproto.DummyRequest{
		Ping: "routing"})
	suite.Assert().NoError(tmsg.ProtoMarshaler().MarshalBody(req))

	rsp, err := suite.trans.Send(req, time.Second)
	suite.Assert().NoError(err)
	suite.Assert().NotNil(rsp)
	suite.Assert().Equal(req.Service(), rsp.Service())
	suite.Assert().Equal(req.Endpoint(), rsp.Endpoint())

	suite.Assert().NoError(tmsg.ProtoUnmarshaler(new(testproto.DummyResponse)).UnmarshalPayload(rsp))
	suite.Assert().NotNil(rsp.Body())
	suite.Assert().IsType(new(testproto.DummyResponse), rsp.Body())
	response := rsp.Body().(*testproto.DummyResponse)
	suite.Assert().Equal("routing", response.Pong)
	suite.Assert().Equal("routing", rsp.Headers()["X-Ping-Pong"])
}
Example #2
0
// TestRoutingParallel sends a bunch of requests in parallel to different endpoints and checks that the responses match
// correctly. 200 workers, 100 requests each.
func (suite *serverSuite) TestRoutingParallel() {
	if testing.Short() {
		suite.T().Skip("Skipping TestRoutingParallel in short mode")
	}

	names := [...]string{"1", "2", "3"}
	srv := suite.server
	srv.AddEndpoints(
		Endpoint{
			Name:     names[0],
			Request:  new(testproto.DummyRequest),
			Response: new(testproto.DummyResponse),
			Handler: func(req mercury.Request) (mercury.Response, error) {
				return req.Response(&testproto.DummyResponse{Pong: names[0]}), nil
			}},
		Endpoint{
			Name:     names[1],
			Request:  new(testproto.DummyRequest),
			Response: new(testproto.DummyResponse),
			Handler: func(req mercury.Request) (mercury.Response, error) {
				return req.Response(&testproto.DummyResponse{Pong: names[1]}), nil
			}},
		Endpoint{
			Name:     names[2],
			Request:  new(testproto.DummyRequest),
			Response: new(testproto.DummyResponse),
			Handler: func(req mercury.Request) (mercury.Response, error) {
				return req.Response(&testproto.DummyResponse{Pong: names[2]}), nil
			}})

	workers := 200
	wg := sync.WaitGroup{}
	wg.Add(workers)
	unmarshaler := tmsg.ProtoUnmarshaler(new(testproto.DummyResponse))
	work := func(i int) {
		defer wg.Done()
		rng := rand.New(rand.NewSource(time.Now().UnixNano()))
		ep := names[rng.Int()%len(names)]
		for i := 0; i < 100; i++ {
			req := mercury.NewRequest()
			req.SetService(testServiceName)
			req.SetEndpoint(ep)
			req.SetBody(&testproto.DummyRequest{})
			suite.Assert().NoError(tmsg.ProtoMarshaler().MarshalBody(req))

			rsp, err := suite.trans.Send(req, time.Second)
			suite.Assert().NoError(err)
			suite.Assert().NotNil(rsp)
			suite.Assert().NoError(unmarshaler.UnmarshalPayload(rsp))
			response := rsp.Body().(*testproto.DummyResponse)
			suite.Assert().Equal(ep, response.Pong)
		}
	}

	for i := 0; i < workers; i++ {
		go work(i)
	}
	wg.Wait()
}
Example #3
0
func main() {
	req := mercury.NewRequest()
	req.SetService("foo")
	req.SetEndpoint("Say.Hello")
	req.SetBody(&hello.Request{
		Name: "John",
	})
	tmsg.ProtoMarshaler().MarshalBody(req)
	trans := rabbit.NewTransport()
	rsp, err := trans.Send(req, time.Second)
	if err != nil {
		fmt.Println(err)
		return
	}
	tmsg.ProtoUnmarshaler(new(hello.Response)).UnmarshalPayload(rsp)

	fmt.Println(rsp.Body())
}
Example #4
0
// TestEndpointNotFound tests that a Bad Request error is correctly returned on receiving an event for an unknown
// endpoing
func (suite *serverSuite) TestEndpointNotFound() {
	req := mercury.NewRequest()
	req.SetService(testServiceName)
	req.SetEndpoint("dummy")
	req.SetBody(&testproto.DummyRequest{
		Ping: "routing"})
	suite.Assert().NoError(tmsg.ProtoMarshaler().MarshalBody(req))

	rsp_, err := suite.trans.Send(req, time.Second)
	rsp := mercury.FromTyphonResponse(rsp_)
	suite.Assert().NoError(err)
	suite.Assert().NotNil(rsp)
	suite.Assert().True(rsp.IsError())

	suite.Assert().NoError(tmsg.ProtoUnmarshaler(new(pe.Error)).UnmarshalPayload(rsp))
	suite.Assert().IsType(new(pe.Error), rsp.Body())
	terr := terrors.Unmarshal(rsp.Body().(*pe.Error))
	suite.Assert().Equal(terrors.ErrBadRequest+".endpoint_not_found", terr.Code)
	suite.Assert().Contains(terr.Error(), "Endpoint not found")
}
Example #5
0
type MarshalerFactory func() tmsg.Marshaler
type UnmarshalerFactory func(interface{}) tmsg.Unmarshaler

type marshalerPair struct {
	m MarshalerFactory
	u UnmarshalerFactory
}

var (
	marshalerRegistryM sync.RWMutex
	marshalerRegistry  = map[string]marshalerPair{
		ProtoContentType: {
			m: tmsg.ProtoMarshaler,
			// Wrapped so we can type assert the interface{} to a proto.Message
			u: func(protocol interface{}) tmsg.Unmarshaler {
				return tmsg.ProtoUnmarshaler(protocol.(proto.Message))
			}},
		JSONContentType: {
			m: tmsg.JSONMarshaler,
			u: tmsg.JSONUnmarshaler},
	}
)

func Register(contentType string, mc MarshalerFactory, uc UnmarshalerFactory) {
	if contentType == "" || mc == nil || uc == nil {
		return
	}

	marshalerRegistryM.Lock()
	defer marshalerRegistryM.Unlock()
	marshalerRegistry[contentType] = marshalerPair{