func (h *defaultHandler) ackLoop() { log.Println("start client ack loop") defer log.Println("client ack loop stopped") // drain queue on shutdown. // Stop ACKing batches in case of error, forcing client to reconnect defer func() { log.Println("drain ack loop") for range h.ch { } }() for { select { case <-h.signal: // return on client/server shutdown log.Println("receive client connection close signal") return case b, open := <-h.ch: if !open { return } if err := h.waitACK(b); err != nil { return } } } }
func (r *reader) readEvents(in io.Reader, events []interface{}) ([]interface{}, error) { for len(events) < cap(events) { var hdr [2]byte if err := readFull(in, hdr[:]); err != nil { return nil, err } if hdr[0] != protocol.CodeVersion { log.Println("Event protocol version error") return nil, ErrProtocolError } switch hdr[1] { case protocol.CodeDataFrame: event, err := r.readEvent(in) if err != nil { log.Printf("failed to read json event with: %v\n", err) return nil, err } events = append(events, event) case protocol.CodeCompressed: readEvents, err := r.readCompressed(in, events) if err != nil { return nil, err } events = readEvents default: log.Printf("Unknown frame type: %v", hdr[1]) return nil, ErrProtocolError } } return events, nil }
func (h *defaultHandler) Run() { defer close(h.ch) // start async routine for returning ACKs to client. // Sends ACK of 0 every 'keepalive' seconds to signal // client the batch still being in pipeline go h.ackLoop() if err := h.handle(); err != nil { log.Println(err) } }