seekToTimestamp in spring-kafka

Viewed 1457

I was trying to play with seeking of timestamp functionality but for some reason, it's not working for me.

In my producer I have next code:

ProducerRecord<String, Obj> producer = new ProducerRecord<>("topic", 0, System.currentTimeMillis() - 10000, "key", obj);
kafkaTemplate.send(producer);

And in my Kafka listener I was trying to seek offsets from some timestamp that is higher than the above one:

@Component
@RequiredArgsConstructor
@KafkaListener(id = "container",
        topics = "topic",
        clientIdPrefix = "init_client",
        autoStartup = "true")
public class KafkaList implements ConsumerSeekAware {
   @Override
    public void onPartitionsAssigned(Map<TopicPartition, Long> assignments, ConsumerSeekCallback callback) {
                long timestamp = System.currentTimeMillis()+60*1000;
        log.info("Search for a time that is great or equal then {}", timestamp);
        callback.seekToTimestamp(new ArrayList<>(assignments.keySet()), timestamp);

    }

    @KafkaHandler
    public void listen(@Header(KafkaHeaders.RECEIVED_MESSAGE_KEY) String key, Obj obj,
                       @Header(KafkaHeaders.RECEIVED_TIMESTAMP) Long timestamp) {
        log.info("Received message timestamp: {}, date: {}", timestamp,
                Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault()).toLocalDate());
    }
}

In logs I see the next output:

Search for a time that is great or equal then 1613079865328
Received message timestamp: 1613079798676, date: 2021-02-11

The timestamp value in Kafka topic 1613079798676 is lower than my search value 1613079865328 so why consumer picked up this offset?

1 Answers

I just tested it with your code and it works as expected for me; I see this in the log...

2021-02-16 11:30:16.587 INFO 36721 --- [o66163492-0-C-1] com.example.demo.So66163492Application : Search for a time that is great or equal then 1613493076587

2021-02-16 11:30:16.590 INFO 36721 --- [o66163492-0-C-1] o.a.k.clients.consumer.KafkaConsumer : [Consumer clientId=consumer-so66163492-1, groupId=so66163492] Seeking to offset 1 for partition so66163492-0

2021-02-16 11:30:16.590 INFO 36721 --- [o66163492-0-C-1] o.s.k.l.KafkaMessageListenerContainer : so66163492: partitions assigned: [so66163492-0]

2021-02-16 11:30:16.611 INFO 36721 --- [o66163492-0-C-1] com.example.demo.So66163492Application : Received message timestamp: 1613529016472 qux

@SpringBootApplication
public class So66163492Application extends AbstractConsumerSeekAware {

    private static final Logger log = LoggerFactory.getLogger(So66163492Application.class);

    public static void main(String[] args) {
        SpringApplication.run(So66163492Application.class, args);
    }

    @KafkaListener(id = "so66163492", topics = "so66163492")
    public void listen(@Header(KafkaHeaders.RECEIVED_MESSAGE_KEY) String key, String obj,
            @Header(KafkaHeaders.RECEIVED_TIMESTAMP) Long timestamp) {

        log.info("Received message timestamp: {} {}", timestamp, obj);
    }

    @Bean
    public NewTopic topic() {
        return TopicBuilder.name("so66163492").partitions(1).replicas(1).build();
    }

    @Bean
    public ApplicationRunner runner(KafkaTemplate<String, String> template) {
        return args -> {
            template.send(new ProducerRecord<>("so66163492", 0, System.currentTimeMillis() - 10_000, "foo", "bar"));
            template.send(new ProducerRecord<>("so66163492", 0, System.currentTimeMillis() + 36_000_000, "baz", "qux"));
        };
    }

    @Override
    public void onPartitionsAssigned(Map<TopicPartition, Long> assignments, ConsumerSeekCallback callback) {
        long timestamp = System.currentTimeMillis() + 60 * 1000;
        log.info("Search for a time that is great or equal then {}", timestamp);
        callback.seekToTimestamp(new ArrayList<>(assignments.keySet()), timestamp);
    }

}
Related