Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First attempt at making IChangeContext interface #26

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/SIL.Harmony.Core/IChangeContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace SIL.Harmony.Core;

public interface IChangeContext
{
public CommitBase Commit { get; }
ValueTask<ObjectSnapshot?> GetSnapshot(Guid entityId);
public async ValueTask<T?> GetCurrent<T>(Guid entityId) where T : class
{
var snapshot = await GetSnapshot(entityId);
if (snapshot is null) return null;
return (T) snapshot.Entity.DbObject;
}

public async ValueTask<bool> IsObjectDeleted(Guid entityId) => (await GetSnapshot(entityId))?.EntityIsDeleted ?? true;
internal IObjectBase Adapt(object obj);
}
35 changes: 35 additions & 0 deletions src/SIL.Harmony.Core/IObjectBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Text.Json.Serialization;

namespace SIL.Harmony.Core;

[JsonPolymorphic]
public interface IObjectBase
{
Guid Id { get; }
DateTimeOffset? DeletedAt { get; set; }

/// <summary>
/// provides the references this object has to other objects, when those objects are deleted
/// <see cref="RemoveReference"/> will be called to remove the reference
/// </summary>
/// <returns></returns>
public Guid[] GetReferences();
/// <summary>
/// remove a reference to another object, in some cases this may cause this object to be deleted
/// </summary>
/// <param name="id">id of the deleted object</param>
/// <param name="commit">
/// commit where the reference was removed
/// should be used to set the deleted date for this object
/// </param>
public void RemoveReference(Guid id, CommitBase commit);

public IObjectBase Copy();
/// <summary>
/// the name of the object type, this is used to discriminate between different types of objects in the snapshots table
/// </summary>
/// <returns>a stable type name of this object, should not change over time</returns>
public string GetObjectTypeName();
[JsonIgnore]
public object DbObject { get; }
}
53 changes: 53 additions & 0 deletions src/SIL.Harmony.Core/ObjectSnapshot.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;

namespace SIL.Harmony.Core;

public class ObjectSnapshot
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks like actually moving this would be more painful than I expected. There's also the fact that since it's stored in the Db changing the Commit type might cause problems there. Instead lets just extract an interface. It should have all the properties but the Commit type will be CommitBase on the interface. We then need to make an explicit interface implementation on ObjectSnapshot. That looks like this:
CommitBase IObjectSnapshot.Commit => Commit, this basically makes this Commit property only get used if the object is referred to as IObjectSnapshot if it's referred to as ObjectSnapshot then it will use the public property.

{
public static ObjectSnapshot ForTesting(CommitBase commit)
{
return new ObjectSnapshot
{
Commit = commit,
Entity = null!,
Id = Guid.Empty,
References = [],
CommitId = commit.Id,
EntityId = Guid.Empty,
IsRoot = false,
TypeName = "Test",
EntityIsDeleted = false
};
}
//determines column name used in projected object tables, changing this will require a migration
public const string ShadowRefName = "SnapshotId";
[JsonConstructor]
protected ObjectSnapshot()
{
}

[SetsRequiredMembers]
public ObjectSnapshot(IObjectBase entity, CommitBase commit, bool isRoot) : this()
{
Id = Guid.NewGuid();
Entity = entity;
References = entity.GetReferences();
EntityId = entity.Id;
EntityIsDeleted = entity.DeletedAt.HasValue;
TypeName = entity.GetObjectTypeName();
CommitId = commit.Id;
Commit = commit;
IsRoot = isRoot;
}

public required Guid Id { get; init; }
public required string TypeName { get; init; }
public required IObjectBase Entity { get; init; }
public required Guid[] References { get; init; }
public required Guid EntityId { get; init; }
public required bool EntityIsDeleted { get; init; }
public required Guid CommitId { get; init; }
public required CommitBase Commit { get; init; }
public required bool IsRoot { get; init; }
}
5 changes: 3 additions & 2 deletions src/SIL.Harmony/Changes/ChangeContext.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using SIL.Harmony.Core;
using SIL.Harmony.Db;
using SIL.Harmony.Entities;

namespace SIL.Harmony.Changes;

public class ChangeContext
public class ChangeContext : IChangeContext

Check failure on line 7 in src/SIL.Harmony/Changes/ChangeContext.cs

View workflow job for this annotation

GitHub Actions / build

'ChangeContext' does not implement interface member 'IChangeContext.Adapt(object)'. 'ChangeContext.Adapt(object)' cannot implement an interface member because it is not public.

Check failure on line 7 in src/SIL.Harmony/Changes/ChangeContext.cs

View workflow job for this annotation

GitHub Actions / build

'ChangeContext' does not implement interface member 'IChangeContext.Commit'. 'ChangeContext.Commit' cannot implement 'IChangeContext.Commit' because it does not have the matching return type of 'CommitBase'.

Check failure on line 7 in src/SIL.Harmony/Changes/ChangeContext.cs

View workflow job for this annotation

GitHub Actions / build

'ChangeContext' does not implement interface member 'IChangeContext.Adapt(object)'. 'ChangeContext.Adapt(object)' cannot implement an interface member because it is not public.

Check failure on line 7 in src/SIL.Harmony/Changes/ChangeContext.cs

View workflow job for this annotation

GitHub Actions / build

'ChangeContext' does not implement interface member 'IChangeContext.Commit'. 'ChangeContext.Commit' cannot implement 'IChangeContext.Commit' because it does not have the matching return type of 'CommitBase'.
{
private readonly SnapshotWorker _worker;
private readonly CrdtConfig _crdtConfig;
Expand All @@ -15,7 +16,7 @@
Commit = commit;
}

public Commit Commit { get; }
public Commit Commit { get; } // PROBLEM: Interface is CommitBase. How do I do this?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can just change the property type from Commit to CommitBase

public async ValueTask<ObjectSnapshot?> GetSnapshot(Guid entityId) => await _worker.GetSnapshot(entityId);
public async ValueTask<T?> GetCurrent<T>(Guid entityId) where T : class
{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Re: line +29]

this doesn't compile, it'll need to change to an explicit implementation IObjectBase IChangeContext.Adapt(object obj)

See this comment inline on Graphite.

Expand Down
53 changes: 1 addition & 52 deletions src/SIL.Harmony/Db/ObjectSnapshot.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
using SIL.Harmony.Core;
using SIL.Harmony.Entities;
using SIL.Harmony.Helpers;
Expand All @@ -24,57 +22,8 @@ public SimpleSnapshot(ObjectSnapshot snapshot) : this(snapshot.Id,
snapshot.CommitId,
snapshot.IsRoot,
snapshot.Commit.HybridDateTime,
snapshot.Commit.Hash,
snapshot.Commit.Hash, // PROBLEM: ObjectSnapshot.Commit is now a CommitBase which doesn't have a Hash property
snapshot.EntityIsDeleted)
{
}
}

public class ObjectSnapshot
{
public static ObjectSnapshot ForTesting(Commit commit)
{
return new ObjectSnapshot
{
Commit = commit,
Entity = null!,
Id = Guid.Empty,
References = [],
CommitId = commit.Id,
EntityId = Guid.Empty,
IsRoot = false,
TypeName = "Test",
EntityIsDeleted = false
};
}
//determines column name used in projected object tables, changing this will require a migration
public const string ShadowRefName = "SnapshotId";
[JsonConstructor]
protected ObjectSnapshot()
{
}

[SetsRequiredMembers]
public ObjectSnapshot(IObjectBase entity, Commit commit, bool isRoot) : this()
{
Id = Guid.NewGuid();
Entity = entity;
References = entity.GetReferences();
EntityId = entity.Id;
EntityIsDeleted = entity.DeletedAt.HasValue;
TypeName = entity.GetObjectTypeName();
CommitId = commit.Id;
Commit = commit;
IsRoot = isRoot;
}

public required Guid Id { get; init; }
public required string TypeName { get; init; }
public required IObjectBase Entity { get; init; }
public required Guid[] References { get; init; }
public required Guid EntityId { get; init; }
public required bool EntityIsDeleted { get; init; }
public required Guid CommitId { get; init; }
public required Commit Commit { get; init; }
public required bool IsRoot { get; init; }
}
33 changes: 1 addition & 32 deletions src/SIL.Harmony/Entities/IObjectBase.cs
Original file line number Diff line number Diff line change
@@ -1,39 +1,8 @@
using System.Text.Json.Serialization;
using SIL.Harmony.Core;

namespace SIL.Harmony.Entities;

[JsonPolymorphic]
public interface IObjectBase
{
Guid Id { get; }
DateTimeOffset? DeletedAt { get; set; }

/// <summary>
/// provides the references this object has to other objects, when those objects are deleted
/// <see cref="RemoveReference"/> will be called to remove the reference
/// </summary>
/// <returns></returns>
public Guid[] GetReferences();
/// <summary>
/// remove a reference to another object, in some cases this may cause this object to be deleted
/// </summary>
/// <param name="id">id of the deleted object</param>
/// <param name="commit">
/// commit where the reference was removed
/// should be used to set the deleted date for this object
/// </param>
public void RemoveReference(Guid id, Commit commit);

public IObjectBase Copy();
/// <summary>
/// the name of the object type, this is used to discriminate between different types of objects in the snapshots table
/// </summary>
/// <returns>a stable type name of this object, should not change over time</returns>
public string GetObjectTypeName();
[JsonIgnore]
public object DbObject { get; }
}

public interface IObjectBase<TThis> : IObjectBase, IPolyType where TThis : IPolyType
{
string IObjectBase.GetObjectTypeName() => TThis.TypeName;
Expand Down
Loading