-
-
Notifications
You must be signed in to change notification settings - Fork 10.9k
Add Nice option to service #14936
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 Nice option to service #14936
Conversation
MikeMcQuaid
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR. Looking good so far!
| @run&.map(&:to_s) | ||
| end | ||
|
|
||
| sig { params(value: T.nilable(Integer)).returns(T.nilable(Integer)) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why/when would you want to pass in a value: nil?
| sig { params(value: T.nilable(Integer)).returns(T.nilable(Integer)) } | |
| sig { params(value: Integer).returns(T.nilable(Integer)) } |
may make more sense if not
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, we can remove nil but I was following the format of the rest of parameters like restart_delay which is also defined nilable
brew/Library/Homebrew/service.rb
Line 211 in 0d70ca7
| sig { params(value: T.nilable(Integer)).returns(T.nilable(Integer)) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CC @SMillerDev for thoughts here, I think it'd probably make sense to make none of these nilable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of these methods simply return the current value when nil (i.e. no argument) is passed. We don't seem to be calling any of these without an argument though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will remove the nil to also resolve the typecheck issue but we might want to also change the rest of parameters. Please verify that the change is correct.
Also if we remove the nilable, the TypeError is unrechable as it expects an integer. Should I remove the it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dduugg @reitermarkus Also would welcome your thoughts on how, in a future PR, we could refactor this type handling to lean more on Sorbet (bearing in mind that e.g. formulae will almost never be evaluated at runtime to use Sorbet and are currently never type checked by Sorbet)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think i have any especially creative suggestions. You can try to bump these files to typed: strict to catch more edge cases. I believe we do runtime typechecking in tests, so covering every service DSL in tests could do the trick. A rubocop that flags unacceptablenice values could help too (it's tricky if you're allowing vars to be passed to nice, but it could enforce that nice is followed by a literal Integer in the required range).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @dduugg!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CC @SMillerDev for thoughts here, I think it'd probably make sense to make none of these nilable.
Not a clue, pretty sure I just copied this from livecheck
revert table header Co-authored-by: Mike McQuaid <mike@mikemcquaid.com>
|
Thanks @jorpilo! Run Essentially it's saying the |
Library/Homebrew/service.rb
Outdated
| end | ||
|
|
||
| sig { params(value: Integer).returns(T.nilable(Integer)) } | ||
| def nice(value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| def nice(value) | |
| def nice(value = nil) |
Sorry, this bit is still needed and then then when nil below will also be needed.
We want users to be able to call nice() or nice(5) but not nice("5") or nice(nil).
Does that make sense?
Sorry for all the back and forth!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry it was my bad as I don't get the objective of calling nice() without a value?
calling nice() without value shouldn't add anything to the plist or unit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also if we want to preserve the nil default value we need to make the argument nilable or typecheck fails.
I have reverted back to be nilable. typecheck and style pass locally. Please let me know if there is any further modification needed
Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When would we want to call nice without arguments though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really see a reason why any of these methods would need to behave like a getter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I mentioned, you don't really want to call nice without arguments. Is there any other better way to get the value? if not, then I do not see the issue in keep it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, if you try to use it as a getter like the following example, it will return nil instead of 5
f = stub_formula do
service do
run opt_bin/"beanstalkd"
nice(5)
end
end
expect(f.service.nice).to eq(5)
# This fails as it returns nil instead of 5
if I do an instance_eval in the nice case, then it does return the correct value
when nil
instance_eval(&@service_block)
@nice
Signed-off-by: Jorge Pinilla López <jorpilo@gmail.com>
Signed-off-by: Jorge Pinilla López <jorpilo@gmail.com>
Signed-off-by: Jorge Pinilla López <jorpilo@gmail.com>
Signed-off-by: Jorge Pinilla López <jorpilo@gmail.com>
Library/Homebrew/service.rb
Outdated
| when nil | ||
| @nice | ||
| when Integer | ||
| if (T.must(value) < -20) || (T.must(value) > 19) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (T.must(value) < -20) || (T.must(value) > 19) | |
| unless (-20..19).cover?(nice) |
This is concise, and also lets you avoid the T.musts. (You could even extract the magic numbers into a const, e.g. NICE_RANGE = -20..19)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to use cover and NICE_RANGE. Thank you for the suggestion.
Any way I can use NICE_RANGE in the tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate on the issue in using NICE_RANGE in tests?
Library/Homebrew/service.rb
Outdated
| when nil | ||
| @nice | ||
| when Integer | ||
| if (T.must(value) < -20) || (T.must(value) > 19) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need sudo for negative nice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct, thank you for noticing. you do need root to run negative nice levels. If you try to run without root it will just run with nice level of 0 (no error will trigger).
You can run positive nice levels as user.
I can add a check for requires_root if the nice level is negative. Not sure if we should throw an error or just a warning. Also where would it best to set the check? at the nice function or when generating plist/units?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess a warning when you call brew services without sudo suffices here. But CC @SMillerDev and @MikeMcQuaid for thoughts here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is not something that should happen I think throwing an error is the best course of action.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems reasonable to truncate the nice level if you don't want to run brew services with sudo (which is what will happen automatically), though, so throwing an error seems a bit much here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe requires_root still allows you to run as a user, it'll just warn against doing so. So if we require that with the nice level you can still opt to have it truncated, brew will just suggest the fully functional option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like we should just have nice < 0 imply requires_root then, regardless of whether the service block includes it. Not sure what the value of forcing its inclusion by throwing an error is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would make it clear to developers and maintainers why it requires root. Instead of only telling users that they need to use root.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think an extra line that says require_root true is going to make the reason more transparent.
Signed-off-by: Jorge Pinilla López <jorpilo@gmail.com>
| @run&.map(&:to_s) | ||
| end | ||
|
|
||
| sig { params(value: T.nilable(Integer)).returns(T.nilable(Integer)) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will remove the nil to also resolve the typecheck issue but we might want to also change the rest of parameters. Please verify that the change is correct.
Also if we remove the nilable, the TypeError is unrechable as it expects an integer. Should I remove the it?
| options << "ExecStart=#{cmd}" | ||
|
|
||
| options << "Restart=always" if @keep_alive.present? && @keep_alive[:always].present? | ||
| options << "RestartSec=#{restart_delay}" if @restart_delay.present? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this correct or should it be the following:
| options << "RestartSec=#{restart_delay}" if @restart_delay.present? | |
| options << "RestartSec=#{@restart_delay}" if @restart_delay.present? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SMillerDev can confirm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ seems more consistent
Library/Homebrew/service.rb
Outdated
| end | ||
|
|
||
| sig { params(value: Integer).returns(T.nilable(Integer)) } | ||
| def nice(value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry it was my bad as I don't get the objective of calling nice() without a value?
calling nice() without value shouldn't add anything to the plist or unit.
Library/Homebrew/service.rb
Outdated
| end | ||
|
|
||
| sig { params(value: Integer).returns(T.nilable(Integer)) } | ||
| def nice(value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also if we want to preserve the nil default value we need to make the argument nilable or typecheck fails.
I have reverted back to be nilable. typecheck and style pass locally. Please let me know if there is any further modification needed
Thanks
Library/Homebrew/service.rb
Outdated
| when nil | ||
| @nice | ||
| when Integer | ||
| if (T.must(value) < -20) || (T.must(value) > 19) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct, thank you for noticing. you do need root to run negative nice levels. If you try to run without root it will just run with nice level of 0 (no error will trigger).
You can run positive nice levels as user.
I can add a check for requires_root if the nice level is negative. Not sure if we should throw an error or just a warning. Also where would it best to set the check? at the nice function or when generating plist/units?
Library/Homebrew/service.rb
Outdated
| when nil | ||
| @nice | ||
| when Integer | ||
| if (T.must(value) < -20) || (T.must(value) > 19) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to use cover and NICE_RANGE. Thank you for the suggestion.
Any way I can use NICE_RANGE in the tests?
Library/Homebrew/service.rb
Outdated
| end | ||
|
|
||
| sig { params(value: Integer).returns(T.nilable(Integer)) } | ||
| def nice(value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I mentioned, you don't really want to call nice without arguments. Is there any other better way to get the value? if not, then I do not see the issue in keep it
Library/Homebrew/service.rb
Outdated
| end | ||
|
|
||
| sig { params(value: Integer).returns(T.nilable(Integer)) } | ||
| def nice(value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, if you try to use it as a getter like the following example, it will return nil instead of 5
f = stub_formula do
service do
run opt_bin/"beanstalkd"
nice(5)
end
end
expect(f.service.nice).to eq(5)
# This fails as it returns nil instead of 5
if I do an instance_eval in the nice case, then it does return the correct value
when nil
instance_eval(&@service_block)
@nice
|
Also sorry for the late reply. I had all my comments as "pending" and I didn't realised I do need to accept the comments for them to be visible.... |
Co-authored-by: Douglas Eichelberger <dduugg@users.noreply.github.com>
| end | ||
| end | ||
|
|
||
| describe "#nice" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a bool check or something still?
| f = stub_formula do | ||
| service do | ||
| run opt_bin/"beanstalkd" | ||
| nice(-21) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| nice(-21) | |
| nice -21 |
Or does RuboCop complain about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah... syntax
|
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
Added service.nice to allow to define default nice levels in plist and systemd units.