示例#1
0
    def _perform_group_join(self):
        """Join the group and return the assignment for the next generation.

        This function handles both JoinGroup and SyncGroup, delegating to
        _perform_assignment() if elected leader by the coordinator.

        Returns:
            Future: resolves to the encoded-bytes assignment returned from the
                group leader
        """
        if self.coordinator_unknown():
            e = Errors.GroupCoordinatorNotAvailableError(self.coordinator_id)
            return Future().failure(e)

        # send a join group request to the coordinator
        log.debug("(Re-)joining group %s", self.group_id)
        request = JoinGroupRequest(
            self.group_id,
            self.config['session_timeout_ms'],
            self.member_id,
            self.protocol_type(),
            [(protocol,
              metadata if isinstance(metadata, bytes) else metadata.encode())
             for protocol, metadata in self.group_protocols()])

        # create the request for the coordinator
        log.debug("Issuing request (%s) to coordinator %s", request, self.coordinator_id)
        future = Future()
        _f = self._client.send(self.coordinator_id, request)
        _f.add_callback(self._handle_join_group_response, future)
        _f.add_errback(self._failed_request, self.coordinator_id,
                       request, future)
        return future
示例#2
0
    def perform_group_join(self):
        """Join the group and return the assignment for the next generation.

        This function handles both JoinGroup and SyncGroup, delegating to
        _perform_assignment() if elected as leader by the coordinator node.

        Returns encoded-bytes assignment returned from the group leader
        """
        # send a join group request to the coordinator
        log.info("(Re-)joining group %s", self.group_id)

        topics = self._subscription
        assert topics is not None, 'Consumer has not subscribed to topics'
        metadata_list = []
        for assignor in self._assignors:
            metadata = assignor.metadata(topics)
            if not isinstance(metadata, bytes):
                metadata = metadata.encode()
            group_protocol = (assignor.name, metadata)
            metadata_list.append(group_protocol)

        request = JoinGroupRequest(self.group_id, self._session_timeout_ms,
                                   self._coordinator.member_id,
                                   ConsumerProtocol.PROTOCOL_TYPE,
                                   metadata_list)

        # create the request for the coordinator
        log.debug("Sending JoinGroup (%s) to coordinator %s", request,
                  self.coordinator_id)
        try:
            response = yield from self._coordinator._send_req(
                self.coordinator_id,
                request,
                group=ConnectionGroup.COORDINATION)
        except Errors.GroupLoadInProgressError:
            log.debug(
                "Attempt to join group %s rejected since coordinator %s"
                " is loading the group.", self.group_id, self.coordinator_id)
        except Errors.UnknownMemberIdError:
            # reset the member id and retry immediately
            self._coordinator.member_id = JoinGroupRequest.UNKNOWN_MEMBER_ID
            log.debug(
                "Attempt to join group %s failed due to unknown member id",
                self.group_id)
            return
        except (Errors.GroupCoordinatorNotAvailableError,
                Errors.NotCoordinatorForGroupError) as err:
            # re-discover the coordinator and retry with backoff
            self._coordinator.coordinator_dead()
            log.debug(
                "Attempt to join group %s failed due to obsolete "
                "coordinator information: %s", self.group_id, err)
        except Errors.KafkaError as err:
            log.error("Error in join group '%s' response: %s", self.group_id,
                      err)
            if not err.retriable:
                raise
        else:
            log.debug("Join group response %s", response)
            self._coordinator.member_id = response.member_id
            self._coordinator.generation = response.generation_id
            self._coordinator.rejoin_needed = False
            protocol = response.group_protocol
            log.info("Joined group '%s' (generation %s) with member_id %s",
                     self.group_id, response.generation_id, response.member_id)

            if response.leader_id == response.member_id:
                log.info(
                    "Elected group leader -- performing partition"
                    " assignments using %s", protocol)
                cor = self._on_join_leader(response)
            else:
                cor = self._on_join_follower()

            try:
                member_assignment_bytes = yield from cor
            except (Errors.UnknownMemberIdError,
                    Errors.RebalanceInProgressError,
                    Errors.IllegalGenerationError):
                # The current group is already not correct, maybe we were too
                # slow and timeouted or a new rebalance is required.
                pass
            except Errors.KafkaError as err:
                if not err.retriable:
                    raise
            else:
                return (protocol, member_assignment_bytes)

        # backoff wait - failure case
        yield from asyncio.sleep(self._retry_backoff_ms / 1000, loop=self.loop)