// CloseMessage releases a message header. // // header: Message header. // // Returns nil on success. func (this *Messenger) CloseMessage(header *msgpb.Header) error { if header.GetMessengerId() != this.uid { this.Errorf("message header %s is not created by this messenger", header) return errs.ErrInvalid } if header.Request == nil { return nil } // // Remove the request and its response channel from live requests map. // lock, errLock := this.ctlr.Lock("this.requestMap") if errLock != nil { return errLock } defer lock.Unlock() requestID := header.GetMessageId() responseCh, found := this.requestMap[requestID] if !found { return nil } close(responseCh) delete(this.requestMap, requestID) return nil }
// Receive waits for a response to a live request. // // request: Message header of a live request. // // Returns response message header and response data on success. func (this *Messenger) Receive(request *msgpb.Header) (*msgpb.Header, []byte, error) { timeout := msg.RequestTimeout(request) lock, errLock := this.ctlr.TimedLock(timeout, "this.requestMap") if errLock != nil { return nil, nil, errLock } defer lock.Unlock() requestID := request.GetMessageId() responseCh, found := this.requestMap[requestID] if !found { this.Errorf("no live request [%s] exist", request) return nil, nil, errs.ErrNotExist } // Close the lock early to unblock others. lock.Unlock() // Perform a non-blocking receive if timeout is zero. if timeout == 0 { select { case entry := <-responseCh: return entry.header, entry.data, nil default: return nil, nil, errs.ErrRetry } } // Perform a blocking receive with a timeout. select { case <-time.After(timeout): this.Warningf("timedout waiting for response to %s", request) return nil, nil, errs.ErrTimeout case entry := <-responseCh: if entry == nil { return nil, nil, errs.ErrRetry } return entry.header, entry.data, nil } }
// NewResponse creates a message header for a response message. // // request: Message header for the received request. func (this *Messenger) NewResponse(request *msgpb.Header) *msgpb.Header { header := this.NewPost() header.Response = &msgpb.Header_Response{} header.Response.RequestId = proto.Int64(request.GetMessageId()) return header }