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

FEATURE: Update object optimization 2023.1 #2126

Merged
merged 23 commits into from Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ade8748
processCRUDResult partially optimizad
JindrichSusen Nov 1, 2023
1dfc86e
Row update optimized
JindrichSusen Nov 1, 2023
e0ba12d
processCRUDResult accepts array of ICRUDResult
JindrichSusen Nov 1, 2023
1d7203d
Number of row states returned by UpdateObject limited
JindrichSusen Nov 2, 2023
9e6e8be
IsEntryInQueue optimized
JindrichSusen Nov 2, 2023
36422f2
EvaluateRule optimized
JindrichSusen Nov 2, 2023
b53184c
Added checks to avoid running DataTable.OnRowChanged
JindrichSusen Nov 2, 2023
1945c3a
Revert "Added checks to avoid running DataTable.OnRowChanged"
JindrichSusen Nov 3, 2023
55912a6
Revert "Number of row states returned by UpdateObject limited"
JindrichSusen Nov 3, 2023
aaa3d6b
DataTable.OnRowChanged is not handled if the row was modified
JindrichSusen Nov 3, 2023
f6badff
Rule queue indexing refactored
JindrichSusen Nov 3, 2023
04ec625
License added
JindrichSusen Nov 3, 2023
6a7fa58
Requests grouped by entity
JindrichSusen Nov 3, 2023
3c105fe
Property renamed
JindrichSusen Nov 3, 2023
4a433fd
Merge remote-tracking branch 'origin/update-object-optimization-2023-…
JindrichSusen Nov 3, 2023
e9381c3
Revert "Revert "Number of row states returned by UpdateObject limited""
JindrichSusen Nov 3, 2023
7ef1250
Microsoft.Bcl.HashCode explicitly referenced
JindrichSusen Nov 3, 2023
276f0fb
Row states were not cleared after UpdateObject
JindrichSusen Nov 3, 2023
e630abc
Merge remote-tracking branch 'origin/update-object-optimization-2023-…
JindrichSusen Nov 3, 2023
f152d66
Null check added
JindrichSusen Nov 4, 2023
0d5756d
Attributions Updated
JindrichSusen Nov 5, 2023
237c142
Comment added
JindrichSusen Nov 5, 2023
c7e1699
Code formatting
JindrichSusen Nov 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 8 additions & 2 deletions backend/Origam.Rule/DatasetRuleHandler.cs
Expand Up @@ -265,8 +265,14 @@ public void OnRowCopied(DataRow row, IDataDocument data, DataStructureRuleSet ru

private void table_RowChanged(object sender, DataRowChangeEventArgs e)
{
OnRowChanged(e, _currentRuleDocument, _ruleSet, _ruleEngine);

// The RowChanged event fires after every call to DataRow.EndEdit().
// Every field change calls the DataRow.EndEdit(). This led to
// execution of the OnRowChanged handler after changing just a single
// field which added undesired overhead.
if (e.Action != DataRowAction.Change && e.Action != DataRowAction.Nothing)
tvavrda marked this conversation as resolved.
Show resolved Hide resolved
{
OnRowChanged(e, _currentRuleDocument, _ruleSet, _ruleEngine);
}
}

private void table_ColumnChanged(object sender, DataColumnChangeEventArgs e)
Expand Down
98 changes: 98 additions & 0 deletions backend/Origam.Rule/IndexedRuleQueue.cs
@@ -0,0 +1,98 @@
#region license
/*
Copyright 2005 - 2023 Advantage Solutions, s. r. o.

This file is part of ORIGAM (http://www.origam.org).

ORIGAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

ORIGAM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with ORIGAM. If not, see <http://www.gnu.org/licenses/>.
*/
#endregion

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using Origam.DA;
using Origam.Schema.EntityModel;

namespace Origam.Rule;

public class IndexedRuleQueue: IEnumerable<object[]>
{
private readonly HashSet<int> hashSet = new ();
private readonly Queue<object[]> queue = new ();

public int Count => queue.Count;

public void Enqueue(object[] entry)
{
hashSet.Add(GetHash(entry));
queue.Enqueue(entry);
}

public bool Contains(DataRow row, DataStructureRuleSet ruleSet)
{
int hash = GetHash(row, ruleSet);
return hashSet.Contains(hash);
}


public object[] Peek()
{
return queue.Peek();
}

public object[] Dequeue()
{
var entry = queue.Dequeue();
int hash = GetHash(entry);
hashSet.Remove(hash);
return entry;
}

public void Clear()
{
queue.Clear();
hashSet.Clear();
}

public IEnumerator<object[]> GetEnumerator()
{
return queue.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

private int GetHash(DataRow row, DataStructureRuleSet ruleSet)
{
HashCode hash = new();
object[] keys = DatasetTools.PrimaryKey(row);
foreach (object key in keys)
{
hash.Add(key);
}
hash.Add(ruleSet?.Id);
return hash.ToHashCode();
}

private int GetHash(object[] entry)
{
var row = entry[0] as DataRow;
var ruleSet = entry[1] as DataStructureRuleSet;
return GetHash(row, ruleSet);
}
}
1 change: 1 addition & 0 deletions backend/Origam.Rule/Origam.Rule.csproj
Expand Up @@ -56,6 +56,7 @@
<ItemGroup>
<PackageReference Include="DiffPlex" Version="1.7.1" />
<PackageReference Include="MarkdownSharp" Version="2.0.5" />
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
<PackageReference Include="Mvp.Xml.NetStandard" Version="1.1.1" />
</ItemGroup>
<ItemGroup>
Expand Down
27 changes: 8 additions & 19 deletions backend/Origam.Rule/RuleEngine.cs
Expand Up @@ -772,25 +772,13 @@ private bool ProcessRulesFromQueue(DataRow rowChanged, IDataDocument data, DataS
{
return ProcessRulesInternal(rowChanged, data, null, ruleSet, columnsChanged, true);
}

private Queue _ruleQueue = new Queue();
private IndexedRuleQueue _ruleQueue = new ();
private Hashtable _ruleColumnChanges = new Hashtable();

private bool IsEntryInQueue(DataRow rowChanged, DataStructureRuleSet ruleSet)
tvavrda marked this conversation as resolved.
Show resolved Hide resolved
{
foreach(object[] entry in _ruleQueue)
{
if(entry[0].Equals(rowChanged) && (
(entry[1] != null && entry[1].Equals(ruleSet) )
|| entry[1] == null && ruleSet == null
)
)
{
return true;
}
}

return false;
return _ruleQueue.Contains(rowChanged, ruleSet);
}

private void UpdateQueueEntries(DataRow rowChanged, DataStructureRuleSet ruleSet, DataColumn column)
Expand Down Expand Up @@ -827,6 +815,7 @@ private void EnqueueEntry(DataRow rowChanged, IDataDocument data, DataStructureR
}

object[] queueEntry = new object[4] {rowChanged, ruleSet, columns, data};

_ruleQueue.Enqueue(queueEntry);
}

Expand Down Expand Up @@ -1000,7 +989,6 @@ public void ProcessRuleQueue()
}

row.CancelEdit();

_ruleQueue.Dequeue();
}
}
Expand Down Expand Up @@ -2081,7 +2069,8 @@ private Guid Evaluate(TransformationReference reference)
#region Rule Evaluators
private object EvaluateRule(XPathRule rule, IXmlContainer context, XPathNodeIterator contextPosition)
{
if(context?.Xml == null)
XmlDocument xmlDocument = context?.Xml;
if(xmlDocument == null)
{
throw new NullReferenceException(ResourceUtils.GetString("ErrorEvaluateContextNull"));
}
Expand All @@ -2093,10 +2082,10 @@ private object EvaluateRule(XPathRule rule, IXmlContainer context, XPathNodeIter
{
log.Debug("Current Position: " + contextPosition?.Current?.Name);
}
log.Debug(" Input data: " + context.Xml?.OuterXml);
log.Debug(" Input data: " + xmlDocument.OuterXml);
}

XPathNavigator nav = context.Xml.CreateNavigator();
XPathNavigator nav = xmlDocument.CreateNavigator();

return XpathEvaluator.Instance.Evaluate(
rule.XPath, rule.IsPathRelative, rule.DataType, nav,
Expand Down
5 changes: 5 additions & 0 deletions backend/Origam.Server/Session Stores/SessionStore.cs
Expand Up @@ -942,6 +942,11 @@ private void GetChangesRecursive(List<ChangeInfo> changes, string requestingGrid
{
if (row.RowState != DataRowState.Deleted && row.RowState != DataRowState.Detached)
{
// Optimization. There are cases when calling UpdateObject can result in a lot of changes and a lot of
// row states. This should reduce size of the returned data and improve the UpdateObject's time.
// The missing row states should be loaded by the client.
includeRowStates = includeRowStates && changes.Count < 20;

object rowKey = DatasetTools.PrimaryKey(row)[0];
string ignoreRowIndex = row.Table.TableName + rowKey.ToString();
if (row.Equals(changedRow))
Expand Down