def _send_sync_group_request(self, request): if (yield from self._coordinator.coordinator_unknown()): raise Errors.GroupCoordinatorNotAvailableError() response = None try: response = yield from self._coordinator._send_req( self.coordinator_id, request, group=ConnectionGroup.COORDINATION) log.info("Successfully synced group %s with generation %s", self.group_id, self._coordinator.generation) return response.member_assignment except Errors.RebalanceInProgressError as err: log.debug("SyncGroup for group %s failed due to coordinator" " rebalance", self.group_id) raise err except (Errors.UnknownMemberIdError, Errors.IllegalGenerationError) as err: log.debug("SyncGroup for group %s failed due to %s,", self.group_id, err) self._coordinator.member_id = JoinGroupRequest.UNKNOWN_MEMBER_ID raise err except (Errors.GroupCoordinatorNotAvailableError, Errors.NotCoordinatorForGroupError) as err: log.debug("SyncGroup for group %s failed due to %s", self.group_id, err) self._coordinator.coordinator_dead() raise err except Errors.KafkaError as err: log.error("Unexpected error from SyncGroup: %s", err) raise err finally: if response is None: # Always rejoin on error self._coordinator.rejoin_needed = True
def commit_offsets(self, offsets): """Commit specific offsets asynchronously. Arguments: offsets (dict {TopicPartition: OffsetAndMetadata}): what to commit Raises error on failure """ self._subscription.needs_fetch_committed_offsets = True if not offsets: log.debug('No offsets to commit') return True if (yield from self.coordinator_unknown()): raise Errors.GroupCoordinatorNotAvailableError() node_id = self.coordinator_id # create the offset commit request offset_data = collections.defaultdict(list) for tp, offset in offsets.items(): offset_data[tp.topic].append( (tp.partition, offset.offset, offset.metadata)) request = OffsetCommitRequest( self.group_id, self.generation, self.member_id, OffsetCommitRequest.DEFAULT_RETENTION_TIME, [(topic, tp_offsets) for topic, tp_offsets in offset_data.items()]) log.debug("Sending offset-commit request with %s for group %s to %s", offsets, self.group_id, node_id) response = yield from self._send_req( node_id, request, group=ConnectionGroup.COORDINATION) unauthorized_topics = set() for topic, partitions in response.topics: for partition, error_code in partitions: tp = TopicPartition(topic, partition) offset = offsets[tp] error_type = Errors.for_code(error_code) if error_type is Errors.NoError: log.debug("Committed offset %s for partition %s", offset, tp) if self._subscription.is_assigned(tp): partition = self._subscription.assignment[tp] partition.committed = offset.offset elif error_type is Errors.GroupAuthorizationFailedError: log.error("OffsetCommit failed for group %s - %s", self.group_id, error_type.__name__) raise error_type() elif error_type is Errors.TopicAuthorizationFailedError: unauthorized_topics.add(topic) elif error_type in (Errors.OffsetMetadataTooLargeError, Errors.InvalidCommitOffsetSizeError): # raise the error to the user log.info( "OffsetCommit failed for group %s on partition %s" " due to %s, will retry", self.group_id, tp, error_type.__name__) raise error_type() elif error_type is Errors.GroupLoadInProgressError: # just retry log.info( "OffsetCommit failed for group %s because group is" " initializing (%s), will retry", self.group_id, error_type.__name__) raise error_type() elif error_type in (Errors.GroupCoordinatorNotAvailableError, Errors.NotCoordinatorForGroupError, Errors.RequestTimedOutError): log.info( "OffsetCommit failed for group %s due to a" " coordinator error (%s), will find new coordinator" " and retry", self.group_id, error_type.__name__) self.coordinator_dead() raise error_type() elif error_type in (Errors.UnknownMemberIdError, Errors.IllegalGenerationError, Errors.RebalanceInProgressError): # need to re-join group error = error_type(self.group_id) log.error( "OffsetCommit failed for group %s due to group" " error (%s), will rejoin", self.group_id, error) self._subscription.mark_for_reassignment() raise error else: log.error( "OffsetCommit failed for group %s on partition %s" " with offset %s: %s", self.group_id, tp, offset, error_type.__name__) raise error_type() if unauthorized_topics: log.error("OffsetCommit failed for unauthorized topics %s", unauthorized_topics) raise Errors.TopicAuthorizationFailedError(unauthorized_topics)