Partial update#886
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe PR modifies ChangesDocument update adapter filtering
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR adds partial-update semantics to
Confidence Score: 4/5The change is safe to merge; the core filtering logic is correct for all adapter backends and the full document is still returned to the caller. The filtering logic is logically correct and well-targeted, but the returned document is assembled from a pre-transaction merge snapshot, so in concurrent workloads the caller may see stale values for fields that were not part of the partial update. Additionally, no tests exercise the new code path where only a subset of attributes is supplied — the existing tests always pass full documents and therefore never activate the $inputKeys filter. src/Database/Database.php — specifically the new filter block at lines 6338–6342 and the stale-return interaction with the castingAfter/decode path for non-updated fields. Important Files Changed
Reviews (1): Last reviewed commit: "partialUpdate" | Re-trigger Greptile |
| $internalKeys = \array_column(self::INTERNAL_ATTRIBUTES, '$id'); | ||
| $allowedKeys = \array_flip(\array_merge($inputKeys, $internalKeys)); | ||
| $adapterDocument = new Document(\array_intersect_key($document->getArrayCopy(), $allowedKeys)); | ||
|
|
||
| $this->adapter->updateDocument($collection, $id, $adapterDocument, $skipPermissionsUpdate); |
There was a problem hiding this comment.
Stale return value for non-updated fields in high-concurrency scenarios
$adapterDocument correctly limits what the adapter writes to the DB (only $inputKeys + internal fields), but $document — which is returned to the caller — is the in-memory merged snapshot assembled at the start of the transaction (old values merged over by the user's input). If another transaction writes to a non-input field between this transaction's getDocument fetch and the adapter write, the caller will receive stale values for those non-updated fields in the returned document, even though the cache is purged and subsequent reads would be accurate.
This diverges from the previous behaviour where writing the full merged document meant the caller's return value always matched what was just persisted. Consider re-fetching the document (or merging in $adapterDocument's updated fields into the final return) to guarantee the caller receives a consistent snapshot.
| $skipPermissionsUpdate = ($originalPermissions === $currentPermissions); | ||
| } | ||
| $createdAt = $document->getCreatedAt(); | ||
| $inputKeys = \array_keys($document->getArrayCopy()); |
There was a problem hiding this comment.
No dedicated tests for the partial-update path
$inputKeys is captured here to restrict which columns the adapter writes. The existing testUpdateDocument test always passes a fully-populated document, so $inputKeys equals the full attribute set and the new filtering is never exercised. A test that passes a document with only a subset of attributes and then asserts the omitted columns retain their previous DB values would prevent regressions in this new code path.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Summary by CodeRabbit