Просмотр исходного кода

feat(storage): add DocumentStore::exists() bound-check

Stage 4 Task 4.1 follow-up — extends the DocumentStore interface with a
cheap existence check. Default implementation is get().has_value() so
LmdbDocumentStore inherits the behavior; backends with a no-materialise
fast path (e.g. mdb_get sniff that ignores v.mv_size) may override.

This is the first method handlers will reach for once Stage 4 starts
migrating actual gRPC routes — the Exists RPC is a one-liner store_.exists()
on the v1.x path today.

Test coverage in tests/test_document_store.cpp:
- exists() returns true for present doc
- exists() returns false for absent id
- exists() returns false for absent collection
fszontagh 2 месяцев назад
Родитель
Сommit
08030237b9
2 измененных файлов с 33 добавлено и 0 удалено
  1. 10 0
      service/src/storage/document_store.hpp
  2. 23 0
      tests/test_document_store.cpp

+ 10 - 0
service/src/storage/document_store.hpp

@@ -49,6 +49,16 @@ public:
     virtual std::optional<smartbotic::database::Document>
     get(std::string_view collection, std::string_view id) = 0;
 
+    // Cheap existence check — does NOT materialise the document. Returns
+    // false if either the collection or the document is absent.
+    //
+    // Default implementation is `get(...).has_value()` so existing
+    // implementations don't have to override; backends with a cheaper path
+    // (e.g. mdb_get with v.mv_size==0 sniff) may override.
+    virtual bool exists(std::string_view collection, std::string_view id) {
+        return get(collection, id).has_value();
+    }
+
     // Delete a document. Returns true if it existed, false otherwise.
     virtual bool del(std::string_view collection, std::string_view id) = 0;
 

+ 23 - 0
tests/test_document_store.cpp

@@ -184,6 +184,27 @@ void test_get_from_nonexistent_collection_returns_nullopt() {
     check(!g.has_value(), "get on nonexistent collection returns nullopt");
 }
 
+// =========================================================================
+// Stage 4 Task 4.1 — exists() bound-check (no materialisation needed).
+// Default impl is get().has_value(); LmdbDocumentStore inherits it.
+// =========================================================================
+
+void test_exists_present_returns_true() {
+    TmpEnv t("exists-true");
+    LmdbDocumentStore store(t.env);
+    store.put("c", "k", make_doc("k", "c", nlohmann::json{{"v", 1}}));
+    check(store.exists("c", "k"), "exists() returns true for present doc");
+}
+
+void test_exists_absent_returns_false() {
+    TmpEnv t("exists-false");
+    LmdbDocumentStore store(t.env);
+    store.put("c", "k", make_doc("k", "c", nlohmann::json{{"v", 1}}));
+    check(!store.exists("c", "missing"), "exists() returns false for absent id");
+    check(!store.exists("no-such-coll", "k"),
+          "exists() returns false for absent collection");
+}
+
 void test_del_missing_returns_false() {
     TmpEnv t("del-missing");
     LmdbDocumentStore store(t.env);
@@ -704,6 +725,8 @@ int main() {
     test_put_overwrite_replaces();
     test_get_missing_returns_nullopt();
     test_get_from_nonexistent_collection_returns_nullopt();
+    test_exists_present_returns_true();
+    test_exists_absent_returns_false();
     test_del_missing_returns_false();
     test_del_then_get_returns_nullopt();
     test_del_returns_true_for_existing();