diff --git a/pj_datastore/include/pj_datastore/object_store.hpp b/pj_datastore/include/pj_datastore/object_store.hpp index 37e4507..9dca500 100644 --- a/pj_datastore/include/pj_datastore/object_store.hpp +++ b/pj_datastore/include/pj_datastore/object_store.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -91,6 +92,11 @@ class ObjectStore { Expected registerTopic(const ObjectTopicDescriptor& descriptor); + // Resolve a topic id by (dataset_id, topic_name) without registering. Returns + // nullopt if no topic with that key exists. Used by hosts that need to bind a + // parser-side write surface to a topic the source already registered. + std::optional findTopic(DatasetId dataset_id, std::string_view topic_name) const; + const ObjectTopicDescriptor& descriptor(ObjectTopicId id) const; std::vector listTopics() const; diff --git a/pj_datastore/src/object_store.cpp b/pj_datastore/src/object_store.cpp index 60a8f13..e53f85c 100644 --- a/pj_datastore/src/object_store.cpp +++ b/pj_datastore/src/object_store.cpp @@ -21,6 +21,17 @@ Expected ObjectStore::registerTopic(const ObjectTopicDescriptor& return id; } +std::optional ObjectStore::findTopic( + DatasetId dataset_id, std::string_view topic_name) const { + std::shared_lock lock(store_mutex_); + for (const auto& [tid, series] : topics_) { + if (series->descriptor.dataset_id == dataset_id && series->descriptor.topic_name == topic_name) { + return tid; + } + } + return std::nullopt; +} + const ObjectTopicDescriptor& ObjectStore::descriptor(ObjectTopicId id) const { std::shared_lock lock(store_mutex_); const auto* s = findSeries(id); diff --git a/pj_datastore/tests/object_store_test.cpp b/pj_datastore/tests/object_store_test.cpp index f2f4492..65dddc6 100644 --- a/pj_datastore/tests/object_store_test.cpp +++ b/pj_datastore/tests/object_store_test.cpp @@ -48,6 +48,21 @@ TEST(ObjectStoreTest, SameNameDifferentDatasetOk) { EXPECT_NE(id1.id, id2_or->id); } +TEST(ObjectStoreTest, FindTopicReturnsRegisteredId) { + ObjectStore store; + auto id = registerTestTopic(store, "cam/image"); + auto found = store.findTopic(1, "cam/image"); + ASSERT_TRUE(found.has_value()); + EXPECT_EQ(found->id, id.id); +} + +TEST(ObjectStoreTest, FindTopicMissingReturnsNullopt) { + ObjectStore store; + registerTestTopic(store, "cam/image"); + EXPECT_FALSE(store.findTopic(1, "other/topic").has_value()); + EXPECT_FALSE(store.findTopic(99, "cam/image").has_value()); +} + TEST(ObjectStoreTest, ListTopics) { ObjectStore store; auto id1 = registerTestTopic(store, "topic_a");