فهرست منبع

feat(storage): shadow-read on Get handler against doc_store_

Same gate as the Exists shadow-read: only when mirror_healthy_ + zero
drift + non-system collection. Compares presence first (memstore-found
vs lmdb-found) then core fields (id, version, data) when both sides
return a document. Divergence logged at WARN with collection/id and the
diverging field.

The compare probe happens BEFORE encryption-decrypt / view-filter /
projection, so divergence is unambiguously attributable to substrate
state — not to a view transform applied on one side but not the other.

Filter parity itself is now guaranteed by 4eeb784's filter_eval lift,
so any Get divergence under view-where would be a substrate bug, not a
filter-implementation bug.
fszontagh 2 ماه پیش
والد
کامیت
e53adb57f6
1فایلهای تغییر یافته به همراه32 افزوده شده و 0 حذف شده
  1. 32 0
      service/src/database_grpc_impl.cpp

+ 32 - 0
service/src/database_grpc_impl.cpp

@@ -164,6 +164,38 @@ grpc::Status DatabaseGrpcImpl::Get(
     }
 
     auto doc = store_.get(targetCollection, request->id());
+
+    // v2.0 Stage 4 — shadow-read on Get. Same gates as Exists: only when
+    // the mirror is healthy + zero drift + non-system collection. Compares
+    // presence and core fields (id, version, data). Divergence is logged
+    // at WARN. MemoryStore stays authoritative.
+    if (!targetCollection.empty() && targetCollection[0] != '_'
+        && service_.mirrorHealthy() && service_.mirrorDriftCount() == 0) {
+        if (auto* ds = service_.docStore()) {
+            try {
+                auto lmdb_doc = ds->get(targetCollection, request->id());
+                const bool mem_found = doc.has_value();
+                const bool lmdb_found = lmdb_doc.has_value();
+                if (mem_found != lmdb_found) {
+                    spdlog::warn("v2.0 shadow-read Get presence divergence coll={} id={} "
+                                 "memstore={} lmdb={}",
+                                 targetCollection, request->id(), mem_found, lmdb_found);
+                } else if (mem_found && lmdb_found) {
+                    if (doc->id != lmdb_doc->id || doc->version != lmdb_doc->version
+                        || doc->data() != lmdb_doc->data()) {
+                        spdlog::warn("v2.0 shadow-read Get content divergence coll={} id={} "
+                                     "mem_ver={} lmdb_ver={}",
+                                     targetCollection, request->id(),
+                                     doc->version, lmdb_doc->version);
+                    }
+                }
+            } catch (const std::exception& e) {
+                spdlog::warn("v2.0 shadow-read Get query failed coll={} id={}: {}",
+                             targetCollection, request->id(), e.what());
+            }
+        }
+    }
+
     if (!doc) {
         response->set_found(false);
         return grpc::Status::OK;