Explorar o código

feat: migrate remaining Document.data callsites (phase B T6)

Service-side cleanup. Each caller materialises through doc.data() and
writes back via set_data() so the binary tree remains canonical:

- conflict_resolver.cpp: resolveMerge — fetch both trees, walk fields,
  build the merged tree, set_data once on the merged Document.
- encryption_manager.cpp: encrypt / decrypt / preserveUnchangedEncryption
  bridge to the existing recursive json helpers via materialise + write-
  back. Same on-disk semantics as v1.10.
- view_manager.cpp: loadFromStore reads via doc.data(); createView
  persists via set_data(toJson(view)).
- collection_config_manager.cpp: same pattern (fromJson(doc.data()) read,
  doc.set_data(toJson(cfg)) write).
- database_service.cpp: event-publish callback writes event.data via
  doc->data() lazy view.
fszontagh hai 2 meses
pai
achega
9dfa1dce12

+ 2 - 2
service/src/config/collection_config_manager.cpp

@@ -38,7 +38,7 @@ void CollectionConfigManager::loadFromStore() {
     auto result = store_.find(SYSTEM_COLLECTION, q);
     auto result = store_.find(SYSTEM_COLLECTION, q);
     for (const auto& doc : result.documents) {
     for (const auto& doc : result.documents) {
         if (doc.id.empty()) continue;
         if (doc.id.empty()) continue;
-        cache_[doc.id] = fromJson(doc.data);
+        cache_[doc.id] = fromJson(doc.data());
     }
     }
     spdlog::info("CollectionConfigManager: loaded {} configs from {}",
     spdlog::info("CollectionConfigManager: loaded {} configs from {}",
                  cache_.size(), SYSTEM_COLLECTION);
                  cache_.size(), SYSTEM_COLLECTION);
@@ -59,7 +59,7 @@ bool CollectionConfigManager::setConfig(const std::string& collection,
     // Persist via upsert (document ID = collection name)
     // Persist via upsert (document ID = collection name)
     Document doc;
     Document doc;
     doc.id = collection;
     doc.id = collection;
-    doc.data = toJson(cfg);
+    doc.set_data(toJson(cfg));
     try {
     try {
         store_.upsert(SYSTEM_COLLECTION, doc);
         store_.upsert(SYSTEM_COLLECTION, doc);
     } catch (const std::exception& e) {
     } catch (const std::exception& e) {

+ 1 - 1
service/src/database_service.cpp

@@ -631,7 +631,7 @@ void DatabaseService::setupComponents() {
             ).count();
             ).count();
             event.nodeId = config_.nodeId;
             event.nodeId = config_.nodeId;
             if (doc) {
             if (doc) {
-                event.data = doc->data;
+                event.data = doc->data();
             }
             }
             events_->publish(event);
             events_->publish(event);
         }
         }

+ 14 - 4
service/src/encryption/encryption_manager.cpp

@@ -194,8 +194,11 @@ void EncryptionManager::encryptSensitiveFields(Document& doc) {
 
 
     std::lock_guard lock(mutex_);
     std::lock_guard lock(mutex_);
 
 
-    // Traverse JSON and encrypt sensitive fields
-    encryptJsonField(doc.data, "");
+    // Materialise once, mutate via the existing recursive helper, then
+    // re-encode. encryptJsonField mutates the tree in place.
+    nlohmann::json tree = doc.data();
+    encryptJsonField(tree, "");
+    doc.set_data(tree);
 
 
     doc.encrypted = true;
     doc.encrypted = true;
 }
 }
@@ -208,7 +211,9 @@ void EncryptionManager::decryptSensitiveFields(Document& doc) {
     std::lock_guard lock(mutex_);
     std::lock_guard lock(mutex_);
 
 
     // Traverse JSON and decrypt sensitive fields
     // Traverse JSON and decrypt sensitive fields
-    decryptJsonField(doc.data, "", doc.collection, doc.id);
+    nlohmann::json tree = doc.data();
+    decryptJsonField(tree, "", doc.collection, doc.id);
+    doc.set_data(tree);
 }
 }
 
 
 void EncryptionManager::preserveUnchangedEncryption(Document& newDoc, const Document& existingDoc) {
 void EncryptionManager::preserveUnchangedEncryption(Document& newDoc, const Document& existingDoc) {
@@ -217,7 +222,12 @@ void EncryptionManager::preserveUnchangedEncryption(Document& newDoc, const Docu
     }
     }
 
 
     std::lock_guard lock(mutex_);
     std::lock_guard lock(mutex_);
-    preserveUnchangedJsonField(newDoc.data, existingDoc.data, "");
+    // existingDoc is const — we need both trees in scope long enough to
+    // walk them. Decode both, mutate newTree, write back.
+    nlohmann::json newTree = newDoc.data();
+    const nlohmann::json& existingTree = existingDoc.data();
+    preserveUnchangedJsonField(newTree, existingTree, "");
+    newDoc.set_data(newTree);
 }
 }
 
 
 void EncryptionManager::preserveUnchangedJsonField(nlohmann::json& newObj,
 void EncryptionManager::preserveUnchangedJsonField(nlohmann::json& newObj,

+ 13 - 8
service/src/replication/conflict_resolver.cpp

@@ -112,22 +112,27 @@ std::optional<Document> ConflictResolver::resolveMerge(
         merged.version = std::max(local.version, remote.version) + 1;
         merged.version = std::max(local.version, remote.version) + 1;
         merged.updatedAt = std::max(local.updatedAt, remote.updatedAt);
         merged.updatedAt = std::max(local.updatedAt, remote.updatedAt);
 
 
-        // Merge JSON data
-        // For each field in remote that doesn't exist in local, add it
-        for (const auto& [key, value] : remote.data.items()) {
-            if (!local.data.contains(key)) {
-                merged.data[key] = value;
-            } else if (local.data[key] != value) {
+        // Merge JSON data. Materialise both trees once (we have to walk
+        // the full structure anyway), mutate the working tree, then write
+        // it back via set_data so the binary view is canonical.
+        const nlohmann::json& localTree = local.data();
+        const nlohmann::json& remoteTree = remote.data();
+        nlohmann::json mergedTree = localTree;
+        for (const auto& [key, value] : remoteTree.items()) {
+            if (!localTree.contains(key)) {
+                mergedTree[key] = value;
+            } else if (localTree[key] != value) {
                 // Field exists in both with different values
                 // Field exists in both with different values
                 // For now, use the most recently updated value
                 // For now, use the most recently updated value
                 if (remote.updatedAt > local.updatedAt) {
                 if (remote.updatedAt > local.updatedAt) {
-                    merged.data[key] = value;
+                    mergedTree[key] = value;
                 }
                 }
             }
             }
         }
         }
+        merged.set_data(mergedTree);
 
 
         spdlog::debug("Conflict resolved (merge): combined {} and {} fields",
         spdlog::debug("Conflict resolved (merge): combined {} and {} fields",
-                     local.data.size(), remote.data.size());
+                     localTree.size(), remoteTree.size());
 
 
         return merged;
         return merged;
 
 

+ 2 - 2
service/src/views/view_manager.cpp

@@ -83,7 +83,7 @@ void ViewManager::loadFromStore() {
     Query q;
     Query q;
     auto result = store_.find(SYSTEM_COLLECTION, q);
     auto result = store_.find(SYSTEM_COLLECTION, q);
     for (const auto& doc : result.documents) {
     for (const auto& doc : result.documents) {
-        ViewInfo v = fromJson(doc.data);
+        ViewInfo v = fromJson(doc.data());
         if (v.name.empty()) continue;
         if (v.name.empty()) continue;
         cache_[v.name] = v;
         cache_[v.name] = v;
     }
     }
@@ -128,7 +128,7 @@ bool ViewManager::createView(const ViewInfo& view, std::string& errorOut) {
     // Persist to _views (view name is the document ID)
     // Persist to _views (view name is the document ID)
     Document doc;
     Document doc;
     doc.id = v.name;
     doc.id = v.name;
-    doc.data = toJson(v);
+    doc.set_data(toJson(v));
     try {
     try {
         std::string id = store_.insert(SYSTEM_COLLECTION, doc);
         std::string id = store_.insert(SYSTEM_COLLECTION, doc);
         if (id.empty()) {
         if (id.empty()) {