Skip to content

Commit

Permalink
Handle some features that came up during integration with the app
Browse files Browse the repository at this point in the history
  • Loading branch information
halgari committed Jun 12, 2024
1 parent c9fe3c2 commit 45ee0a7
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 9 deletions.
6 changes: 6 additions & 0 deletions src/NexusMods.MnemonicDB.Abstractions/IDb.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using NexusMods.MnemonicDB.Abstractions.Attributes;
using NexusMods.MnemonicDB.Abstractions.DatomIterators;
Expand Down Expand Up @@ -77,6 +78,11 @@ public Entities<EntityIds, TModel> GetReverse<TModel>(EntityId id, Attribute<Ent
/// </summary>
IEnumerable<EntityId> FindIndexed<TValue, TLowLevel>(Attribute<TValue, TLowLevel> attribute, TValue value);

/// <summary>
/// Finds all the entity ids that have the given attribute with the given value.
/// </summary>
IEnumerable<EntityId> FindIndexed(ReferenceAttribute attribute, EntityId value);

/// <summary>
/// Finds all the datoms have the given attribute with the given value.
/// </summary>
Expand Down
27 changes: 27 additions & 0 deletions src/NexusMods.MnemonicDB.Abstractions/Models/ModelExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using System.Reactive.Linq;
using DynamicData;
using NexusMods.MnemonicDB.Abstractions.Query;

namespace NexusMods.MnemonicDB.Abstractions.Models;

/// <summary>
/// Extensions for models
/// </summary>
public static class ModelExtensions
{
/// <summary>
/// An observable that emits the revisions of the model, terminates when the model is deleted
/// or otherwise invalid
/// </summary>
public static IObservable<TModel> Revisions<TModel>(this TModel model)
where TModel : IReadOnlyModel<TModel>
{
// Pull these out of the model so that we don't keep the model data lying around in memory
var conn = model.Db.Connection;
var id = model.Id;
return conn.ObserveDatoms(id)
.QueryWhenChanged(_ => TModel.Create(conn.Db, id))
.TakeWhile(m => m.IsValid());
}
}
25 changes: 25 additions & 0 deletions src/NexusMods.MnemonicDB.Abstractions/Query/ObservableDatoms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Reactive.Linq;
using DynamicData;
using NexusMods.MnemonicDB.Abstractions.Attributes;
using NexusMods.MnemonicDB.Abstractions.DatomComparators;
using NexusMods.MnemonicDB.Abstractions.DatomIterators;
using NexusMods.MnemonicDB.Abstractions.IndexSegments;
Expand Down Expand Up @@ -37,6 +38,30 @@ public static IObservable<IChangeSet<Datom>> ObserveDatoms(this IConnection conn
return conn.ObserveDatoms(SliceDescriptor.Create(id, conn.Registry));
}

/// <summary>
/// Observe changes for a given attribue on a given entity id
/// </summary>
public static IObservable<IChangeSet<Datom>> ObserveDatoms(this IConnection conn, EntityId id, IAttribute attribute)
{
return conn.ObserveDatoms(SliceDescriptor.Create(id, attribute.GetDbId(conn.Registry.Id), conn.Registry));
}

/// <summary>
/// Observe changes for datoms that point to the given entity id via the given attribute
/// </summary>
public static IObservable<IChangeSet<Datom>> ObserveDatoms(this IConnection conn, ReferenceAttribute attribute, EntityId id)
{
return conn.ObserveDatoms(SliceDescriptor.Create(attribute, id, conn.Registry));
}

/// <summary>
/// Observe changes for a given attribute
/// </summary>
public static IObservable<IChangeSet<Datom>> ObserveDatoms(this IConnection conn, IAttribute attribute)
{
return conn.ObserveDatoms(SliceDescriptor.Create(attribute, conn.Registry));
}

private static IChangeSet<Datom> Diff(SortedSet<Datom> set, IndexSegment updates, SliceDescriptor descriptor, IEqualityComparer<Datom> comparer)
{
List<Change<Datom>>? changes = null;
Expand Down
13 changes: 13 additions & 0 deletions src/NexusMods.MnemonicDB.Abstractions/Query/SliceDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,19 @@ public static SliceDescriptor Create<THighLevel, TLowLevel>(Attribute<THighLevel
};
}

/// <summary>
/// Creates a slice descriptor for the given reference attribute and entity that is being pointed to.
/// </summary>
public static SliceDescriptor Create(ReferenceAttribute attr, EntityId value, IAttributeRegistry registry)
{
return new SliceDescriptor
{
Index = IndexType.VAETCurrent,
From = Datom(EntityId.MinValueNoPartition, attr, value, TxId.MinValue, false, registry),
To = Datom(EntityId.MaxValueNoPartition, attr, value, TxId.MaxValue, false, registry)
};
}

/// <summary>
/// Creates a slice descriptor for the given reference attribute and entity that is being pointed to, this is a
/// reverse lookup.
Expand Down
9 changes: 6 additions & 3 deletions src/NexusMods.MnemonicDB.SourceGenerator/Template.weave
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,12 @@ public partial class {{= model.Name}} {
#region CRUD Methods

{{each attr in model.Attributes}}
{{if attr.IsIndexed}}

{{if attr.IsIndexed || attr.IsReference}}
public static IEnumerable<{{= model.Name}}.ReadOnly> FindBy{{= attr.Name}}(__ABSTRACTIONS__.IDb db, {{= attr.HighLevelType.ToDisplayString()}} value) {
foreach (var id in db.FindIndexed({{= attr.Name}}, value)) {
yield return new {{= model.Name}}.ReadOnly(db, id);
}
}

{{/if}}
{{/each}}

Expand Down Expand Up @@ -245,6 +243,11 @@ public partial class {{= model.Name}} {
/// </summary>
public __ABSTRACTIONS__.IDb Db { get; }

/// <summary>
/// Rebases the entity to the most recent version of the database
/// </summary>
public ReadOnly Rebase() => new ReadOnly(Db.Connection.Db, Id);

/// <summary>
/// Constructs a new ReadOnly model of the entity.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.Win32;
using NexusMods.MnemonicDB.Abstractions;
using NexusMods.MnemonicDB.Abstractions.IndexSegments;
using NexusMods.MnemonicDB.Abstractions.Query;
Expand Down
1 change: 0 additions & 1 deletion src/NexusMods.MnemonicDB/Connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using Microsoft.Extensions.Logging;
using NexusMods.MnemonicDB.Abstractions;
using NexusMods.MnemonicDB.Abstractions.BuiltInEntities;
using NexusMods.MnemonicDB.Abstractions.ElementComparers;
using NexusMods.MnemonicDB.Abstractions.IndexSegments;
using NexusMods.MnemonicDB.Abstractions.Internals;
using NexusMods.MnemonicDB.Abstractions.Query;
Expand Down
7 changes: 7 additions & 0 deletions src/NexusMods.MnemonicDB/Db.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ public IEnumerable<EntityId> FindIndexed<TValue, TLowLevel>(Attribute<TValue, TL
.Select(d => d.E);
}

public IEnumerable<EntityId> FindIndexed(ReferenceAttribute attribute, EntityId value)
{
return Snapshot
.Datoms(SliceDescriptor.Create(attribute, value, _registry))
.Select(d => d.E);
}

public IEnumerable<Datom> FindIndexedDatoms<TValue, TLowLevel>(Attribute<TValue, TLowLevel> attribute, TValue value)
{
if (!attribute.IsIndexed)
Expand Down
15 changes: 11 additions & 4 deletions tests/NexusMods.MnemonicDB.Tests/DbTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -552,9 +552,6 @@ public async Task CanGetModelRevisions()

var loadoutNames = new List<string>();


// TODO: re-enable this once we decide on how to handle revisions
/*
using var subscription = loadout.Revisions()
.Select(l => l.Name)
.Finally(() => loadoutNames.Add("DONE"))
Expand All @@ -578,9 +575,19 @@ public async Task CanGetModelRevisions()
loadoutNames.Count.Should().Be(4, "All revisions should be loaded");

loadoutNames.Should().BeEquivalentTo(["Test Loadout", "Update 1", "Update 2", "DONE"]);
*/

}

[Fact]
public async Task CanFindByReference()
{
var loadout = await InsertExampleData();
foreach (var mod in loadout.Mods)
{
var found = Mod.FindByLoadout(Connection.Db, mod.LoadoutId)
.Select(f => f.Id);
found.Should().Contain(mod.Id, "we can look entities via the value if they are references");
}
}

[Fact]
Expand Down

0 comments on commit 45ee0a7

Please sign in to comment.