Skip to content

Commit

Permalink
Added the read index keys to data manager interface and index worker …
Browse files Browse the repository at this point in the history
…interface
  • Loading branch information
TechLiam committed Apr 29, 2021
1 parent c342fd5 commit ac12101
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 0 deletions.
65 changes: 65 additions & 0 deletions PackDB.Core.Tests/DataManagerTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public void Setup()
ExpectedIndexedEntity = new IndexedEntity {Id = Randomizer.Next(), IndexedValue = Randomizer.GetString()};
ExpectedAuditedEntity = new AuditedEntity {Id = Randomizer.Next()};
ExpectedAuditedEntityAuditLog = new AuditLog();
ExpectedIndexKey = new IndexKey<string>() { Value = Randomizer.GetString() };

MockDataStream = new Mock<IDataWorker>();
MockDataStream
Expand Down Expand Up @@ -93,6 +94,10 @@ public void Setup()
.Setup(
x => x.GetIdsFromIndex<IndexedEntity, string>("IndexedValue", ExpectedIndexedEntity.IndexedValue))
.Returns(ExpectedIndexEntityList);
MockIndexer
.Setup(
x => x.GetKeysFromIndex<IndexedEntity, string>("IndexedValue"))
.Returns(ExpectedIndexKeysEntityList);
MockIndexer
.Setup(x => x.Index(ExpectedBasicEntity1))
.ReturnsAsync(true);
Expand Down Expand Up @@ -154,13 +159,30 @@ private async IAsyncEnumerable<int> RandomIndexEntityList()
yield return await Task.FromResult(Randomizer.Next());
}

private async IAsyncEnumerable<IndexKey<string>> EmptyIndexKeysEntityList()
{
await Task.CompletedTask;
yield break;
}

private async IAsyncEnumerable<IndexKey<string>> RandomIndexKeysEntityList()
{
yield return await Task.FromResult(new IndexKey<string>(){ Value = Randomizer.GetString() });
}

private async IAsyncEnumerable<IndexKey<string>> ExpectedIndexKeysEntityList()
{
yield return await Task.FromResult(ExpectedIndexKey);
}

private DataManager DataManager { get; set; }
private static BasicEntity ExpectedBasicEntity1 { get; set; }
private static BasicEntity ExpectedBasicEntity2 { get; set; }
private static IndexedEntity ExpectedIndexedEntity { get; set; }
private static AuditedEntity ExpectedAuditedEntity { get; set; }
private static AuditLog ExpectedAuditedEntityAuditLog { get; set; }
private static int ExpectedNextBasicEntityId { get; set; }
private static IndexKey<string> ExpectedIndexKey { get; set; }
private Randomizer Randomizer { get; set; }
private Mock<IDataWorker> MockDataStream { get; set; }
private Mock<IIndexWorker> MockIndexer { get; set; }
Expand Down Expand Up @@ -266,7 +288,50 @@ public async Task ReadWhenIndexHasAValueAndThereIsData()
Assert.AreEqual(result.Count(), 1);
Assert.AreSame(ExpectedIndexedEntity, result.ElementAt(0));
}

[Test(Author = "PackDB Creator")]
public async Task ReadKeysWhenIndexPropertyIsNotIndexed()
{
var data = DataManager.ReadIndexKeys<BasicEntity, string>(x => x.Value1);
var result = new List<IndexKey<string>>();
await foreach (var d in data) result.Add(d);
Assert.IsEmpty(result);
MockIndexer.Verify(x => x.IndexExist<BasicEntity>(It.IsAny<string>()), Times.Never);
}

[Test(Author = "PackDB Creator")]
public async Task ReadKeysWhenIndexDoesNotExist()
{
MockIndexer.Setup(x => x.IndexExist<IndexedEntity>("IndexedValue")).ReturnsAsync(false);
var data = DataManager.ReadIndexKeys<IndexedEntity, string>(x => x.IndexedValue);
var result = new List<IndexKey<string>>();
await foreach (var d in data) result.Add(d);
Assert.IsEmpty(result);
}

[Test(Author = "PackDB Creator")]
public async Task ReadKeysWhenIndexHasNoValue()
{
MockIndexer
.Setup(
x => x.GetKeysFromIndex<IndexedEntity, string>("IndexedValue"))
.Returns(EmptyIndexKeysEntityList);
var data = DataManager.ReadIndexKeys<IndexedEntity, string>(x => x.IndexedValue);
var results = new List<IndexKey<string>>();
await foreach (var d in data) results.Add(d);
Assert.IsFalse(results.Any());
}

[Test(Author = "PackDB Creator")]
public async Task ReadKeysWhenIndexHasAValueAndThereIsData()
{
var data = DataManager.ReadIndexKeys<IndexedEntity, string>(x => x.IndexedValue);
var result = new List<IndexKey<string>>();
await foreach (var d in data) result.Add(d);
Assert.AreEqual(result.Count(), 1);
Assert.AreSame(ExpectedIndexKey, result.ElementAt(0));
}

[Test(Author = "PackDB Creator", ExpectedResult = false)]
public async Task<bool> WriteDataWithNoAuditFails()
{
Expand Down
24 changes: 24 additions & 0 deletions PackDB.Core/DataManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,30 @@ public async IAsyncEnumerable<TDataType> ReadIndex<TDataType, TKeyType>(TKeyType
}
}

public async IAsyncEnumerable<IndexKey<TKeyType>> ReadIndexKeys<TDataType, TKeyType>(Expression<Func<TDataType, TKeyType>> indexProperty) where TDataType : DataEntity
{
var indexMember = ((MemberExpression) indexProperty.Body).Member;
using (Logger.BeginScope("{Operation} is {Action} {IndexName} for {DataType}",
nameof(DataManager), "getting keys from index", indexMember.Name, typeof(TDataType).Name))
{
if (indexMember.IsDefined(typeof(IndexAttribute), true))
{
Logger.LogTrace("Property is indexed");
var indexName = indexMember.Name;
if (await IndexWorker.IndexExist<TDataType>(indexName))
{
var keys = IndexWorker.GetKeysFromIndex<TDataType, TKeyType>(indexName);
Logger.LogInformation("Found keys in index", keys);
await foreach (var key in keys) yield return key;
}

yield break;
}

Logger.LogWarning("The property used is not marked as indexed");
}
}

public async Task<bool> Write<TDataType>(TDataType data) where TDataType : DataEntity
{
using (Logger.BeginScope("{Operation} is {Action} {DataType} with Id ({Id})", nameof(DataManager),
Expand Down
10 changes: 10 additions & 0 deletions PackDB.Core/IDataManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Threading.Tasks;
using PackDB.Core.Auditing;
using PackDB.Core.Data;
using PackDB.Core.Indexing;

namespace PackDB.Core
{
Expand Down Expand Up @@ -45,6 +46,15 @@ public interface IDataManager
/// <returns>An enumerable of the data indexed under the key</returns>
IAsyncEnumerable<TDataType> ReadIndex<TDataType, TKeyType>(TKeyType key,
Expression<Func<TDataType, TKeyType>> indexProperty) where TDataType : DataEntity;

/// <summary>
/// Get keys that have been indexed for the property provided
/// </summary>
/// <param name="indexProperty">The property the key is for</param>
/// <typeparam name="TDataType">The type of data that is being got</typeparam>
/// <typeparam name="TKeyType">The type of the key</typeparam>
/// <returns></returns>
IAsyncEnumerable<IndexKey<TKeyType>> ReadIndexKeys<TDataType, TKeyType>(Expression<Func<TDataType, TKeyType>> indexProperty) where TDataType : DataEntity;

/// <summary>
/// Writes the data to the storage system
Expand Down
2 changes: 2 additions & 0 deletions PackDB.Core/Indexing/IIndexWorker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,7 @@ IAsyncEnumerable<int> GetIdsFromIndex<TDataType, TKeyType>(string indexName, TKe
/// <typeparam name="TDataType">The data type that should have indexable properties</typeparam>
/// <returns>True if all properties are unindexed</returns>
Task<bool> Unindex<TDataType>(TDataType data) where TDataType : DataEntity;

IAsyncEnumerable<IndexKey<TKeyType>> GetKeysFromIndex<TDataType, TKeyType>(string indexName) where TDataType : DataEntity;
}
}

0 comments on commit ac12101

Please sign in to comment.