Skip to content

Commit

Permalink
use timestamp to identify model changes
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexNav73 committed Mar 19, 2024
1 parent f2b0aa9 commit 9fc3c8f
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ void ImplementUpdateMethod(ModelShard modelShard)

void ImplementSaveMethod(ModelShard modelShard)
{
code.WriteLine($"public void Save(int changeId, IHistoryRepository repository)");
code.WriteLine($"public void Save(long changeId, IHistoryRepository repository)");
code.Block(() =>
{
foreach (var collection in modelShard.Collections)
Expand All @@ -476,7 +476,7 @@ void ImplementSaveMethod(ModelShard modelShard)

void ImplementLoadMethod(ModelShard modelShard)
{
code.WriteLine($"public void Load(int changeId, IHistoryRepository repository)");
code.WriteLine($"public void Load(long changeId, IHistoryRepository repository)");
code.Block(() =>
{
foreach (var collection in modelShard.Collections)
Expand Down
8 changes: 4 additions & 4 deletions src/CoreCraft.Storage.Json/JsonRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,14 @@ public void Save<TParent, TChild>(IRelation<TParent, TChild> relation)
}
}

public void Save<TEntity, TProperties>(int changeId, ICollectionChangeSet<TEntity, TProperties> changes)
public void Save<TEntity, TProperties>(long changeId, ICollectionChangeSet<TEntity, TProperties> changes)
where TEntity : Entity
where TProperties : Properties
{
throw new NotImplementedException();
}

public void Save<TParent, TChild>(int changeId, IRelationChangeSet<TParent, TChild> changes)
public void Save<TParent, TChild>(long changeId, IRelationChangeSet<TParent, TChild> changes)
where TParent : Entity
where TChild : Entity
{
Expand Down Expand Up @@ -204,14 +204,14 @@ public void Load<TParent, TChild>(IMutableRelation<TParent, TChild> relation, IE
}
}

public void Load<TEntity, TProperties>(int changeId, ICollectionChangeSet<TEntity, TProperties> changes)
public void Load<TEntity, TProperties>(long changeId, ICollectionChangeSet<TEntity, TProperties> changes)
where TEntity : Entity
where TProperties : Properties
{
throw new NotImplementedException();
}

public void Load<TParent, TChild>(int changeId, IRelationChangeSet<TParent, TChild> changes)
public void Load<TParent, TChild>(long changeId, IRelationChangeSet<TParent, TChild> changes)
where TParent : Entity
where TChild : Entity
{
Expand Down
6 changes: 4 additions & 2 deletions src/CoreCraft.Storage.Sqlite/ISqliteRepository.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using CoreCraft.Persistence;
using CoreCraft.ChangesTracking;
using CoreCraft.Core;
using CoreCraft.Persistence;
using CoreCraft.Persistence.History;
using System.Data;

Expand Down Expand Up @@ -31,7 +33,7 @@ public interface ISqliteRepository : IRepository, IHistoryRepository, IDisposabl
/// TODO: Write documentation
/// </summary>
/// <returns>TODO: Write documentation</returns>
int GetMaxChangeId();
IEnumerable<IModelChanges> LoadChanges(IEnumerable<IModelShard> shards);

/// <summary>
/// Sets new database version
Expand Down
31 changes: 16 additions & 15 deletions src/CoreCraft.Storage.Sqlite/QueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ internal static class History
CREATE TABLE IF NOT EXISTS [__CollectionHistory] (
[Id] INTEGER NOT NULL,
[Collection] TEXT NOT NULL,
[ChangeId] INTEGER NOT NULL,
[ChangeId] NUMERIC NOT NULL,
[Action] INTEGER NOT NULL,
[EntityId] TEXT NOT NULL,
[OldProperties] TEXT,
Expand All @@ -62,17 +62,6 @@ PRIMARY KEY([Id])
);
""";

internal const string SelectMaxChangeId = """
SELECT [ChangeId]
FROM (
SELECT [ChangeId] FROM [__CollectionHistory]
UNION ALL
SELECT [ChangeId] FROM [__RelationHistory]
)
ORDER BY [ChangeId] DESC
LIMIT 1;
""";

internal const string InsertIntoCollectionTable = """
INSERT INTO [__CollectionHistory] ([Collection], [ChangeId], [Action], [EntityId], [OldProperties], [NewProperties])
VALUES ($Collection, $ChangeId, $Action, $EntityId, $OldProperties, $NewProperties);
Expand All @@ -82,7 +71,7 @@ INSERT INTO [__CollectionHistory] ([Collection], [ChangeId], [Action], [EntityId
CREATE TABLE IF NOT EXISTS [__RelationHistory] (
[Id] INTEGER NOT NULL,
[Relation] TEXT NOT NULL,
[ChangeId] INTEGER NOT NULL,
[ChangeId] NUMERIC NOT NULL,
[Action] INTEGER NOT NULL,
[ParentId] TEXT NOT NULL,
[ChildId] TEXT NOT NULL,
Expand All @@ -95,17 +84,29 @@ INSERT INTO [__RelationHistory] ([Relation], [ChangeId], [Action], [ParentId], [
VALUES ($Relation, $ChangeId, $Action, $ParentId, $ChildId);
""";

internal static string SelectCollectionTable(int changeId, string collection) => $"""
internal static string SelectCollectionTable(long changeId, string collection) => $"""
SELECT [Action], [EntityId], [OldProperties], [NewProperties]
FROM [__CollectionHistory]
WHERE [ChangeId] = {changeId} AND [Collection] = '{collection}';
""";

internal static string SelectRelationTable(int changeId, string relation) => $"""
internal static string SelectRelationTable(long changeId, string relation) => $"""
SELECT [Action], [ParentId], [ChildId]
FROM [__RelationHistory]
WHERE [ChangeId] = {changeId} AND [Relation] = '{relation}';
""";

internal const string SelectChangeIds = """
SELECT DISTINCT *
FROM (
SELECT [ChangeId]
FROM [__CollectionHistory]
UNION ALL
SELECT [ChangeId]
FROM [__RelationHistory]
)
ORDER BY [ChangeId] ASC;
""";
}

internal static class Migrations
Expand Down
35 changes: 25 additions & 10 deletions src/CoreCraft.Storage.Sqlite/SqliteRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ public void Save<TParent, TChild>(IRelation<TParent, TChild> relation)
}
}

public void Save<TEntity, TProperties>(int changeId, ICollectionChangeSet<TEntity, TProperties> changes)
public void Save<TEntity, TProperties>(long changeId, ICollectionChangeSet<TEntity, TProperties> changes)
where TEntity : Entity
where TProperties : Properties
{
Expand Down Expand Up @@ -218,7 +218,7 @@ public void Save<TEntity, TProperties>(int changeId, ICollectionChangeSet<TEntit
}
}

public void Save<TParent, TChild>(int changeId, IRelationChangeSet<TParent, TChild> changes)
public void Save<TParent, TChild>(long changeId, IRelationChangeSet<TParent, TChild> changes)
where TParent : Entity
where TChild : Entity
{
Expand Down Expand Up @@ -305,7 +305,7 @@ public void Load<TParent, TChild>(IMutableRelation<TParent, TChild> relation, IE
}
}

public void Load<TEntity, TProperties>(int changeId, ICollectionChangeSet<TEntity, TProperties> changes)
public void Load<TEntity, TProperties>(long changeId, ICollectionChangeSet<TEntity, TProperties> changes)
where TEntity : Entity
where TProperties : Properties
{
Expand All @@ -325,7 +325,7 @@ public void Load<TEntity, TProperties>(int changeId, ICollectionChangeSet<TEntit
}
}

public void Load<TParent, TChild>(int changeId, IRelationChangeSet<TParent, TChild> changes)
public void Load<TParent, TChild>(long changeId, IRelationChangeSet<TParent, TChild> changes)
where TParent : Entity
where TChild : Entity
{
Expand All @@ -344,21 +344,36 @@ public void Load<TParent, TChild>(int changeId, IRelationChangeSet<TParent, TChi
}
}

public int GetMaxChangeId()
public IEnumerable<IModelChanges> LoadChanges(IEnumerable<IModelShard> shards)
{
var command = CreateCommand(History.SelectMaxChangeId);
var changes = new List<IModelChanges>();
using var command = CreateCommand(History.SelectChangeIds);

Log(command);

using var reader = command.ExecuteReader();
if (reader.Read())
while (reader.Read())
{
var changeId = reader.GetInt32(0);
var timestamp = reader.GetInt64(0);
var modelChanges = new ModelChanges(timestamp);

return changeId;
foreach (var shard in shards.Cast<IFrameFactory>())
{
var change = (IChangesFrameEx)shard.Create();
change.Load(timestamp, this);
if (change.HasChanges())
{
modelChanges.AddOrGet(change);
}
}

if (modelChanges.Any())
{
changes.Add(modelChanges);
}
}

return 0;
return changes;
}

internal bool Exists(CollectionInfo collection)
Expand Down
33 changes: 3 additions & 30 deletions src/CoreCraft.Storage.Sqlite/SqliteStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,9 @@ public void Save(IEnumerable<IModelChanges> modelChanges)
repository.ExecuteNonQuery(QueryBuilder.History.CreateCollectionTable);
repository.ExecuteNonQuery(QueryBuilder.History.CreateRelationTable);
var baseId = repository.GetMaxChangeId();
foreach (var (idx, change) in modelChanges.Select((c, idx) => (idx, c)))
foreach (var change in modelChanges)
{
foreach (var frame in change.Cast<IChangesFrameEx>())
{
frame.Save(baseId + idx, repository);
}
change.Save(repository);
}
});
}
Expand Down Expand Up @@ -121,30 +117,7 @@ public IEnumerable<IModelChanges> Load(IEnumerable<IModelShard> modelShards)
repository.ExecuteNonQuery(QueryBuilder.History.CreateCollectionTable);
repository.ExecuteNonQuery(QueryBuilder.History.CreateRelationTable);

var changes = new List<IModelChanges>();
var numOfChanges = repository.GetMaxChangeId();

for (int i = 0; i <= numOfChanges; i++)
{
var modelChanges = new ModelChanges();

foreach (var shard in modelShards.Cast<IFrameFactory>())
{
var change = (IChangesFrameEx)shard.Create();
change.Load(i, repository);
if (change.HasChanges())
{
modelChanges.AddOrGet(change);
}
}

if (modelChanges.Any())
{
changes.Add(modelChanges);
}
}

return changes;
return repository.LoadChanges(modelShards);
}

private void Transaction(string path, Action<ISqliteRepository> action)
Expand Down
4 changes: 2 additions & 2 deletions src/CoreCraft/ChangesTracking/IChangesFrameEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public interface IChangesFrameEx : IChangesFrame
/// - The `changeId` parameter allows for associating the changes with a specific event or action.
/// - The `repository` parameter is an <see cref="IHistoryRepository" /> instance responsible for handling the storage and retrieval of history data.
/// </remarks>
void Save(int changeId, IHistoryRepository repository);
void Save(long changeId, IHistoryRepository repository);

/// <summary>
/// Loads changes history from the specified repository for the given change identifier.
Expand All @@ -81,5 +81,5 @@ public interface IChangesFrameEx : IChangesFrame
/// - The `changeId` parameter specifies the unique identifier of the change set to be loaded.
/// - The `repository` parameter is an <see cref="IHistoryRepository" /> instance responsible for providing access to changes.
/// </remarks>
void Load(int changeId, IHistoryRepository repository);
void Load(long changeId, IHistoryRepository repository);
}
10 changes: 9 additions & 1 deletion src/CoreCraft/ChangesTracking/IModelChanges.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace CoreCraft.ChangesTracking;
using CoreCraft.Persistence.History;

namespace CoreCraft.ChangesTracking;

/// <summary>
/// A collection of changes for a model
Expand Down Expand Up @@ -36,4 +38,10 @@ bool TryGetFrame<T>(out T frame)
/// </summary>
/// <returns>A new inverted changes</returns>
IModelChanges Invert();

/// <summary>
///
/// </summary>
/// <param name="repository"></param>
void Save(IHistoryRepository repository);
}
23 changes: 18 additions & 5 deletions src/CoreCraft/ChangesTracking/ModelChanges.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections;
using CoreCraft.Persistence.History;

namespace CoreCraft.ChangesTracking;

Expand All @@ -7,16 +8,19 @@ public sealed class ModelChanges : IMutableModelChanges
{
private readonly HashSet<IChangesFrameEx> _frames;

private long _timestamp;

/// <summary>
/// Ctor
/// </summary>
public ModelChanges()
: this(new HashSet<IChangesFrameEx>(ChangesFrameComparer.Instance))
public ModelChanges(long timestamp)
: this(timestamp, new HashSet<IChangesFrameEx>(ChangesFrameComparer.Instance))
{
}

private ModelChanges(HashSet<IChangesFrameEx> frames)
private ModelChanges(long timestamp, HashSet<IChangesFrameEx> frames)
{
_timestamp = timestamp;
_frames = frames;
}

Expand Down Expand Up @@ -45,7 +49,7 @@ public IModelChanges Invert()
{
var frames = _frames.Select(x => x.Invert()).Cast<IChangesFrameEx>();

return new ModelChanges(new HashSet<IChangesFrameEx>(frames, ChangesFrameComparer.Instance));
return new ModelChanges(_timestamp, new HashSet<IChangesFrameEx>(frames, ChangesFrameComparer.Instance));
}

/// <inheritdoc />
Expand All @@ -71,7 +75,16 @@ public IMutableModelChanges Merge(IModelChanges changes)
}
}

return new ModelChanges(result);
return new ModelChanges(_timestamp, result);
}

/// <inheritdoc />
public void Save(IHistoryRepository repository)
{
foreach (var frame in _frames)
{
frame.Save(_timestamp, repository);
}
}

/// <inheritdoc />
Expand Down
8 changes: 4 additions & 4 deletions src/CoreCraft/Core/IFeature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ public interface IFeature
/// </summary>
/// <typeparam name="TEntity">A type of an entity</typeparam>
/// <typeparam name="TProperties">A type of properties</typeparam>
/// <param name="context">A context with utility methods</param>
/// <param name="factory">A factory for changes frames</param>
/// <param name="collection">A base collection which will be wrapped in this method</param>
/// <returns>A new collection with adjusted behavior</returns>
IMutableCollection<TEntity, TProperties> Decorate<TEntity, TProperties>(
IFrameFactory context,
IFrameFactory factory,
IMutableCollection<TEntity, TProperties> collection)
where TEntity : Entity
where TProperties : Properties;
Expand All @@ -40,11 +40,11 @@ IMutableCollection<TEntity, TProperties> Decorate<TEntity, TProperties>(
/// </summary>
/// <typeparam name="TParent">A type of a parent entity</typeparam>
/// <typeparam name="TChild">A type of a child entity</typeparam>
/// <param name="context">A context with utility methods</param>
/// <param name="factory">A factory for changes frames</param>
/// <param name="relation">A base relation which will be wrapped in this method</param>
/// <returns>A new relation with adjusted behavior</returns>
IMutableRelation<TParent, TChild> Decorate<TParent, TChild>(
IFrameFactory context,
IFrameFactory factory,
IMutableRelation<TParent, TChild> relation)
where TParent : Entity
where TChild : Entity;
Expand Down
Loading

0 comments on commit 9fc3c8f

Please sign in to comment.