I have a requirement to start and stop servers within rake tasks. Each server gets a specific process id. I have created a number of tasks that start and stop each server (note that the servers may not always be unique and will start on different ports, so its unreasonable that I grep/search for processes by name and kill those). I have been unsuccessful in programmatically maintaining state between tasks (either by environment variables, class methods, instance methods, local or global variables). It is also not possible for me (at least with my current setup) to use rake task dependencies, for example:
Rakefile.rb
class Proc
attr_accessor :process_id
def start_server(port=4444)
@process_id = spawn("node application -p #{port}", :chdir => "server_path")
end
end
@proc = Proc.new
task :start_server_one do |t, args|
@proc.start_server()
p @proc.process_id
end
task :stop_server_one => :start_server_one do
begin
Process.kill(9, @proc.process_id)
rescue => e
p e
end
end
On the command line I want to be able to run tasks at any given time, so I dont want the execution of one task to block any other tasks (hence the reason why Ive chosen spawn process). Unfortunately, this approach does not work.
On getting no luck with managing state between tasks my end solution was to use yaml files to serialise the process ids and remove them from the file as soon as I have killed the process successfully, similar to the following:
Initial yaml_file.yml contents:
---
server_one_process_id:
server_two_process_id:
server_three_process_id:
Rakefile contents:
require 'yaml'
yaml_file_path = 'yaml_file_path.yml'
all_yaml_contents = YAML::load_file(yaml_file_path)
class Proc
attr_accessor :process_id
def start_server(port=4444)
@process_id = spawn("node application -p #{port}", :chdir => "server_path")
end
end
@proc = Proc.new
task :start_server_one do |t, args|
@proc.start_server()
p 'server started!'
all_yaml_contents['server_one_process_id'] = @proc.process_id
File.open(yaml_file_path, 'w') {|f| f.write all_yaml_contents.to_yaml}
p @proc.process_id
end
task :stop_server_one do
all_yaml_contents_updated = YAML::load_file(yaml_file_path)
p "server process id: #{all_yaml_contents_updated['server_one_process_id']}"
Process.kill(9, all_yaml_contents_updated['server_one_process_id'])
all_yaml_contents_updated['server_one_process_id'] = nil
File.open(yaml_file_path, 'w') {|f| f.write all_yaml_contents_updated.to_yaml}
sleep 5
p 'server killed!'
end
Now I can run the tasks independently, for example on command line I can run:
rake start_server_one
#=> 'server started!'
#=> 12892
rake stop_server_one
#=> server process id: 12892
#=> server killed!
and be sure that the tasks execute and the server starts and stops as I expected as the yaml file is now updated with the process id for the given server.
However, to me at least, it seems as though this is not the best approach and I really want a purely programmatic way of managing state between tasks; or even a suitable library that can help me achieve this.