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

Remove +1 assumption for input versions in $import #3685

Merged
merged 8 commits into from
Jan 30, 2024

Conversation

SergeyGaluzo
Copy link
Contributor

@SergeyGaluzo SergeyGaluzo commented Jan 23, 2024

There is demand to honor arbitrary non sequential resource versions provided for $import. Currently versions are assumed to be sequential ints. This PR enables any int version.

@SergeyGaluzo SergeyGaluzo added Enhancement Enhancement on existing functionality. Azure Healthcare APIs Label denotes that the issue or PR is relevant to the FHIR service in the Azure Healthcare APIs Schema Version backward compatible labels Jan 23, 2024
@SergeyGaluzo SergeyGaluzo added this to the S133 milestone Jan 23, 2024
@SergeyGaluzo SergeyGaluzo requested a review from a team as a code owner January 23, 2024 19:24
@github-actions github-actions bot added SQL Scripts If SQL scripts are added to the PR labels Jan 23, 2024
@SergeyGaluzo SergeyGaluzo enabled auto-merge (squash) January 23, 2024 20:14
@@ -164,12 +164,12 @@ internal class SqlServerFhirDataStore : IFhirDataStore, IProvideCapability
(var transactionId, var minSequenceId) = await StoreClient.MergeResourcesBeginTransactionAsync(resources.Count, cancellationToken);

var index = 0;
var mergeWrappers = new List<MergeResourceWrapper>();
var mergeWrappersPlus = new List<(MergeResourceWrapper Wrapper, bool KeepVersion, int ResourceVersion, int? ExistingVersion)>();
Copy link
Contributor

@abiisnn abiisnn Jan 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the same name than before? "plus" without context could lead confusion, perhaps, adding a comment? #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plus indicates that this variable contains not only merge wrappers but other data points too. There are 3 other data points.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mergeWrappersAndVersions :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine.

// In each group find the smallest version higher then existing
prevResourceId = string.Empty;
var notSetInResoureGroup = false;
foreach (var mergeWrapperPlus in mergeWrappersPlus.Where(_ => _.KeepVersion && _.ExistingVersion != 0).OrderBy(_ => _.Wrapper.ResourceWrapper.ResourceId).ThenBy(_ => _.ResourceVersion))
Copy link
Member

@brendankowitz brendankowitz Jan 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: _ as a variable confuses tooling, x is just as short ;) #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:-) I like _ as it denotes that it is derived from the definition of enumerable, nothing else. In complex cases when there is more than one thing derived, I use meaningful variable names to differentiate between cases. BTW All code scanner are happy...

Copy link
Member

@brendankowitz brendankowitz Jan 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Using other variable names gives the more IntelliSense:
image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When hovering over _, my VS shows correct type details.

Copy link
Member

@brendankowitz brendankowitz Jan 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is also documented in the C# fundamentals: https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/discards. I'd suggest that this would break existing assumptions that someone might have when reading this code.

image

Copy link
Contributor Author

@SergeyGaluzo SergeyGaluzo Jan 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced _ by x.
BTW In this article they are talking about treating _ as discards in the outputs of some methods. I don't see _ used inside LINQ expression as an output. So, I don't see a violation here.

if (mergeWrappers.Count > 0) // Do not call DB with empty input
// Resources with input versions (keepVersion=true) might not have hasVersionToCompare set. Fix it here.
// Resources with keepVersion=true must be in separate call, and not mixed with keepVersion=false ones.
// Sort them in groups by resource id and order by version.
Copy link
Member

@brendankowitz brendankowitz Jan 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be done with Linq to simplify? Something like:

mergeWrappersPlus
.Where(x => x.KeepVersion && x.ExistingVersion != 0)
.GroupBy(key => key.Wrapper.ResourceWrapper.ResourceId, items => items.OrderBy(y =>y.ResourceVersion))
``` #ByDesign

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not able to find a clear way to apply required logic only using Linq. So I did what I did. I hope it is obvious, hence simple.

@@ -164,12 +164,12 @@ internal class SqlServerFhirDataStore : IFhirDataStore, IProvideCapability
(var transactionId, var minSequenceId) = await StoreClient.MergeResourcesBeginTransactionAsync(resources.Count, cancellationToken);

var index = 0;
var mergeWrappers = new List<MergeResourceWrapper>();
var mergeWrappersPlus = new List<(MergeResourceWrapper Wrapper, bool KeepVersion, int ResourceVersion, int? ExistingVersion)>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mergeWrappersAndVersions :)

Comment on lines 322 to 338
prevResourceId = string.Empty;
var notSetInResoureGroup = false;
foreach (var mergeWrapper in mergeWrappersWithVersions.Where(_ => _.KeepVersion && _.ExistingVersion != 0).OrderBy(_ => _.Wrapper.ResourceWrapper.ResourceId).ThenBy(_ => _.ResourceVersion))
{
if (prevResourceId != mergeWrapper.Wrapper.ResourceWrapper.ResourceId) // this should reset flag on each resource id group including first.
{
notSetInResoureGroup = true;
}

prevResourceId = mergeWrapper.Wrapper.ResourceWrapper.ResourceId;

if (notSetInResoureGroup && mergeWrapper.ResourceVersion > mergeWrapper.ExistingVersion)
{
mergeWrapper.Wrapper.HasVersionToCompare = true;
notSetInResoureGroup = false;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The linq version would look like this:

foreach (var wrapperWithVersionToCompare in mergeWrappersWithVersions
             .Where(x => x.KeepVersion && x.ExistingVersion != 0)
             .GroupBy(key => key.Wrapper.ResourceWrapper.ResourceId)
             .Select(group => group.MinBy(y => y.ResourceVersion))
             .Where(x => x.ResourceVersion > x.ExistingVersion))
{
    wrapperWithVersionToCompare.Wrapper.HasVersionToCompare = true;
}

Copy link
Contributor Author

@SergeyGaluzo SergeyGaluzo Jan 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. Your version is more difficult for me to understand, so I want to stick to my current one.

Copy link
Member

@brendankowitz brendankowitz Jan 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sergey, I understand you have code that functions as intended. In this case though, .net has a GroupBy function that we can leverage instead of needed to code it ourselves.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brendan,
I agree that this code can be rewritten. I still prefer my simple loop because it seems more transparent to me.
I already ran large scale perf test on my version before submitting PR, and I would like to avoid time waste.
If you are comfortable with your logic, please make changes directly in the PR.

@SergeyGaluzo SergeyGaluzo enabled auto-merge (squash) January 29, 2024 20:40
@SergeyGaluzo SergeyGaluzo merged commit 3046bd0 into main Jan 30, 2024
6 checks passed
@SergeyGaluzo SergeyGaluzo deleted the users/sergal/versionplusonefix branch January 30, 2024 21:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Azure Healthcare APIs Label denotes that the issue or PR is relevant to the FHIR service in the Azure Healthcare APIs Enhancement Enhancement on existing functionality. Schema Version backward compatible SQL Scripts If SQL scripts are added to the PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants