From 075015eaa24b43916675b2769d9618d526bc6986 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 3 Sep 2026 01:25:59 +0000 Subject: [PATCH 1/2] Expose an explicit event-timestamp presence check on `Message` `getEventTimestamp` returns 0 both when the producer set no event time and when it explicitly set the Unix epoch. Add `hasEventTimestamp`, mirroring the existing `hasPartitionKey`/`hasOrderingKey`, so callers can tell the two apart. --- include/pulsar/Message.h | 11 +++++++++++ lib/Message.cc | 2 ++ lib/MessageImpl.cc | 2 ++ lib/MessageImpl.h | 1 + 4 files changed, 16 insertions(+) diff --git a/include/pulsar/Message.h b/include/pulsar/Message.h index 1c906e8a..6d5c3afd 100644 --- a/include/pulsar/Message.h +++ b/include/pulsar/Message.h @@ -181,6 +181,17 @@ class PULSAR_PUBLIC Message { */ uint64_t getEventTimestamp() const; + /** + * Check whether the event timestamp was set by the client producer. + * + * @return true if the event timestamp was set while creating the message + * false if the event timestamp was not set while creating the message + * + * This is distinct from `getEventTimestamp() != 0`, because a producer may legitimately set an + * event timestamp of 0 (the Unix epoch). + */ + bool hasEventTimestamp() const; + /** * Get the topic Name from which this message originated from */ diff --git a/lib/Message.cc b/lib/Message.cc index 8bde683f..156bc59c 100644 --- a/lib/Message.cc +++ b/lib/Message.cc @@ -232,6 +232,8 @@ uint64_t Message::getPublishTimestamp() const { return impl_ ? impl_->getPublish uint64_t Message::getEventTimestamp() const { return impl_ ? impl_->getEventTimestamp() : 0ull; } +bool Message::hasEventTimestamp() const { return impl_ ? impl_->hasEventTimestamp() : false; } + const std::string& Message::getProducerName() const noexcept { if (!impl_) { return emptyString; diff --git a/lib/MessageImpl.cc b/lib/MessageImpl.cc index cfc573a7..2ef48d16 100644 --- a/lib/MessageImpl.cc +++ b/lib/MessageImpl.cc @@ -55,6 +55,8 @@ uint64_t MessageImpl::getEventTimestamp() const { } } +bool MessageImpl::hasEventTimestamp() const { return metadata.has_event_time(); } + void MessageImpl::setReplicationClusters(const std::vector& clusters) { google::protobuf::RepeatedPtrField r(clusters.begin(), clusters.end()); r.Swap(metadata.mutable_replicate_to()); diff --git a/lib/MessageImpl.h b/lib/MessageImpl.h index a234ca45..db974894 100644 --- a/lib/MessageImpl.h +++ b/lib/MessageImpl.h @@ -61,6 +61,7 @@ class MessageImpl { uint64_t getPublishTimestamp() const; uint64_t getEventTimestamp() const; + bool hasEventTimestamp() const; /** * Get the topic Name from which this message originated from From c2f127829699d37961924836869e95b1eef9adce Mon Sep 17 00:00:00 2001 From: Groene AI <270696204+groeneai@users.noreply.github.com> Date: Fri, 13 Nov 2026 23:38:41 +0000 Subject: [PATCH 2/2] Add a test for Message::hasEventTimestamp Co-Authored-By: Claude Opus 5.5 --- tests/MessageTest.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/MessageTest.cc b/tests/MessageTest.cc index 7f1ae4d6..a178bddc 100644 --- a/tests/MessageTest.cc +++ b/tests/MessageTest.cc @@ -63,6 +63,20 @@ bool compareMaps(const Map& lhs, const Map& rhs) { return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); } +TEST(MessageTest, testHasEventTimestamp) { + ASSERT_FALSE(Message().hasEventTimestamp()); + ASSERT_FALSE(MessageBuilder().setContent("msg").build().hasEventTimestamp()); + + // The Unix epoch is a valid event time, so it must not be reported as an unset one. + Message msg = MessageBuilder().setContent("msg").setEventTimestamp(0).build(); + ASSERT_TRUE(msg.hasEventTimestamp()); + ASSERT_EQ(msg.getEventTimestamp(), 0u); + + msg = MessageBuilder().setContent("msg").setEventTimestamp(1234).build(); + ASSERT_TRUE(msg.hasEventTimestamp()); + ASSERT_EQ(msg.getEventTimestamp(), 1234u); +} + TEST(MessageTest, testProperties) { MessageBuilder msgBuilder1; msgBuilder1.setProperty("property1", "value1");