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

Exporting some events and properties for supporting external dynamic indexing #582

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Data.Common;

namespace YesSql.Commands.DocumentChanged
{
public class DocumentChangeContext
{
public ISession Session { get; set; }
public object Entity { get; set; }
public Document Document { get; set; }
public IStore Store { get; set; }
public DbConnection Connection { get; set; }
public DbTransaction Transaction { get; set; }
public ISqlDialect Dialect { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Collections.Generic;
using System.Data.Common;

namespace YesSql.Commands.DocumentChanged
{
public class DocumentChangeInBatchContext
{
public object Entity { get; set; }
public List<string> Queries { get; set; }
public DbCommand BatchCommand { get; set; }
public ISession Session { get; set; }
public Document Document { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ namespace YesSql.Commands
{
public abstract class DocumentCommand : IIndexCommand, ICollectionName
{
protected static readonly PropertyInfo[] AllProperties = new PropertyInfo[]
{
protected static readonly PropertyInfo[] AllProperties =
[
typeof(Document).GetProperty("Type")
};
];

protected static readonly PropertyInfo[] AllKeys = new PropertyInfo[]
{
protected static readonly PropertyInfo[] AllKeys =
[
typeof(Document).GetProperty("Id")
};
];

public abstract int ExecutionOrder { get; }

Expand Down
16 changes: 16 additions & 0 deletions src/YesSql.Abstractions/Commands/IDocumentCommandHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Threading.Tasks;
using YesSql.Commands.DocumentChanged;

namespace YesSql.Commands
{
public interface IDocumentCommandHandler
{
Task CreatedAsync(DocumentChangeContext context);
bool CreatedInBatch(DocumentChangeInBatchContext context);

Task RemovingAsync(DocumentChangeContext context);
bool RemovingInBatch(DocumentChangeInBatchContext context);
Task UpdatedAsync(DocumentChangeContext context);
bool UpdatedInBatch(DocumentChangeInBatchContext context);
}
}
5 changes: 5 additions & 0 deletions src/YesSql.Abstractions/ISession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Data;
using System.Data.Common;
using System.Threading.Tasks;
using YesSql.Commands;
using YesSql.Indexes;

namespace YesSql
Expand Down Expand Up @@ -147,5 +148,9 @@ public interface ISession : IDisposable, IAsyncDisposable
/// Gets the <see cref="Store" /> instance that created this session.
/// </summary>
IStore Store { get; }

IEnumerable<IndexDescriptor> ExtraIndexDescriptors { get; set; }
Func<Type, string, Task<IEnumerable<IndexDescriptor>>> BuildExtraIndexDescriptors { get; set; }
IDocumentCommandHandler DocumentCommandHandler { get; set; }
}
}
2 changes: 1 addition & 1 deletion src/YesSql.Abstractions/IStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ public interface IStore : IDisposable
/// <summary>
/// Returns the <see cref="ITypeService" /> instance used to create this store.
/// </summary>
ITypeService TypeNames { get; }
ITypeService TypeService { get; set; }
}
}
5 changes: 5 additions & 0 deletions src/YesSql.Abstractions/ITypeService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Reflection;
using YesSql.Serialization;

namespace YesSql
{
Expand All @@ -16,5 +18,8 @@ public interface ITypeService
/// Gets the type represented by a string.
/// </summary>
Type this[string s] { get; }

PropertyInfo[] GetProperties(Type type);
PropertyInfoAccessor GetPropertyAccessors(PropertyInfo property, Func<PropertyInfo, PropertyInfoAccessor> createFactory);
}
}
35 changes: 30 additions & 5 deletions src/YesSql.Core/Commands/CreateDocumentCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,25 @@
using System.Collections.Generic;
using System.Data.Common;
using System.Threading.Tasks;
using YesSql.Commands.DocumentChanged;

namespace YesSql.Commands
{
public sealed class CreateDocumentCommand : DocumentCommand
public class CreateDocumentCommand : DocumentCommand
{
private readonly IStore _store;

private readonly ISession _session;
private readonly object _entity;
public override int ExecutionOrder { get; } = 0;

public CreateDocumentCommand(Document document, IStore store, string collection) : base(document, collection)
public CreateDocumentCommand(object entity, Document document, IStore store, string collection, ISession session) : base(document, collection)
{
_store = store;
_session = session;
_entity = entity;
}

public override Task ExecuteAsync(DbConnection connection, DbTransaction transaction, ISqlDialect dialect, ILogger logger)
public override async Task ExecuteAsync(DbConnection connection, DbTransaction transaction, ISqlDialect dialect, ILogger logger)
{
var documentTable = _store.Configuration.TableNameConvention.GetDocumentTable(Collection);

Expand All @@ -28,8 +32,19 @@ public override Task ExecuteAsync(DbConnection connection, DbTransaction transac
{
logger.LogTrace(insertCmd);
}
await connection.ExecuteAsync(insertCmd, Document, transaction);

return connection.ExecuteAsync(insertCmd, Document, transaction);
var context = new DocumentChangeContext
{
Session = _session,
Entity = _entity,
Document = Document,
Store = _store,
Connection = connection,
Transaction = transaction,
Dialect = dialect,
};
await _session.DocumentCommandHandler.CreatedAsync(context);
}

public override bool AddToBatch(ISqlDialect dialect, List<string> queries, DbCommand batchCommand, List<Action<DbDataReader>> actions, int index)
Expand All @@ -45,6 +60,16 @@ public override bool AddToBatch(ISqlDialect dialect, List<string> queries, DbCom
.AddParameter("Content_" + index, Document.Content)
.AddParameter("Version_" + index, Document.Version);

var context = new DocumentChangeInBatchContext
{
Session = _session,
Document = Document,
Entity = _entity,
BatchCommand = batchCommand,
Queries = queries,
};
_session.DocumentCommandHandler.CreatedInBatch(context);

return true;
}
}
Expand Down
20 changes: 20 additions & 0 deletions src/YesSql.Core/Commands/DefaultDocumentCommandHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Threading.Tasks;
using YesSql.Commands.DocumentChanged;

namespace YesSql.Commands
{
public class DefaultDocumentCommandHandler : IDocumentCommandHandler
{
public Task CreatedAsync(DocumentChangeContext context) => Task.CompletedTask;

public bool CreatedInBatch(DocumentChangeInBatchContext context) => true;

public Task RemovingAsync(DocumentChangeContext context) => Task.CompletedTask;

public bool RemovingInBatch(DocumentChangeInBatchContext context) => true;

public Task UpdatedAsync(DocumentChangeContext context) => Task.CompletedTask;

public bool UpdatedInBatch(DocumentChangeInBatchContext context) => true;
}
}
39 changes: 33 additions & 6 deletions src/YesSql.Core/Commands/DeleteDocumentCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,61 @@
using System.Collections.Generic;
using System.Data.Common;
using System.Threading.Tasks;
using YesSql.Commands.DocumentChanged;

namespace YesSql.Commands
{
public sealed class DeleteDocumentCommand : DocumentCommand
public class DeleteDocumentCommand : DocumentCommand
{
private readonly IStore _store;
private readonly ISession _session;
private readonly object _entity;
public override int ExecutionOrder { get; } = 4;

public DeleteDocumentCommand(Document document, IStore store, string collection) : base(document, collection)
public DeleteDocumentCommand(object entity, Document document, IStore store, string collection, Session session) : base(document, collection)
{
_store = store;
_session = session;
_entity = entity;
}

public override Task ExecuteAsync(DbConnection connection, DbTransaction transaction, ISqlDialect dialect, ILogger logger)
public async override Task ExecuteAsync(DbConnection connection, DbTransaction transaction, ISqlDialect dialect, ILogger logger)
{
var context = new DocumentChangeContext
{
Session = _session,
Entity = _entity,
Document = Document,
Store = _store,
Connection = connection,
Transaction = transaction,
Dialect = dialect,
};
await _session.DocumentCommandHandler.RemovingAsync(context);

var documentTable = _store.Configuration.TableNameConvention.GetDocumentTable(Collection);
var deleteCmd = $"delete from {dialect.QuoteForTableName(_store.Configuration.TablePrefix + documentTable, _store.Configuration.Schema)} where {dialect.QuoteForColumnName("Id")} = @Id;";

if (logger.IsEnabled(LogLevel.Trace))
{
logger.LogTrace(deleteCmd);
}
return connection.ExecuteAsync(deleteCmd, Document, transaction);

await connection.ExecuteAsync(deleteCmd, Document, transaction);
}

public override bool AddToBatch(ISqlDialect dialect, List<string> queries, DbCommand command, List<Action<DbDataReader>> actions, int index)
{
var context = new DocumentChangeInBatchContext
{
Session = _session,
Document = Document,
Entity = _entity,
BatchCommand = command,
Queries = queries,
};
_session.DocumentCommandHandler.RemovingInBatch(context);

var documentTable = _store.Configuration.TableNameConvention.GetDocumentTable(Collection);

var deleteCmd = $"delete from {dialect.QuoteForTableName(_store.Configuration.TablePrefix + documentTable, _store.Configuration.Schema)} where {dialect.QuoteForColumnName("Id")} = @Id_{index};";
Expand Down
29 changes: 6 additions & 23 deletions src/YesSql.Core/Commands/IndexCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using YesSql.Data;
using YesSql.Indexes;
using YesSql.Serialization;

Expand All @@ -19,8 +19,6 @@ public abstract class IndexCommand : IIndexCommand

protected readonly IStore _store;

private static readonly ConcurrentDictionary<PropertyInfo, PropertyInfoAccessor> PropertyAccessors = new();
private static readonly ConcurrentDictionary<string, PropertyInfo[]> TypeProperties = new();
private static readonly ConcurrentDictionary<CompoundKey, string> InsertsList = new();
private static readonly ConcurrentDictionary<CompoundKey, string> UpdatesList = new();

Expand All @@ -47,13 +45,13 @@ public static void ResetQueryCache()
UpdatesList.Clear();
}

protected static void GetProperties(DbCommand command, object item, string suffix, ISqlDialect dialect)
protected void GetProperties(DbCommand command, object item, string suffix, ISqlDialect dialect)
{
var type = item.GetType();

foreach (var property in TypePropertiesCache(type))
{
var accessor = PropertyAccessors.GetOrAdd(property, p => new PropertyInfoAccessor(p));
var accessor = _store.TypeService.GetPropertyAccessors(property, prop => new PropertyInfoAccessor(prop));

var value = accessor.Get(item);

Expand All @@ -65,16 +63,9 @@ protected static void GetProperties(DbCommand command, object item, string suffi
}
}

protected static PropertyInfo[] TypePropertiesCache(Type type)
protected PropertyInfo[] TypePropertiesCache(Type type)
{
if (TypeProperties.TryGetValue(type.FullName, out var pis))
{
return pis;
}

var properties = type.GetProperties().Where(IsWriteable).ToArray();
TypeProperties[type.FullName] = properties;
return properties;
return _store.TypeService.GetProperties(type);
}

protected string Inserts(Type type, ISqlDialect dialect)
Expand Down Expand Up @@ -178,15 +169,7 @@ protected string Updates(Type type, ISqlDialect dialect)
return result;
}

private static bool IsWriteable(PropertyInfo pi)
{
return
pi.Name != nameof(IIndex.Id) &&
// don't read DocumentId when on a MapIndex as it might be used to
// read the DocumentId directly from an Index query
pi.Name != "DocumentId"
;
}


public abstract bool AddToBatch(ISqlDialect dialect, List<string> queries, DbCommand batchCommand, List<Action<DbDataReader>> actions, int index);

Expand Down
Loading
Loading