Skip to content

Commit

Permalink
[Improve] performance of the OperationProcessor by allowing it to rea…
Browse files Browse the repository at this point in the history
…d from the Cahce tables instead of VIEWs where appropriate; fixes #232
  • Loading branch information
samatstariongroup committed Sep 24, 2021
1 parent f6a1781 commit 6443981
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 86 deletions.
140 changes: 70 additions & 70 deletions CDP4WebServices.API.Tests/ChangeLog/ChangeLogTestFixture.cs

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions CDP4WebServices.API.Tests/OperationProcessorTestFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ public class OperationProcessorTestFixture
private Mock<API.Services.IServiceProvider> serviceProvider;
private Mock<IResolveService> resolveService;
private Mock<IPermissionService> permissionService;
private Mock<ICdp4TransactionManager> Cdp4TransactionManager;

private OperationProcessor operationProcessor;

Expand All @@ -110,14 +111,19 @@ public class OperationProcessorTestFixture
[SetUp]
public void TestSetup()
{
this.Cdp4TransactionManager = new Mock<ICdp4TransactionManager>();
this.Cdp4TransactionManager.Setup(x => x.IsCachedDtoReadEnabled(It.IsAny<NpgsqlTransaction>())).Returns(true);

this.mockedMetaInfoProvider = new Mock<IMetaInfoProvider>();
this.transactionManager = new Mock<ICdp4TransactionManager>();
this.requestUtils.MetaInfoProvider = this.mockedMetaInfoProvider.Object;
this.operationProcessor = new OperationProcessor();
this.operationProcessor.RequestUtils = this.requestUtils;
this.operationSideEffectProcessor.RequestUtils = this.requestUtils;
this.operationProcessor.OperationSideEffectProcessor = this.operationSideEffectProcessor;

this.operationProcessor.TransactionManager = this.Cdp4TransactionManager.Object;


this.serviceProvider = new Mock<API.Services.IServiceProvider>();
this.resolveService = new Mock<IResolveService>();

Expand Down Expand Up @@ -629,7 +635,7 @@ public void VerifyCopyElementDefWorks()

this.serviceProvider.Setup(x => x.MapToReadService(ClassKind.EngineeringModelSetup.ToString())).Returns(modelSetupService.Object);
// targetIteration
this.operationProcessor.Process(postOperation, null, $"Iteration_{targetIteration.Iid.ToString().Replace("-", "_")}", null);
this.operationProcessor.Process(postOperation, null, $"Iteration_{targetIteration.Iid.ToString().Replace("-", "_")}", It.IsAny<bool>(), null);

Assert.AreEqual(2, edDao.WrittenThingCount);
Assert.AreEqual(2, paramDao.WrittenThingCount);
Expand Down
2 changes: 1 addition & 1 deletion CDP4WebServices.API/Modules/10-25/EngineeringModelApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ protected override Response PostResponseData(dynamic routeParams)
// retrieve the revision for this transaction (or get next revision if it does not exist)
var transactionRevision = this.RevisionService.GetRevisionForTransaction(transaction, partition);

this.OperationProcessor.Process(operationData, transaction, partition, fileDictionary);
this.OperationProcessor.Process(operationData, transaction, partition, true, fileDictionary);

var actor = this.PermissionService.Credentials.Person.Iid;

Expand Down
2 changes: 1 addition & 1 deletion CDP4WebServices.API/Modules/10-25/SiteDirectoryApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ protected override Response PostResponseData(dynamic routeParams)
// retrieve the revision for this transaction (or get next revision if it does not exist)
var transactionRevision = this.RevisionService.GetRevisionForTransaction(transaction, TopContainer);

this.OperationProcessor.Process(operationData, transaction, TopContainer);
this.OperationProcessor.Process(operationData, transaction, TopContainer, true);

// save revision-history
var actor = credentials.Person.Iid;
Expand Down
2 changes: 1 addition & 1 deletion CDP4WebServices.API/Services/ChangeLog/ChangeLogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ public bool TryAppendModelChangeLogData(NpgsqlTransaction transaction, string pa
operationData.Update.Add(modelLogEntryClasslessDTO);
}

this.OperationProcessor.Process(operationData, transaction, partition);
this.OperationProcessor.Process(operationData, transaction, partition, false);

result = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ namespace CDP4WebServices.API.Services.Operations

using CDP4Common.DTO;

using CDP4Orm.Dao.Resolve;

using Npgsql;

/// <summary>
Expand All @@ -50,10 +48,13 @@ public interface IOperationProcessor
/// <param name="partition">
/// The database partition (schema) where the requested resource will be stored.
/// </param>
/// <param name="resolveFromCache">
/// A value indicating whether meta data shall be resolved from the CAHCE tables or from the VIEWs
/// </param>
/// <param name="fileStore">
/// The optional file binaries that were included in the request.
/// </param>
void Process(CdpPostOperation operation, NpgsqlTransaction transaction, string partition, Dictionary<string, Stream> fileStore = null);
void Process(CdpPostOperation operation, NpgsqlTransaction transaction, string partition, bool resolveFromCache, Dictionary<string, Stream> fileStore = null);

/// <summary>
/// Gets the operation original <see cref="Thing"/> instance cache.
Expand Down
73 changes: 65 additions & 8 deletions CDP4WebServices.API/Services/Operations/OperationProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ namespace CDP4WebServices.API.Services.Operations
using System.Linq;
using System.Security;

using CDP4WebServices.API.Helpers;

using IServiceProvider = CDP4WebServices.API.Services.IServiceProvider;
using Thing = CDP4Common.DTO.Thing;

Expand Down Expand Up @@ -142,6 +144,11 @@ public class OperationProcessor : IOperationProcessor
/// </summary>
public ICopySourceService CopySourceService { get; set; }

/// <summary>
/// Gets or sets the transaction manager.
/// </summary>
public ICdp4TransactionManager TransactionManager { get; set; }

/// <summary>
/// Process the posted operation message.
/// </summary>
Expand All @@ -154,17 +161,21 @@ public class OperationProcessor : IOperationProcessor
/// <param name="partition">
/// The database partition (schema) where the requested resource will be stored.
/// </param>
/// <param name="resolveFromCache">
/// A value indicating whether meta data shall be resolved from the CAHCE tables or from the VIEWs
/// </param>
/// <param name="fileStore">
/// The optional file binaries that were included in the request.
/// </param>
public void Process(
CdpPostOperation operation,
NpgsqlTransaction transaction,
string partition,
bool resolveFromCache,
Dictionary<string, Stream> fileStore = null)
{
this.ValidatePostMessage(operation, fileStore ?? new Dictionary<string, Stream>(), transaction, partition);
this.ApplyOperation(operation, transaction, partition, fileStore ?? new Dictionary<string, Stream>());
this.ApplyOperation(operation, transaction, partition, resolveFromCache, fileStore ?? new Dictionary<string, Stream>());
}

/// <summary>
Expand Down Expand Up @@ -764,17 +775,26 @@ private DtoResolveHelper GetContainerInfo(Thing thing)
/// <param name="partition">
/// The partition.
/// </param>
/// <param name="resolveFromCache">
/// A value indicating whether meta data shall be resolved from the CAHCE tables or from the VIEWs
/// </param>
/// <param name="fileStore">
/// The file Store.
/// </param>
private void ApplyOperation(
CdpPostOperation operation,
NpgsqlTransaction transaction,
string partition,
bool resolveFromCache,
Dictionary<string, Stream> fileStore)
{
// resolve any meta data from the persitence store
if (resolveFromCache)
{
this.TransactionManager.SetCachedDtoReadEnabled(true);
}
this.ResolveService.ResolveItems(transaction, partition, this.operationThingCache);
this.TransactionManager.SetCachedDtoReadEnabled(false);

// apply the operations
this.ApplyDeleteOperations(operation, transaction, partition);
Expand Down Expand Up @@ -841,9 +861,47 @@ private void DeletePersistedItem(NpgsqlTransaction transaction, string partition
/// </param>
private Thing GetPersistedItem(NpgsqlTransaction transaction, string partition, IPersistService service, Guid iid, ISecurityContext securityContext)
{
return service.GetShallow(
transaction, partition, new[] { iid }, securityContext)
.SingleOrDefault();
return service.GetShallow(
transaction, partition, new[] { iid }, securityContext)
.SingleOrDefault();
}

/// <summary>
/// Try and get persisted item from the data store cache tables
/// </summary>
/// <param name="transaction">
/// The current transaction to the database.
/// </param>
/// <param name="partition">
/// The database partition (schema) where the requested resource will be stored.
/// </param>
/// <param name="service">
/// The service instance for the requested type.
/// </param>
/// <param name="iid">
/// The id of the item to retrieve.
/// </param>
/// <returns>
/// The retrieved <see cref="Thing"/> instance or null if not found.
/// </returns>
/// <param name="securityContext">
/// The security Context used for permission checking.
/// </param>
private Thing GetPersistedItemFromDatastoreCache(NpgsqlTransaction transaction, string partition, IPersistService service, Guid iid, ISecurityContext securityContext)
{
try
{
// make sure we read from Cache tables and not from Views
this.TransactionManager.SetCachedDtoReadEnabled(true);

return service.GetShallow(
transaction, partition, new[] { iid }, securityContext)
.SingleOrDefault();
}
finally
{
this.TransactionManager.SetCachedDtoReadEnabled(false);
}
}

/// <summary>
Expand Down Expand Up @@ -969,13 +1027,12 @@ private void ApplyCreateOperations(CdpPostOperation operation, NpgsqlTransaction

var resolvedInfo = this.operationThingCache[createInfo];

// check that item doen not exist:
var persistedItem = this.GetPersistedItem(transaction, resolvedInfo.Partition, service, createInfo.Iid, securityContext);
// check that item doen not exist and get it from the datastore cache
var persistedItem = this.GetPersistedItemFromDatastoreCache(transaction, resolvedInfo.Partition, service, createInfo.Iid, securityContext);

if (persistedItem != null)
{
throw new InvalidOperationException(
string.Format("Item '{0}' with Iid: '{1}' already exists", createInfo.TypeName, createInfo.Iid));
throw new InvalidOperationException($"Item '{createInfo.TypeName}' with Iid: '{createInfo.Iid}' already exists");
}

// get the (cached) containment information for this create request
Expand Down

0 comments on commit 6443981

Please sign in to comment.