Bläddra i källkod

docs: add PatchDocument and concurrency patterns to integration guide

fszontagh 3 månader sedan
förälder
incheckning
f633ed162c
2 ändrade filer med 43 tillägg och 3 borttagningar
  1. 1 0
      CLAUDE.md
  2. 42 3
      docs/integration-guide.md

+ 1 - 0
CLAUDE.md

@@ -30,6 +30,7 @@ cmake --build build -j$(nproc) && ./build/tests/test_vector_storage
 - JSON document store with collections, version history, field-level encryption
 - gRPC API with replication, events, file storage, migrations
 - **Vector Storage** — Embedding vectors stored alongside documents with SIMD-accelerated (AVX2/SSE4.1) cosine similarity search via `SimilaritySearch` RPC. Vectors use `_vector` document field, stored in parallel float arrays, persisted through WAL (`VEC_PUT`/`VEC_DELETE`) and snapshots (v3 format). Collection `vector_dimension` option is immutable after creation.
+- **Atomic Partial Updates** — `PatchDocument` RPC merges fields into existing documents atomically (server-side, within collection lock). Client `patch()` method. `update()` uses automatic optimistic locking with retry. See `docs/integration-guide.md` for concurrency patterns.
 
 ## Packaging
 

+ 42 - 3
docs/integration-guide.md

@@ -187,12 +187,15 @@ if (result) {
     std::cout << (*result)["name"] << std::endl;
 }
 
-// Update
-db.update("users", "user-123", {{"name", "Alice Smith"}});
+// Update (full document replacement, with automatic optimistic locking)
+db.update("users", "user-123", {{"name", "Alice Smith"}, {"email", "alice@example.com"}});
 
-// Update with optimistic locking (fails if version changed)
+// Update with explicit optimistic locking (fails if version changed)
 db.updateIfVersion("users", "user-123", {{"name", "Alice"}}, /*expectedVersion=*/2);
 
+// Patch — atomic partial update (only specified fields are modified)
+uint64_t newVer = db.patch("users", "user-123", {{"name", "Alice Smith"}});
+
 // Upsert (insert or update)
 auto [uid, isNew] = db.upsert("users", doc, "user-123");
 
@@ -203,6 +206,42 @@ db.remove("users", "user-123");
 bool found = db.exists("users", "user-123");
 ```
 
+### Concurrency: update() vs patch()
+
+When multiple clients modify the same document concurrently, choose the right method:
+
+**`patch()`** — use for most updates (recommended). Merges only the specified fields on the server, atomically. Two clients can safely modify different fields simultaneously:
+
+```cpp
+// Client A:                                    // Client B:
+db.patch("users", "user-123",                   db.patch("users", "user-123",
+    {{"name", "Alice Smith"}});                      {{"email", "alice@new.com"}});
+// Result: both fields updated, nothing lost
+```
+
+**`update()`** — full document replacement with automatic retry. Uses optimistic locking internally (reads current version, writes with version check, retries on conflict). Use when you need to replace the entire document:
+
+```cpp
+auto doc = db.get("users", "user-123");
+(*doc)["name"] = "Alice Smith";
+(*doc)["role"] = "admin";
+db.update("users", "user-123", *doc);  // replaces entire document
+```
+
+Note: `update()` is "last writer wins" for complete replacement — if two clients modify different fields via `update()`, the last one overwrites the other's changes. Use `patch()` to avoid this.
+
+**`updateIfVersion()`** — explicit optimistic locking. Use when you need to detect conflicts and handle them yourself:
+
+```cpp
+auto doc = db.get("users", "user-123");
+uint64_t version = (*doc)["_version"];
+(*doc)["balance"] = (*doc)["balance"].get<int>() + 100;
+if (!db.updateIfVersion("users", "user-123", *doc, version)) {
+    // Version conflict — someone else modified the document
+    // Re-read and retry, or report error to user
+}
+```
+
 ### Querying
 
 ```cpp