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

Add reload on empty or missing key #129

Merged

Conversation

andrewvk
Copy link
Contributor

No description provided.

@CLAassistant
Copy link

CLAassistant commented May 25, 2022

CLA assistant check
All committers have signed the CLA.

@@ -156,7 +156,7 @@ private async Task PollingLoop(CancellationToken cancellationToken)

private void SetData(QueryResult<KVPair[]> result)
{
Data = result.ToConfigDictionary(_source.ConvertConsulKVPairToConfig);
Data = result.HasValue() ? result.ToConfigDictionary(_source.ConvertConsulKVPairToConfig) : null;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we need to include a check here and only set Data to null when _source.IsOptional. Otherwise we'll be unsetting required data which I think is different to the design of the other configuration providers.

It's a bit of a pain because we'll end up duplicating some of the checking that happens in the initial DoLoad. This isn't a big problem, but one potential solution would be to make this method return bool to indicate whether it was able to update the Data or not and then in DoLoad throw if setting fails (because the data was missing and required).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you look at the code, unlike FileConfigurationProvider, DoLoad is called only in case of initial loading. And there is a check for HasValue. And at reload another code is called. So the check inside SetData is redundant.

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 will try to do some refactoring to simplify the code.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sorry, I'm not sure if my first comment was clear as I think we're both in agreement that DoLoad is only called once when it first loads and then PollingLoop is responsible for monitoring for changes and reloading.

What I was referring to is the fact that in PollingLoop we need to make sure that don't set Data to null if result.HasValue() is false and _source.IsOptional is false. So we need something similar to the code that's in DoLoad but it shouldn't throw in the case when the result doesn't have a value and it is required, it should just silently ignore this and leave the Data as it was.

Copy link
Contributor Author

@andrewvk andrewvk May 25, 2022

Choose a reason for hiding this comment

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

OK. I think the best approach (in terms of code size and complexity) would be to just inline the SetData method and add null logic only to the PollingLoop version. This will eliminate unnecessary returns and checks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Made the commit

{
SetData(result);
Data = result.HasValue() ? result.ToConfigDictionary(_source.ConvertConsulKVPairToConfig) : null;
Copy link
Collaborator

Choose a reason for hiding this comment

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

So yes I think inlining this is better, nice idea. I think we just need to make one more change here now to make this correct. I think it should be:

Data = result.HasValue()
    ? result.ToConfigDictionary(_source.ConvertConsulKVPairToConfig)
    : _source.Optional
        ? null
        : Data;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not the behavior that FileConfigurationProvider has. There, even with optional=false, deleting a file will remove the values from it in IConfiguration. And in this code, when the key is deleted, the values will remains.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah right, that is the source of the confusion then. I was under the impression that old data should remain if it is not optional and is missing on a reload.

Copy link
Collaborator

Choose a reason for hiding this comment

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

One final observation from me. In FileConfigurationProvider it sets Data to an empty dictionary when the value is missing. We should probably do the same here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Another difference is that FIleConfigurationProvider uses the OrdinalIgnoreCase comparer:
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
Should we do the same?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes. We do actually create the dictionary with StringComparer.OrdinalIgnoreCase in the result.ToConfigDictionary extension method. So I don't think it matters too much what we do in the empty case as I don't the comparer will be used, but good to be consistent.

Copy link
Collaborator

Choose a reason for hiding this comment

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

In fact, if you call result.ToConfigDictionary with a result that doesn't have any data then it should already do the right thing and create an empty dictionary.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Which means we can just write

Data = result.ToConfigDictionary(_source.ConvertConsulKVPairToConfig);

@Choc13
Copy link
Collaborator

Choc13 commented May 25, 2022

LGTM. I'm not longer an admin on this repo, but I'll ask someone who is to kick off the build and then merge it if that passes. Thanks for taking the time to fix this.

@baileydoestech baileydoestech merged commit 03f942d into wintoncode:master May 31, 2022
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.

4 participants