コード例 #1
0
ファイル: mocktransport.go プロジェクト: boyand/typhon
func (t *mockTransport) Send(req message.Request, timeout time.Duration) (message.Response, error) {
	id := req.Id()
	if id == "" {
		_uuid, err := uuid.NewV4()
		if err != nil {
			log.Errorf("[Typhon:MockTransport] Failed to generate request uuid: %v", err)
			return nil, err
		}
		req.SetId(_uuid.String())
	}

	// Make a copy of the response that does not preserve the Body (this is not preserved over the wire)
	req = req.Copy()
	req.SetBody(nil)

	t.RLock()
	l, ok := t.listeners[req.Service()]
	t.RUnlock()
	if ok {
		responseChan := make(chan message.Response, 1)
		t.Lock()
		t.inflightReqs[req.Id()] = responseChan
		t.Unlock()
		defer func() {
			t.Lock()
			delete(t.inflightReqs, req.Id())
			t.Unlock()
		}()

		timer := time.NewTimer(timeout)
		defer timer.Stop()
		select {
		case <-timer.C:
			log.Debugf("[Typhon:MockTransport] Timed out after %s waiting for delivery of \"%s\"", timeout.String(),
				req.Id())
			return nil, transport.ErrTimeout
		case l.reqChan <- req:
		}

		select {
		case rsp := <-responseChan:
			return rsp, nil
		case <-timer.C:
			log.Debugf("[Typhon:MockTransport] Timed out after %s waiting for response to \"%s\"", timeout.String(),
				req.Id())
			return nil, transport.ErrTimeout
		}
	}

	return nil, transport.ErrTimeout // Don't bother waiting artificially
}
コード例 #2
0
ファイル: rabbittransport.go プロジェクト: boyand/typhon
func (t *rabbitTransport) Send(req message.Request, _timeout time.Duration) (message.Response, error) {
	id := req.Id()
	if id == "" {
		_uuid, err := uuid.NewV4()
		if err != nil {
			log.Errorf("[Typhon:RabbitTransport] Failed to generate request uuid: %v", err)
			return nil, err
		}
		req.SetId(_uuid.String())
	}

	rspQueue := req.Id()
	defer func() {
		t.inflightReqsM.Lock()
		delete(t.inflightReqs, rspQueue)
		t.inflightReqsM.Unlock()
	}()
	rspChan := make(chan message.Response, 1)
	t.inflightReqsM.Lock()
	t.inflightReqs[rspQueue] = rspChan
	t.inflightReqsM.Unlock()

	timeout := time.NewTimer(_timeout)
	defer timeout.Stop()

	headers := req.Headers()
	headers["Content-Encoding"] = "request"
	headers["Service"] = req.Service()
	headers["Endpoint"] = req.Endpoint()

	select {
	case <-t.Ready():
	case <-timeout.C:
		log.Warnf("[Typhon:RabbitTransport] Timed out after %s waiting for ready", _timeout.String())
		return nil, transport.ErrTimeout
	}

	if err := t.connection().Publish(Exchange, req.Service(), amqp.Publishing{
		CorrelationId: req.Id(),
		Timestamp:     time.Now().UTC(),
		Body:          req.Payload(),
		ReplyTo:       t.replyQueue,
		Headers:       headersToTable(headers),
	}); err != nil {
		log.Errorf("[Typhon:RabbitTransport] Failed to publish: %v", err)
		return nil, err
	}

	select {
	case rsp := <-rspChan:
		return rsp, nil
	case <-timeout.C:
		log.Warnf("[Typhon:RabbitTransport] Timed out after %s waiting for response to %s", _timeout.String(),
			req.Id())
		return nil, transport.ErrTimeout
	}
}
コード例 #3
0
ファイル: mocktransport.go プロジェクト: boyand/typhon
func (t *mockTransport) Respond(req message.Request, rsp message.Response) error {
	t.RLock()
	rspChan, ok := t.inflightReqs[req.Id()]
	t.RUnlock()

	// Make a copy of the response that does not preserve the Body (this is not preserved over the wire)
	rsp = rsp.Copy()
	rsp.SetBody(nil)

	if ok {
		select {
		case rspChan <- rsp:
			return nil
		case <-time.After(timeout):
			return transport.ErrTimeout
		}
	}
	return fmt.Errorf("No correlated request \"%s\" is in-flight", req.Id())
}