// ackFollower sends an acknowledgement to the follower. func (b *Broker) ackFollower(f *Follower) error { b.lock.Lock() defer b.lock.Unlock() ack := new(protocol.Ack) if b.role != LEADER || f.conn.RemoteAddr().String() == b.Origin() { log.Warn("Denying follow requests from %s.", f.conn.RemoteAddr()) ack.Status = protocol.StatusFailure } else { inner := new(protocol.FollowACK) inner.Truncate = make(Offsets) for topic, checkpoint := range b.checkpoints { log.Info("Checkpoint is %v", checkpoint) if f.tails[topic] > checkpoint { inner.Truncate[topic] = checkpoint f.tails[topic] = checkpoint } } ack.Status = protocol.StatusSuccess ack.Payload, _ = json.Marshal(inner) } return websocket.JSON.Send(f.conn, ack) }
// producer handles incoming produce requests. Producers may send multiple // produce requests on the same persistent connection. The function exits when // an `io.EOF` is received on the connection. func producer(conn *websocket.Conn) { defer conn.Close() for { var request protocol.ProduceRequest err := websocket.JSON.Receive(conn, &request) if err == io.EOF { // graceful shutdown break } if nil != err { log.Warn("Ignoring invalid message from %v.", conn.RemoteAddr()) continue } ack := new(protocol.Ack) if err := broker.Publish(request.Topic, request.ID, &request.Message); nil != err { log.Error(err.Error()) ack.Status = protocol.StatusFailure } else { ack.Status = protocol.StatusSuccess } // TODO: should redirect if this node is not the leader websocket.JSON.Send(conn, &ack) } log.Info("Closed producer connection from %v.", conn.RemoteAddr()) }