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 } }
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 }