Add DataModel.GetBeforeCommit to get entity state before a commit#81
Conversation
Adds GetBeforeCommit<T>(Guid commitId, Guid entityId) and GetBeforeCommit<T>(Commit commit, Guid entityId), mirroring GetAtCommit but returning the entity state as it was immediately before the given commit was applied. The methods return default when there is no state before the commit (i.e. the commit is the first commit, or it is the commit that created the entity). The snapshot-resolution logic shared with GetAtCommit is extracted into a private GetSnapshotAtCommit helper. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MveQ25eqoruavs2yTPTpFB
📝 WalkthroughWalkthrough
ChangesCommit Snapshot Reads
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ 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 |
Previously each of GetAtCommit/GetBeforeCommit and the shared GetSnapshotAtCommit helper created its own repository from the factory, so a single call created two or three repositories. Create the repository at the public entry point and pass it through to the private helpers instead.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/SIL.Harmony/DataModel.cs (1)
328-355: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider adding
where T : classgeneric constraint toGetAtCommitandGetBeforeCommit.In C# 9+, an unconstrained
T?meansTifTis a value type, rather thanNullable<T>. This can lead to unexpected behavior where returningdefaultyields an uninitialized struct rather thannull. Adding thewhere T : classconstraint aligns these methods withGetLatest<T>and ensures thatT?strictly represents a nullable reference type.♻️ Proposed refactor
- public async Task<T> GetAtCommit<T>(Commit commit, Guid entityId) + public async Task<T> GetAtCommit<T>(Commit commit, Guid entityId) where T : class { await using var repo = await _crdtRepositoryFactory.CreateRepository(); return await GetAtCommit<T>(commit, entityId, repo); } - private async Task<T> GetAtCommit<T>(Commit commit, Guid entityId, CrdtRepository repo) + private async Task<T> GetAtCommit<T>(Commit commit, Guid entityId, CrdtRepository repo) where T : class { var snapshot = await GetSnapshotAtCommit(commit, entityId, repo); ArgumentNullException.ThrowIfNull(snapshot); return (T)snapshot.Entity.DbObject; } - public async Task<T?> GetBeforeCommit<T>(Guid commitId, Guid entityId) + public async Task<T?> GetBeforeCommit<T>(Guid commitId, Guid entityId) where T : class { await using var repo = await _crdtRepositoryFactory.CreateRepository(); var commit = await repo.CurrentCommits().SingleAsync(c => c.Id == commitId); return await GetBeforeCommit<T>(commit, entityId, repo); } - public async Task<T?> GetBeforeCommit<T>(Commit commit, Guid entityId) + public async Task<T?> GetBeforeCommit<T>(Commit commit, Guid entityId) where T : class { await using var repo = await _crdtRepositoryFactory.CreateRepository(); return await GetBeforeCommit<T>(commit, entityId, repo); } - private async Task<T?> GetBeforeCommit<T>(Commit commit, Guid entityId, CrdtRepository repo) + private async Task<T?> GetBeforeCommit<T>(Commit commit, Guid entityId, CrdtRepository repo) where T : class🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/SIL.Harmony/DataModel.cs` around lines 328 - 355, Add a where T : class constraint to every public and private GetAtCommit and GetBeforeCommit overload, matching the existing GetLatest<T> contract. Ensure nullable T? in GetBeforeCommit represents only nullable reference types and keep the current method behavior otherwise unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/SIL.Harmony/DataModel.cs`:
- Around line 328-355: Add a where T : class constraint to every public and
private GetAtCommit and GetBeforeCommit overload, matching the existing
GetLatest<T> contract. Ensure nullable T? in GetBeforeCommit represents only
nullable reference types and keep the current method behavior otherwise
unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6da43833-74db-416d-987a-039652b51625
📒 Files selected for processing (2)
src/SIL.Harmony.Tests/ModelSnapshotTests.cssrc/SIL.Harmony/DataModel.cs
Adds
GetBeforeCommit<T>(Guid commitId, Guid entityId)andGetBeforeCommit<T>(Commit commit, Guid entityId), mirroringGetAtCommitbut returning the entity state as it was immediately before the given commit was applied.The methods return
defaultwhen there is no state before the commit (i.e. the commit is the first commit, or it is the commit that created the entity). The snapshot-resolution logic shared withGetAtCommitis extracted into a privateGetSnapshotAtCommithelper.🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Tests