def test_send_offset_request(self): req = OffsetRequest(self.topic, 0, -1, 100) (resp, ) = yield self.client.send_offset_request([req]) self.assertEqual(resp.error, 0) self.assertEqual(resp.topic, self.topic) self.assertEqual(resp.partition, 0) self.assertEqual(resp.offsets, (0, ))
def test_send_offset_request(self): req = OffsetRequest(self.topic, 0, -1, 100) [resp] = yield self.retry_while_broker_errors(self.client.send_offset_request, [req]) self.assertEqual(resp.error, 0) self.assertEqual(resp.topic, self.topic) self.assertEqual(resp.partition, 0) self.assertEqual(resp.offsets, (0,))
def test_encode_offset_request__no_payload(self): expected = b"".join([ struct.pack('>h', 2), # Message type = offset fetch struct.pack('>h', 0), # API version struct.pack('>i', 4), # Correlation ID struct.pack('>h3s', 3, b"cid"), # The client ID struct.pack('>i', -1), # Replica Id struct.pack('>i', 1), # Num topics struct.pack(">h6s", 6, b"topic1"), # Topic for the request struct.pack(">i", 2), # Two partitions struct.pack(">i", 3), # Partition 3 struct.pack(">q", -1), # No time offset struct.pack(">i", 1), # One offset requested struct.pack(">i", 4), # Partition 3 struct.pack(">q", -1), # No time offset struct.pack(">i", 1), # One offset requested ]) encoded = KafkaCodec.encode_offset_request(b"cid", 4, [ OffsetRequest(b'topic1', 3, -1, 1), OffsetRequest(b'topic1', 4, -1, 1), ]) self.assertEqual(encoded, expected)
def _do_fetch(self): """Send a fetch request if there isn't a request outstanding Sends a fetch request to the Kafka cluster to get messages at the current offset. When the response comes back, if there are messages, it delivers them to the :attr:`processor` callback and initiates another fetch request. If there is a recoverable error, the fetch is retried after :attr:`retry_delay`. In the case of an unrecoverable error, :func:`errback` is called on the :class:`Deferred` returned by :meth:`start()`. """ # Check for outstanding request. if self._request_d: log.debug("_do_fetch: Outstanding request: %r", self._request_d) return # Cleanup our _retry_call, if we have one if self._retry_call is not None: if self._retry_call.active(): self._retry_call.cancel() self._retry_call = None # Do we know our offset yet, or do we need to figure it out? if (self._fetch_offset == OFFSET_EARLIEST or self._fetch_offset == OFFSET_LATEST): # We need to fetch the offset for our topic/partition offset_request = OffsetRequest( self.topic, self.partition, self._fetch_offset, 1) self._request_d = self.client.send_offset_request([offset_request]) self._request_d.addCallbacks( self._handle_offset_response, self._handle_offset_error) elif self._fetch_offset == OFFSET_COMMITTED: # We need to fetch the committed offset for our topic/partition # Note we use the same callbacks, as the responses are "close # enough" for our needs here if not self.consumer_group: # consumer_group must be set for OFFSET_COMMITTED failure = Failure( InvalidConsumerGroupError("Bad Group_id:{0!r}".format( self.consumer_group))) self._start_d.errback(failure) request = OffsetFetchRequest(self.topic, self.partition) self._request_d = self.client.send_offset_fetch_request( self.consumer_group, [request]) self._request_d.addCallbacks( self._handle_offset_response, self._handle_offset_error) else: # Create fetch request payload for our partition request = FetchRequest( self.topic, self.partition, self._fetch_offset, self.buffer_size) # Send request and add handlers for the response self._request_d = self.client.send_fetch_request( [request], max_wait_time=self.fetch_max_wait_time, min_bytes=self.fetch_min_bytes) # We need a temp for this because if the response is already # available, _handle_fetch_response() will clear self._request_d d = self._request_d d.addCallback(self._handle_fetch_response) d.addErrback(self._handle_fetch_error)
def current_offset(self, topic, partition): offsets, = yield self.client.send_offset_request( [OffsetRequest(topic, partition, -1, 1)]) returnValue(offsets.offsets[0])