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

Plat stop breakpoints causing timeouts #41

Merged
merged 15 commits into from
Jul 20, 2015

Conversation

lewislabs
Copy link
Contributor

Commands now have the facility to ignore the timeouts. This should make it easier to debug Command decorated methods.

Ignoring timeouts can either be configured using the CommandAttribute constructor (in Hudl.Mjonir.Attributes), or using a ConfigurableValue (for system wide ignoring of timeouts).


// See Mjolnir's Command constructors.
public CommandAttribute(string group, string isolationKey, int timeout = DefaultTimeout) : this(group, isolationKey, isolationKey, timeout) { }

public CommandAttribute(string group, string isolationKey, bool ignoreTimeout)
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've added this extra constructor to allow for setting specific Command calls to ignore timeouts. Is this wise? Do we want to expose this feature?

Copy link
Member

Choose a reason for hiding this comment

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

I don't think we do - ignoring timeouts seems like a conditional thing, so to have it baked into the attribute permanently feels odd.

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'll be honest, part of the reason for me doing this was to make testing a little bit easier. But I can take it out and just use an injected ConfigurationProvider, as is done in the current set of tests.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I think that's the way to go - it'll more align the tests with how the library is supposed to behave (i.e. driven by the config value). If we have to go this route, I think we'd want this constructor to be internal so that it's not part of the public API.

…orking some of the code to adjust for that. Tests are broken at this time and need some rework.

namespace Hudl.Mjolnir.Tests.Command.Attribute
{
public sealed class NewCommandAttributeAndProxyTestsIgnoringTimeouts : TestFixtureIgnoreTimeouts
Copy link
Member

Choose a reason for hiding this comment

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

The TestFixtureIgnoreTimeouts caught me here - I was reading through the tests and said to myself, "it looks like these aren't actually using the ignoreTimeouts property", and I stumbled upon how it was used later. What are your thoughts on bringing the config value closer to the tests here? It feels too disconnected to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can do that, just means running the TestFixtureIgnoreTimeouts and TestFixture constructor logic at the start of each test.
A lot of changes but In the spirit of the xunit philosophy maybe we should do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@robhruska Having started to move this logic to the start of each of the ~160 tests, I'm starting to think it's better where it is in the constructor. Here's my reason;

In each test, since we don't know what other tests may have done to the ConfigProvider, we have to initialise all of the possible keys. e.g. in a test where we're not looking to test anything related to the ignoreTimeouts functionality we still need to start the test off with a

ConfigProviderContext.Instance.SetConfigValue(ConfigProviderContext.IgnoreTimeoutsKey, false);

This seems like code bloat, and is perhaps more confusing than having it all in one place?
It also makes it tricky if we end up adding another config value to the tests!

Copy link
Member

Choose a reason for hiding this comment

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

In each test, since we don't know what other tests may have done to the ConfigProvider

If we assume that other tests appropriately tore themselves down, is that enough?

we still need to start the test off with a ...

If we can assume a sane config state, and the config value defaults to false, we should only have to add it to cases where we want to set it with a true value.

Thoughts there?

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'm thinking that relying on assumptions in a unit test for it to pass, is a little bit flawed. Also if one test forgets to tear down properly then finding where that is could be more tricky.

But on the other hand if we actually changed the default values for config inside of mjolnir in the future, then I would hope a bunch of failing tests would be enough for someone to reconsider what they're doing. This is probably the biggest benefit so I'll go with the approach of just setting values where they are needed and assuming that the world is otherwise configured using defaults.

_log.DebugFormat("Timeout configuration override for this command of {0}",timeout);
//I think it is sensible to apply this timeout to the command if it has been explicitly set in configuration.
//Therefore setting TimeoutsFullyDisabled to false regardless
TimeoutsIgnored = false;
Copy link
Member

Choose a reason for hiding this comment

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

This feels a little hidden to me. As a user of the library, if I set mjolnir.ignoreTimeouts=True, that feels like a pretty assertive thing (like, I expect it to ignore all timeouts). If I were to set the config to True and still encounter a timeout, I'd be confused. Additionally, in local development, I'm almost positive that we have 0 people with per-command timeouts configured, so I'm not sure there's much of a problem to address by doing this.

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 guess ignoreTimeouts should be fully self explanatory. I was in two minds as to what I was going to do with these per command timeouts. My thought was that it may give users the ability to apply the blanket ignore first, then if they were interested in tweaking the timeout for a particular command they could just work with the per-command config.
I guess since the per-command config overrides the default anyway you can still get the same use case.

I'll change it.

@@ -169,7 +177,8 @@ internal Command(string group, string name, string breakerKey, string poolKey, T
throw new ArgumentNullException("poolKey");
}

if (defaultTimeout.TotalMilliseconds <= 0)
TimeoutsIgnored = IgnoreCommandTimeouts.Value;
if (!TimeoutsIgnored && defaultTimeout.TotalMilliseconds <= 0)
Copy link
Member

Choose a reason for hiding this comment

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

Technically I don't think we need to check the ignored flag here - the default timeout's often going to get passed from a constant or hard-coded value, so it should be valid.

In fact, thinking about it more, I'd lobby to always validate the default timeout here, because otherwise, if timeouts are ignored, invalid default timeout values might go unnoticed in development.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's true! I think there's actually a test which looks at this. It will give a false positive in the case where ignoredTimeouts is true and the timeout is <=0

/// This is likely to be useful when debugging Command decorated methods, however it is not advisable to use in a production environment since it disables
/// some of Mjolnir's key features.
/// </summary>
protected static readonly ConfigurableValue<bool> IgnoreCommandTimeouts = new ConfigurableValue<bool>("mjolnir.ignoreTimeouts", false);

Choose a reason for hiding this comment

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

with Mjolnir being open source are we ok referencing ConfigurableValue

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, we've got a version of Hudl.Config that's published to nuget.org

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 haven't made any changes to mjolnir's references

lewislabs added a commit that referenced this pull request Jul 20, 2015
@lewislabs lewislabs merged commit c93ee9e into master Jul 20, 2015
@robhruska robhruska deleted the Plat-StopBreakpointsCausingTimeouts branch July 20, 2015 15:48
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.

None yet

3 participants