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

Customized FHIR service configuration exceptions #150

Merged
merged 15 commits into from
Jan 22, 2022

Conversation

kyclai
Copy link
Contributor

@kyclai kyclai commented Dec 8, 2021

Added custom exceptions for the following scenarios:

  • Invalid FHIR service URL (e.g. not a URL for a FHIR server URL, not an absolute URL, etc.)
  • Unauthorized access to create/update FHIR resources (i.e. FHIR Data Writer role is missing)

Also renamed "FhirServerError" to "FhirServiceError" for consistency with product name "FHIR service".

@kyclai kyclai requested a review from a team as a code owner December 8, 2021 22:11
case MsalServiceException _:
string errorCode = ((MsalServiceException)exception).ErrorCode;
message = FhirResources.FhirServiceMsalServiceError;
errorName = $"{nameof(FhirServiceErrorCode.ConfigurationError)}_{errorCode}";
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be auth error instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From my testing, no, because MsalServiceException was given for invalid FHIR service URLs such as https://clai1015.azurehealthcareapis.com/metadata, https://clai1015.azurehealthcareapis.com///, https://sdfsldfkwr389lksnldsf.com

In commit 9ab3837, I've scoped MsalServiceException down by checking the ErrorCode property.

try
{
client = new FhirClient(url, fhirClientSettings, new BearerTokenAuthorizationMessageHandler(uri, tokenCredential, logger));
FhirServiceValidator.ValidateFhirService(client, logger);
Copy link
Contributor

Choose a reason for hiding this comment

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

So currently if this fails, we just log the exception and return false, so what happens in the rest of the execution flow in that case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this case (when ValidateFhirService catches an exception, gets the exception logged, and returns false), FhirClient is returned (Line 90), as before these code changes.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure but I was trying to understand that if this validation failed and we still returned the client, then what happens in the ingestion flow? Do we encounter other exceptions that block the ingestion?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As discussed offline, what happens when an invalid client is returned is something to further investigate later. For now, the previous behaviour is still retained: a client, whether valid or not, gets returned.

{
_ = await SaveObservationAsync(config, grp, ids).ConfigureAwait(false);
FhirServiceExceptionProcessor.ProcessException(ex, _logger);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should retain the previous behaviour and not eat the exception?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just clarifying - do you mean to wrap only the line with ResolveResourceIdentitiesAsync in the try-block, so that the other lines are still executed if we do get an exception thrown (for an authorization error) from ResolveResourceIdentitiesAsync?

Copy link
Contributor

Choose a reason for hiding this comment

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

To retain the previous behaviour where this function would throw if we encountered an exception, we can just throw it back after processing the exception. Unless we feel like throwing it back doesn't make sense anymore? I'm worried that if we were previously retrying on this exception, then by eating the exception now, we will not be and if that is desired.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh I see what you mean, thanks for the details. I think you bring up a good point; I'll re-throw while keeping the stack trace.

m.Dimensions[DimensionNames.Operation].Equals(ConnectorOperation.FHIRConversion) &&
m.Dimensions[DimensionNames.Category].Equals(Category.Errors) &&
m.Dimensions[DimensionNames.ErrorType].Equals(ErrorType.FHIRServiceError) &&
m.Dimensions[DimensionNames.ErrorSeverity].Equals(ErrorSeverity.Critical) &&
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Maybe this can go into a separate method like ValidateFHIRServiceErrorProperteies() similar to a recent change you made in the other test file.

@kyclai kyclai merged commit 6b160d7 into master Jan 22, 2022
@kyclai kyclai deleted the personal/clai/fhir-exceptions branch January 22, 2022 02:20
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