func (w *Worker) readLoop(c *nsqConn) { for { if atomic.LoadInt32(&c.stopFlag) == 1 || atomic.LoadInt32(&c.stopFlag) == 1 { goto exit } //TODO FIXME should listen on exist, need wait for timeout frameType, data, err := c.readUnpackedResponse() if err != nil { handleError(w, c, fmt.Sprintf("[%s] error (%s) reading response %d %s", c, err.Error(), frameType, data)) continue } switch frameType { case FrameTypeMessage: msg, err := broker.DecodeMessage(data) // msg.cmdChan = c.cmdChan // msg.responseChan = c.finishedMessages if err != nil { handleError(w, c, fmt.Sprintf("[%s] error (%s) reading response %d %s", c, err.Error(), frameType, data)) continue } log.Printf("INFO: [%s] FrameTypeMessage receive %s - %s", c, msg.Id, msg.Body) // remain := atomic.AddInt64(&c.rdyCount, -1) // atomic.AddInt64(&q.totalRdyCount, -1) // atomic.AddUint64(&c.messagesReceived, 1) // atomic.AddUint64(&q.MessagesReceived, 1) // atomic.AddInt64(&c.messagesInFlight, 1) // atomic.AddInt64(&q.messagesInFlight, 1) // atomic.StoreInt64(&c.lastMsgTimestamp, time.Now().UnixNano()) // if q.VerboseLogging { // log.Printf("[%s] (remain %d) FrameTypeMessage: %s - %s", // c, remain, msg.Id, msg.Body) // } // q.incomingMessages <- msg // c.rdyChan <- c case FrameTypeResponse: switch { case bytes.Equal(data, []byte("CLOSE_WAIT")): // server is ready for us to close (it ack'd our StartClose) // we can assume we will not receive any more messages over this channel // (but we can still write back responses) log.Printf("[%s] received ACK from nsqd - now in CLOSE_WAIT", c) atomic.StoreInt32(&c.stopFlag, 1) case bytes.Equal(data, []byte("H")): // var buf bytes.Buffer // err := c.sendCommand(&buf, Nop()) // if err != nil { // handleError(q, c, fmt.Sprintf("[%s] error sending NOP - %s", // c, err.Error())) // goto exit // } log.Printf("[%s] heartbeat received", c) } case FrameTypeAck: log.Printf("[%s] ack receive %s", c, data) params := bytes.Split(data, separatorBytes) ackType, err := strconv.ParseInt(string(params[0]), 10, 64) clientId, err := strconv.ParseInt(string(params[1]), 10, 64) msgId, err := strconv.ParseInt(string(params[1]), 10, 64) if err != nil { log.Printf("ERROR: parse msgId error %s", err) break } if ackType != int64(ACK_SUCCESS) { model.SaveOfflineMessage(fmt.Sprintf("%d", clientId), msgId) model.IncrMsgErrCount(msgId, 1) model.IncrClientErrCount(clientId, 1) } else { model.IncrMsgOKCount(msgId, 1) model.IncrClientOKCount(clientId, 1) } case FrameTypeError: log.Printf("[%s] error from nsqd %s", c, data) default: log.Printf("[%s] unknown message type %d", c, frameType) } } exit: c.wg.Done() log.Printf("[%s] readLoop exiting", c) }
func (c *Client) readLoop() { rbuf := bufio.NewReader(c.Conn) for { if atomic.LoadInt32(&c.stopFlag) == 1 { goto exit } resp, err := ReadResponse(rbuf) frameType, data, err := UnpackResponse(resp) if err != nil { //handleError(q, c, fmt.Sprintf("[%s] error (%s) reading response %d %s", c, err.Error(), frameType, data)) continue } switch frameType { case FrameTypeMessage: msg, err := broker.DecodeMessage(data) // msg.cmdChan = c.cmdChan // msg.responseChan = c.finishedMessages log.Printf("INFO: [%s] FrameTypeMessage receive %s - %s", c.Conn.RemoteAddr(), msg.Id, msg.Body) if err != nil { // handleError(q, c, fmt.Sprintf("[%s] error (%s) decoding message %s", // c, err.Error(), data)) continue } // remain := atomic.AddInt64(&c.rdyCount, -1) // atomic.AddInt64(&q.totalRdyCount, -1) // atomic.AddUint64(&c.messagesReceived, 1) // atomic.AddUint64(&q.MessagesReceived, 1) // atomic.AddInt64(&c.messagesInFlight, 1) // atomic.AddInt64(&q.messagesInFlight, 1) // atomic.StoreInt64(&c.lastMsgTimestamp, time.Now().UnixNano()) // if q.VerboseLogging { // log.Printf("[%s] (remain %d) FrameTypeMessage: %s - %s", // c, remain, msg.Id, msg.Body) // } // q.incomingMessages <- msg // c.rdyChan <- c case FrameTypeResponse: switch { case bytes.Equal(data, []byte("CLOSE_WAIT")): // server is ready for us to close (it ack'd our StartClose) // we can assume we will not receive any more messages over this channel // (but we can still write back responses) log.Printf("[%s] received ACK from nsqd - now in CLOSE_WAIT", c) atomic.StoreInt32(&c.stopFlag, 1) case bytes.Equal(data, []byte("H")): // var buf bytes.Buffer log.Printf("[%s] heartbeat received", c) // err := c.sendCommand(&buf, Nop()) // if err != nil { // handleError(q, c, fmt.Sprintf("[%s] error sending NOP - %s", // c, err.Error())) // goto exit // } default: log.Printf("FrameTypeResponse receive %s", string(data)) } case FrameTypeError: log.Printf("[%s] error from nsqd %s", c, data) default: log.Printf("[%s] unknown message type %d", c, frameType) } } exit: c.wg.Done() log.Printf("[%s] readLoop exiting", c) }