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

Fixed an issue with the _lastUpdated search param not being recognised as a valid sort spec with Elastic Search enabled in CDR #6670

Open
wants to merge 13 commits into
base: rel_8_0
Choose a base branch
from

Conversation

AbayomiE-T
Copy link

@AbayomiE-T AbayomiE-T commented Jan 31, 2025

In CDR, with HSearch is enabled, it is observed that a lot of search parameters are missing from the SearchParamRegistry which results in the error 500 HAPI-0389: Failed to call access method: org.springframework.dao.InvalidDataAccessApiUsageException: HAPI-2523: Invalid sort specification: _lastUpdated when using the $apply-codesystem-delta-add operation.

A fall back was added in HSearchSortHelperImpl.getParamType() to account for these missing search params.

@AbayomiE-T AbayomiE-T self-assigned this Jan 31, 2025
Copy link

github-actions bot commented Jan 31, 2025

Formatting check succeeded!

…d as a valid sort spec with Hsearch enabled in CDR
@AbayomiE-T AbayomiE-T changed the title Fixed an issue with the _lastUpdated search param not being recognised as a valid sort spec with Elastic Search enabled Fixed an issue with the _lastUpdated search param not being recognised as a valid sort spec with Elastic Search enabled in CDR Jan 31, 2025
Copy link

codecov bot commented Feb 1, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Please upload report for BASE (rel_8_0@637a79f). Learn more about missing BASE report.

Additional details and impacted files
@@            Coverage Diff             @@
##             rel_8_0    #6670   +/-   ##
==========================================
  Coverage           ?   83.56%           
  Complexity         ?    28625           
==========================================
  Files              ?     1798           
  Lines              ?   111309           
  Branches           ?    13978           
==========================================
  Hits               ?    93011           
  Misses             ?    12297           
  Partials           ?     6001           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@@ -155,12 +156,23 @@ Optional<RestSearchParameterTypeEnum> getParamType(String theResourceTypeName, S
theResourceTypeName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
RuntimeSearchParam searchParam = activeSearchParams.get(theParamName);
if (searchParam == null) {
return Optional.empty();
RestSearchParameterTypeEnum paramType = this.getParamTypeOfSortingParams(theParamName);
Copy link
Collaborator

Choose a reason for hiding this comment

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

no need to use this

Copy link
Author

Choose a reason for hiding this comment

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

Corrected 👍

@@ -155,12 +156,23 @@ Optional<RestSearchParameterTypeEnum> getParamType(String theResourceTypeName, S
theResourceTypeName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
RuntimeSearchParam searchParam = activeSearchParams.get(theParamName);
if (searchParam == null) {
return Optional.empty();
RestSearchParameterTypeEnum paramType = this.getParamTypeOfSortingParams(theParamName);
return paramType != null ? Optional.of(paramType) : Optional.empty();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Optional.ofNullable(paramType);

Copy link
Author

Choose a reason for hiding this comment

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

Updated. Thanks for this.

}

return Optional.of(searchParam.getParamType());
}

private RestSearchParameterTypeEnum getParamTypeOfSortingParams(String paramName) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

make the map static so u don't create/throw away with each method invocation

Copy link
Author

Choose a reason for hiding this comment

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

Done.

* Validates that _id, _lastUpdated, _tag, _security and _source returns a type when absent from
* the search param registry.
*/
@Test
Copy link
Collaborator

Choose a reason for hiding this comment

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

try to use the test name concept test[WhatUrTesting]_when[TheCondition]_will[WhatIsExpected]

Copy link
Author

Choose a reason for hiding this comment

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

Done.

void testGetParamTypeWhenParamNameIsNotInSearchParamRegistry() {
//Given that we have params absent from the SearchParamsRegistry
String resourceType = "CodeSystem";
SortSpec [] sortSpecs = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

i would recommend using a @ParameterizedTest with @MethodSource("theNameOfTheMethod"). do a search on the code base for example.

with a @ParameterizedTest, u will have test function parameters (SortSpec theSortSpec, Optional theOptionalSPTypeEnum). that will be much cleaner.

Copy link
Author

Choose a reason for hiding this comment

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

Used @ParameterizedTest and it does look much, much cleaner. Thank you!

RestSearchParameterTypeEnum.TOKEN
};
when(mockSearchParamRegistry.getActiveSearchParams(eq(resourceType), any())).thenReturn(mockResourceSearchParams);
//Execute
Copy link
Collaborator

Choose a reason for hiding this comment

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

not too sure about what's ur testing. i'll have to take a look once u clean it all up with @ParameterizedTest

Copy link
Author

Choose a reason for hiding this comment

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

Should be a bit clearer now after your suggested changes.

Copy link
Collaborator

Choose a reason for hiding this comment

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

ok, now i can see better and here's my two cents on it:
Class HSearchSortHelperImpl declares a map of default mapping between SortSpec's and ParameterTypeEnum. The test methodSource function does the same thing but stores the mappings in a stream instead of a map. so u have 2 declarations of pretty much the same stuff minus the optional. if someone adds to the map in the class, ur test suddenly does not account for the new value. someone would have to know that u have implemented the test and go look for it. that makes it a brittle test.

let's fix this.

  • u could make that map visible (public) and non-modifiable, there's no arm in exposing something that no one can mess with.
  • then build ur parameterized argument out of that map.
  • since u've spent already quite a bit of time on this, i 'll give u the starting pointers:
private static Stream<Arguments> provideArgumentsForGetParamType() {
		Stream.Builder<Arguments> retVal = Stream.builder();
		HSearchSortHelperImpl.ourSortingParamNameToParamType.forEach((theSortSpecName, theRestSearchParameterTypeEnum) ->
			{
				// ur code goes here
			});
		
		return retVal.build();
	}

myStorageSettings.setHibernateSearchIndexFullText(true);
myStorageSettings.setHibernateSearchIndexSearchParams(true);
myStorageSettings.setStoreResourceInHSearchIndex(true);
//Given: We have a non-existent code system
Copy link
Collaborator

Choose a reason for hiding this comment

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

add breathing spaces in between stages of ur test. good construction though, i can see what's going on.

Copy link
Author

Choose a reason for hiding this comment

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

Added some whitespaces.

@@ -52,6 +53,12 @@
*/
public class HSearchSortHelperImpl implements IHSearchSortHelper {
private static final Logger ourLog = LoggerFactory.getLogger(HSearchSortHelperImpl.class);
private static final Map<String, RestSearchParameterTypeEnum> sortingParamNameToParamType = Map.of(
Copy link
Collaborator

Choose a reason for hiding this comment

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

as per code convention, any class static variable name is 'our'. please change to ourSortingParamNameToParamType

Copy link
Author

Choose a reason for hiding this comment

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

Updated. Thank you.

@@ -155,9 +162,9 @@ Optional<RestSearchParameterTypeEnum> getParamType(String theResourceTypeName, S
theResourceTypeName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
RuntimeSearchParam searchParam = activeSearchParams.get(theParamName);
if (searchParam == null) {
return Optional.empty();
Copy link
Collaborator

Choose a reason for hiding this comment

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

what would happen if theParamName is null? does the get returns null (which i hope) or blows up?

i'll see if u have a test covering that.

RestSearchParameterTypeEnum.TOKEN
};
when(mockSearchParamRegistry.getActiveSearchParams(eq(resourceType), any())).thenReturn(mockResourceSearchParams);
//Execute
Copy link
Collaborator

Choose a reason for hiding this comment

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

ok, now i can see better and here's my two cents on it:
Class HSearchSortHelperImpl declares a map of default mapping between SortSpec's and ParameterTypeEnum. The test methodSource function does the same thing but stores the mappings in a stream instead of a map. so u have 2 declarations of pretty much the same stuff minus the optional. if someone adds to the map in the class, ur test suddenly does not account for the new value. someone would have to know that u have implemented the test and go look for it. that makes it a brittle test.

let's fix this.

  • u could make that map visible (public) and non-modifiable, there's no arm in exposing something that no one can mess with.
  • then build ur parameterized argument out of that map.
  • since u've spent already quite a bit of time on this, i 'll give u the starting pointers:
private static Stream<Arguments> provideArgumentsForGetParamType() {
		Stream.Builder<Arguments> retVal = Stream.builder();
		HSearchSortHelperImpl.ourSortingParamNameToParamType.forEach((theSortSpecName, theRestSearchParameterTypeEnum) ->
			{
				// ur code goes here
			});
		
		return retVal.build();
	}

Copy link
Collaborator

@epeartree epeartree left a comment

Choose a reason for hiding this comment

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

also, u'll need a changelog. ping me when u get to this.

@AbayomiE-T
Copy link
Author

also, u'll need a changelog. ping me when u get to this.

Right so I do have one on the CDR side but wasn't sure on how to go about the HAPI side since the bug was reported on CDR. Do I use the same ticket number for the .yaml file? Should it have the same content?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants