Merge pull request #12367 from SMillerDev/feature/service/interval

Service: add interval support
This commit is contained in:
Sean Molenaar 2021-11-08 16:24:19 +01:00 committed by GitHub
commit ca7623c70f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 93 additions and 27 deletions

View File

@ -9,14 +9,14 @@ module Homebrew
extend T::Sig
extend Forwardable
RUN_TYPE_IMMEDIATE = "immediate"
RUN_TYPE_INTERVAL = "interval"
RUN_TYPE_CRON = "cron"
RUN_TYPE_IMMEDIATE = :immediate
RUN_TYPE_INTERVAL = :interval
RUN_TYPE_CRON = :cron
PROCESS_TYPE_BACKGROUND = "background"
PROCESS_TYPE_STANDARD = "standard"
PROCESS_TYPE_INTERACTIVE = "interactive"
PROCESS_TYPE_ADAPTIVE = "adaptive"
PROCESS_TYPE_BACKGROUND = :background
PROCESS_TYPE_STANDARD = :standard
PROCESS_TYPE_INTERACTIVE = :interactive
PROCESS_TYPE_ADAPTIVE = :adaptive
# sig { params(formula: Formula).void }
def initialize(formula, &block)
@ -124,35 +124,47 @@ module Homebrew
end
end
sig { params(type: T.nilable(String)).returns(T.nilable(String)) }
def process_type(type = nil)
case T.unsafe(type)
sig { params(value: T.nilable(Symbol)).returns(T.nilable(Symbol)) }
def process_type(value = nil)
case T.unsafe(value)
when nil
@process_type
when PROCESS_TYPE_BACKGROUND, PROCESS_TYPE_STANDARD, PROCESS_TYPE_INTERACTIVE, PROCESS_TYPE_ADAPTIVE
@process_type = type.to_s
when String
when :background, :standard, :interactive, :adaptive
@process_type = value
when Symbol
raise TypeError, "Service#process_type allows: "\
"'#{PROCESS_TYPE_BACKGROUND}'/'#{PROCESS_TYPE_STANDARD}'/"\
"'#{PROCESS_TYPE_INTERACTIVE}'/'#{PROCESS_TYPE_ADAPTIVE}'"
else
raise TypeError, "Service#process_type expects a String"
raise TypeError, "Service#process_type expects a Symbol"
end
end
sig { params(type: T.nilable(T.any(String, Symbol))).returns(T.nilable(String)) }
def run_type(type = nil)
case T.unsafe(type)
sig { params(value: T.nilable(Symbol)).returns(T.nilable(Symbol)) }
def run_type(value = nil)
case T.unsafe(value)
when nil
@run_type
when "immediate", :immediate
@run_type = type.to_s
when RUN_TYPE_INTERVAL, RUN_TYPE_CRON
raise TypeError, "Service#run_type does not support timers"
when String
when :immediate, :interval
@run_type = value
when :cron
raise TypeError, "Service#run_type does not support cron"
when Symbol
raise TypeError, "Service#run_type allows: '#{RUN_TYPE_IMMEDIATE}'/'#{RUN_TYPE_INTERVAL}'/'#{RUN_TYPE_CRON}'"
else
raise TypeError, "Service#run_type expects a string"
raise TypeError, "Service#run_type expects a Symbol"
end
end
sig { params(value: T.nilable(Integer)).returns(T.nilable(Integer)) }
def interval(value = nil)
case T.unsafe(value)
when nil
@interval
when Integer
@interval = value
else
raise TypeError, "Service#interval expects an Integer"
end
end
@ -205,16 +217,18 @@ module Homebrew
# @return [String]
sig { returns(String) }
def to_plist
# command needs to be first because it initializes all other values
base = {
Label: @formula.plist_name,
RunAtLoad: @run_type == RUN_TYPE_IMMEDIATE,
ProgramArguments: command,
RunAtLoad: @run_type == RUN_TYPE_IMMEDIATE,
}
base[:KeepAlive] = @keep_alive if @keep_alive == true
base[:LegacyTimers] = @macos_legacy_timers if @macos_legacy_timers == true
base[:TimeOut] = @restart_delay if @restart_delay.present?
base[:ProcessType] = @process_type.capitalize if @process_type.present?
base[:ProcessType] = @process_type.to_s.capitalize if @process_type.present?
base[:StartInterval] = @interval if @interval.present? && @run_type == RUN_TYPE_INTERVAL
base[:WorkingDirectory] = @working_dir if @working_dir.present?
base[:RootDirectory] = @root_dir if @root_dir.present?
base[:StandardInPath] = @input_path if @input_path.present?

View File

@ -32,6 +32,28 @@ describe Homebrew::Service do
end
end
describe "#run_type" do
it "throws for cron type" do
f.class.service do
run opt_bin/"beanstalkd"
run_type :cron
end
expect { f.service.manual_command }.to raise_error TypeError, "Service#run_type does not support cron"
end
it "throws for unexpected type" do
f.class.service do
run opt_bin/"beanstalkd"
run_type :cow
end
expect {
f.service.manual_command
}.to raise_error TypeError, "Service#run_type allows: 'immediate'/'interval'/'cron'"
end
end
describe "#manual_command" do
it "returns valid manual_command" do
f.class.service do
@ -76,8 +98,9 @@ describe Homebrew::Service do
root_dir var
working_dir var
keep_alive true
process_type "interactive"
process_type :interactive
restart_delay 30
interval 5
macos_legacy_timers true
end
@ -154,6 +177,35 @@ describe Homebrew::Service do
EOS
expect(plist).to eq(plist_expect)
end
it "returns valid interval plist" do
f.class.service do
run opt_bin/"beanstalkd"
run_type :interval
interval 5
end
plist = f.service.to_plist
plist_expect = <<~EOS
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
\t<key>Label</key>
\t<string>homebrew.mxcl.formula_name</string>
\t<key>ProgramArguments</key>
\t<array>
\t\t<string>#{HOMEBREW_PREFIX}/opt/formula_name/bin/beanstalkd</string>
\t</array>
\t<key>RunAtLoad</key>
\t<false/>
\t<key>StartInterval</key>
\t<integer>5</integer>
</dict>
</plist>
EOS
expect(plist).to eq(plist_expect)
end
end
describe "#to_systemd_unit" do
@ -168,7 +220,7 @@ describe Homebrew::Service do
root_dir var
working_dir var
keep_alive true
process_type "interactive"
process_type :interactive
restart_delay 30
macos_legacy_timers true
end