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

Extracted CircuitBreaker states into 3 structures #62

Merged
merged 1 commit into from
Nov 12, 2015

Conversation

kyewei
Copy link
Contributor

@kyewei kyewei commented Nov 10, 2015

Older closed PR is this: #56
Even older massive PR that we're trying to split is this (probably a bit outdated by this point): #54

Three structures are for holding the @success, @state, and @sliding_window of the CircuitBreaker class.

They are now under Semian::Simple, and future SysV implementation will be under Semian::SysV.

Issue that came up and may/may not have been addressed:

  • For methods in the classes that explicitly return self as the last line, its so things like #<< don't expose the inner array and leak the implementation, and instead return the appropriate wrapper class. Cascading still works: wrapper_class_instance << 1 << 2
  • The Atomic prefix was removed since it is misleading, and we probably won't be providing a Mutex or Monitor
  • it was suggested to rename the enum type from Semian::Simple::Enum to Semian::Simple::State and be specialized for the three possible items: :open, :closed, :half_open. Similarly, also rename from Integer to SuccessCount. I haven't changed it to those names yet, since it requires removing some code and makes some of the code a bit weird.
    • Pro: specialized, more simple
    • Con: naming would definitely be weird, even if the in-memory version from Simple stores the values directly, the SysV enum type delegates the shared-ness to the SysV integer type, and would need to keep a SysV::SuccessCount type in the SysV::State if we use those names.
  • A bit looking into the future, but with the SysV versions of the structure needing permissions and a name, Semian::Simple::SlidingWindow.new(max_size: 4) and Semian::SysV::SlidingWindow.new(max_size: 4, permissions: 0660, name: "sample_int") have different interfaces. Ways to solve
    • do def initialize(max_size: , **_)
    • do def initialize(options = {}) or something of the sort
    • not pass in permissions and name at all, but they have to come from somewhere else without leaking the implementation, possible from Semian.register
  • The enum class has an #increment because it was suggested that it could be used to iterate through the enums. May/may not be needed.
  • Slightly extraneous: it was previously mentioned that test suite naming is a bit off, for example TestCircuitBreaker is circuit_breaker_test.rb


def initialize(exceptions:, success_threshold:, error_threshold:, error_timeout:)
class CircuitBreaker #:nodoc:
def initialize(name, exceptions:, success_threshold:, error_threshold:, error_timeout:, type_namespace:)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not a fan of type_namespace IMO we should call this an implementation

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.

@byroot
Copy link
Contributor

byroot commented Nov 10, 2015

Just a few comments that I believe are minor. Otherwise LGTM.

@kyewei
Copy link
Contributor Author

kyewei commented Nov 11, 2015

@sirupsen any thoughts? The one bigger discussion would be this: #62 (diff)

@kyewei kyewei force-pushed the separate_cb_structures branch 3 times, most recently from d291681 to 32f68ad Compare November 11, 2015 15:23

def increment(val = 1)
@value = @allowed_symbols[(@allowed_symbols.index(@value) + val) % @allowed_symbols.size]
end
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this actually used? The only reason I suggested it before was because you inherited from the integer, since you don't do that anymore, I don't think you actually use 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.

It's not used in lib code. It is being tested.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you want to go back to a undef

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 might need SysV::Enum to inherit from SysV::Integer if byroot's suggestion goes through #62 (diff) because thats the only way it can be done if #value= disappears or goes private

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with @byroot's suggestion, which is in line with my comment above that this is not an implementation of an enumerator.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah. That's ok with me. You guys convinced me.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't envision how that'd happen. You always go straight from closed to half_open.

No you don't. That's the only transition that doesn't make sense.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also this never have been a validation....

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Too bad I can't just make a create_accessors_and_setters because of english: :closed vs #close. Otherwise I'd just do something like names.each { |name| define_method(name) { @value == name)}.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do we still want an #increment

assert_equal(sliding_window_1.last, sliding_window_2.last)
assert_equal(sliding_window_1.size, sliding_window_2.size)
assert_equal(sliding_window_1.max_size, sliding_window_2.max_size)
end
Copy link
Contributor

Choose a reason for hiding this comment

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

This should just be an array comparison.

Copy link
Contributor

Choose a reason for hiding this comment

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

You also never use this assertion.

@sirupsen
Copy link
Contributor

All my comments are smaller things, looking good Kye. After this iteration, I think it should be ready to go in. Then we'll deploy it to Shopify to make sure all is fine, and start working on the next small PR.

module Semian
module Simple
class Enum #:nodoc:
def initialize(symbol_list:)
Copy link
Contributor

Choose a reason for hiding this comment

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

I wouldn't make this argument named.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why not? Everything else is named already, like the max_size:

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, but it's so key to this class and no default makes sense. It doesn't matter much. Up to you.

@kyewei
Copy link
Contributor Author

kyewei commented Nov 11, 2015

Look over again, I suppose?

@sirupsen
Copy link
Contributor

LGTM

def value=(val)
raise ArgumentError unless @enums.include?(val)
@value = val
end
Copy link
Contributor

Choose a reason for hiding this comment

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

This method is unused.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So then, if I remove this test_will_throw_error_when_invalid_symbol_given will be gone as well? Also @enums is not needed either then

Copy link
Contributor

Choose a reason for hiding this comment

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

Yup. No need to test a method that is not used. Just remove the method and the test althogether.

@byroot
Copy link
Contributor

byroot commented Nov 11, 2015

One last concern (unused method). Once it's solved 🐑

@kyewei
Copy link
Contributor Author

kyewei commented Nov 11, 2015

Alright, I added @byroot 's suggestion and squashed into one commit. @sirupsen suggested writing an appropriate PR for testing in production before merging it in here.

@sirupsen
Copy link
Contributor

I'd say merge this :)

kyewei added a commit that referenced this pull request Nov 12, 2015
Extracted CircuitBreaker states into 3 structures
@kyewei kyewei merged commit bad6820 into master Nov 12, 2015
@kyewei kyewei deleted the separate_cb_structures branch November 12, 2015 15:36
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.

3 participants